package main import ( "errors" "time" ) type TimeComponent struct { TS *string `parser:"@Time"` } func (t TimeComponent) Time(loc *time.Location) (time.Time, error) { return time.ParseInLocation("15:04:05", *t.TS, loc) } func (t TimeComponent) RequiresRefreshing() bool { return false } type TimeInZoneComponent struct { TS *string `parser:"@Time"` InUTC bool `parser:"@Z?"` } func (t TimeInZoneComponent) Time() (time.Time, error) { loc := time.Local if t.InUTC { loc = time.UTC } return time.ParseInLocation("15:04:05", *t.TS, loc) } func (t TimeInZoneComponent) RequiresRefreshing() bool { return false } type DateWithTimeComponents struct { Date *string `parser:"@Date"` MaybeTime *TimeComponent `parser:"(T? @@)?"` InUTC bool `parser:"(@Z)?"` } func (d DateWithTimeComponents) Time() (time.Time, error) { loc := time.Local if d.InUTC { loc = time.UTC } t, err := time.ParseInLocation("2006-01-02", *d.Date, loc) if err != nil { return time.Time{}, err } if d.MaybeTime != nil { tt, err := d.MaybeTime.Time(loc) if err != nil { return time.Time{}, err } t = time.Date(t.Year(), t.Month(), t.Day(), tt.Hour(), tt.Minute(), tt.Second(), 0, loc) } return t, nil } type Timestamp struct { DT *DateWithTimeComponents `parser:"@@"` TimeToday *TimeInZoneComponent `parser:" | @@"` Int *int `parser:" | @Int"` } func (t Timestamp) Time() (time.Time, error) { switch { case t.DT != nil: return t.DT.Time() case t.TimeToday != nil: tt, err := t.TimeToday.Time() if err != nil { return time.Time{}, err } today := time.Now().In(tt.Location()) return time.Date(today.Year(), today.Month(), today.Day(), tt.Hour(), tt.Minute(), tt.Second(), tt.Nanosecond(), tt.Location()), nil } return time.Unix(int64(*t.Int), 0), nil } func (t Timestamp) RequiresRefreshing() bool { return false } type Atom struct { Timestamp *Timestamp `parser:"@@"` Identifier *string `parser:" | @Identifier"` } func (a Atom) Time() (time.Time, error) { switch { case a.Timestamp != nil: return a.Timestamp.Time() case a.Identifier != nil: if *a.Identifier == "now" { return time.Now(), nil } return time.Time{}, errors.New("unknown identifier") } return time.Time{}, errors.New("unhandled case") } func (a Atom) RequiresRefreshing() bool { switch { case a.Timestamp != nil: return a.Timestamp.RequiresRefreshing() case a.Identifier != nil: if *a.Identifier == "now" { return true } return false } return false }