2022-03-26 19:49:04 +01:00
|
|
|
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 {
|
2022-08-05 16:23:44 +02:00
|
|
|
token, err := s.Token(true, func(rune) bool { return true })
|
2022-03-26 19:49:04 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return t.Set(string(token))
|
|
|
|
}
|