package chlog import ( "fmt" "regexp" "strconv" "time" ) var durationRe = regexp.MustCompile(`^(\d+)([smhdw])$`) var durationUnits = map[string]time.Duration{ "s": time.Second, "m": time.Minute, "h": time.Hour, "d": 24 * time.Hour, "w": 7 * 24 * time.Hour, } // ParseTimeSpec accepts a relative duration (15m, 1h, 2d, 1w) meaning "that // long before now", or an absolute RFC3339 timestamp. func ParseTimeSpec(spec string, now time.Time) (time.Time, error) { if spec == "" { return time.Time{}, fmt.Errorf("empty time spec") } if m := durationRe.FindStringSubmatch(spec); m != nil { n, err := strconv.ParseInt(m[1], 10, 64) if err != nil { return time.Time{}, fmt.Errorf("invalid duration %q: %w", spec, err) } return now.Add(-time.Duration(n) * durationUnits[m[2]]), nil } t, err := time.Parse(time.RFC3339, spec) if err != nil { return time.Time{}, fmt.Errorf("invalid time %q: use a duration (15m, 1h, 2d) or RFC3339", spec) } return t.UTC(), nil }