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
This commit is contained in:
Nick Craig-Wood 2022-08-05 15:23:44 +01:00
parent ebe86c6cec
commit 16039b350d
4 changed files with 42 additions and 17 deletions

View File

@ -126,7 +126,7 @@ func parseDurationFromNow(age string, getNow func() time.Time) (d time.Duration,
// ParseDuration parses a duration string. Accept ms|s|m|h|d|w|M|y suffixes. Defaults to second if not provided // ParseDuration parses a duration string. Accept ms|s|m|h|d|w|M|y suffixes. Defaults to second if not provided
func ParseDuration(age string) (time.Duration, error) { func ParseDuration(age string) (time.Duration, error) {
return parseDurationFromNow(age, time.Now) return parseDurationFromNow(age, timeNowFunc)
} }
// ReadableString parses d into a human-readable duration. // ReadableString parses d into a human-readable duration.
@ -216,7 +216,7 @@ func (d *Duration) UnmarshalJSON(in []byte) error {
// Scan implements the fmt.Scanner interface // Scan implements the fmt.Scanner interface
func (d *Duration) Scan(s fmt.ScanState, ch rune) error { func (d *Duration) Scan(s fmt.ScanState, ch rune) error {
token, err := s.Token(true, nil) token, err := s.Token(true, func(rune) bool { return true })
if err != nil { if err != nil {
return err return err
} }

View File

@ -145,11 +145,28 @@ func TestDurationReadableString(t *testing.T) {
} }
func TestDurationScan(t *testing.T) { func TestDurationScan(t *testing.T) {
var v Duration now := time.Date(2020, 9, 5, 8, 15, 5, 250, time.UTC)
n, err := fmt.Sscan(" 17m ", &v) oldTimeNowFunc := timeNowFunc
require.NoError(t, err) timeNowFunc = func() time.Time { return now }
assert.Equal(t, 1, n) defer func() { timeNowFunc = oldTimeNowFunc }()
assert.Equal(t, Duration(17*60*time.Second), v)
for _, test := range []struct {
in string
want Duration
}{
{"17m", Duration(17 * time.Minute)},
{"-12h", Duration(-12 * time.Hour)},
{"0", Duration(0)},
{"off", DurationOff},
{"2022-03-26T17:48:19Z", Duration(now.Sub(time.Date(2022, 03, 26, 17, 48, 19, 0, time.UTC)))},
{"2022-03-26 17:48:19", Duration(now.Sub(time.Date(2022, 03, 26, 17, 48, 19, 0, time.Local)))},
} {
var got Duration
n, err := fmt.Sscan(test.in, &got)
require.NoError(t, err)
assert.Equal(t, 1, n)
assert.Equal(t, test.want, got)
}
} }
func TestParseUnmarshalJSON(t *testing.T) { func TestParseUnmarshalJSON(t *testing.T) {

View File

@ -83,7 +83,7 @@ func (t *Time) UnmarshalJSON(in []byte) error {
// Scan implements the fmt.Scanner interface // Scan implements the fmt.Scanner interface
func (t *Time) Scan(s fmt.ScanState, ch rune) error { func (t *Time) Scan(s fmt.ScanState, ch rune) error {
token, err := s.Token(true, nil) token, err := s.Token(true, func(rune) bool { return true })
if err != nil { if err != nil {
return err return err
} }

View File

@ -93,15 +93,23 @@ func TestTimeScan(t *testing.T) {
timeNowFunc = func() time.Time { return now } timeNowFunc = func() time.Time { return now }
defer func() { timeNowFunc = oldTimeNowFunc }() defer func() { timeNowFunc = oldTimeNowFunc }()
var v1, v2, v3, v4, v5 Time for _, test := range []struct {
n, err := fmt.Sscan(" 17m -12h 0 off 2022-03-26T17:48:19Z ", &v1, &v2, &v3, &v4, &v5) in string
require.NoError(t, err) want Time
assert.Equal(t, 5, n) }{
assert.Equal(t, Time(now.Add(-17*time.Minute)), v1) {"17m", Time(now.Add(-17 * time.Minute))},
assert.Equal(t, Time(now.Add(12*time.Hour)), v2) {"-12h", Time(now.Add(12 * time.Hour))},
assert.Equal(t, Time(now), v3) {"0", Time(now)},
assert.Equal(t, Time(time.Time{}), v4) {"off", Time(time.Time{})},
assert.Equal(t, Time(time.Date(2022, 03, 26, 17, 48, 19, 0, time.UTC)), v5) {"2022-03-26T17:48:19Z", Time(time.Date(2022, 03, 26, 17, 48, 19, 0, time.UTC))},
{"2022-03-26 17:48:19", Time(time.Date(2022, 03, 26, 17, 48, 19, 0, time.Local))},
} {
var got Time
n, err := fmt.Sscan(test.in, &got)
require.NoError(t, err)
assert.Equal(t, 1, n)
assert.Equal(t, test.want, got)
}
} }
func TestParseTimeUnmarshalJSON(t *testing.T) { func TestParseTimeUnmarshalJSON(t *testing.T) {