rclone/fs/parsetime.go
Nick Craig-Wood 16039b350d fs: fix parsing of times and durations of the form "YYYY-MM-DD HH:MM:SS"
Before this fix, the parsing code gave an error like this

    parsing "2022-08-02 07:00:00" as fs.Time failed: expected newline

This was due to the Scan call failing to read all the data.

This patch fixes that, and redoes the tests
2022-08-05 16:45:23 +01:00

92 lines
1.6 KiB
Go

package fs
import (
"encoding/json"
"fmt"
"time"
)
// Time is a time.Time with some more parsing options
type Time time.Time
// For overriding in unittests.
var (
timeNowFunc = time.Now
)
// Turn Time into a string
func (t Time) String() string {
if !t.IsSet() {
return "off"
}
return time.Time(t).Format(time.RFC3339Nano)
}
// IsSet returns if the time is not zero
func (t Time) IsSet() bool {
return !time.Time(t).IsZero()
}
// ParseTime parses a time or duration string as a Time.
func ParseTime(date string) (t time.Time, err error) {
if date == "off" {
return time.Time{}, nil
}
now := timeNowFunc()
// Attempt to parse as a text time
t, err = parseTimeDates(date)
if err == nil {
return t, nil
}
// Attempt to parse as a time.Duration offset from now
d, err := time.ParseDuration(date)
if err == nil {
return now.Add(-d), nil
}
d, err = parseDurationSuffixes(date)
if err == nil {
return now.Add(-d), nil
}
return t, err
}
// Set a Time
func (t *Time) Set(s string) error {
parsedTime, err := ParseTime(s)
if err != nil {
return err
}
*t = Time(parsedTime)
return nil
}
// Type of the value
func (t Time) Type() string {
return "Time"
}
// UnmarshalJSON makes sure the value can be parsed as a string in JSON
func (t *Time) UnmarshalJSON(in []byte) error {
var s string
err := json.Unmarshal(in, &s)
if err != nil {
return err
}
return t.Set(s)
}
// Scan implements the fmt.Scanner interface
func (t *Time) Scan(s fmt.ScanState, ch rune) error {
token, err := s.Token(true, func(rune) bool { return true })
if err != nil {
return err
}
return t.Set(string(token))
}