package duration import ( "math" "strconv" "strings" "time" "github.com/spf13/pflag" ) type Duration time.Duration const DurationOff = Duration((1 << 63) - 1) func (d *Duration) String() string { if *d == DurationOff { return "off" } ageSuffix := &ageSuffixes[0] if math.Abs(float64(*d)) >= float64(ageSuffix.Multiplier) { timeUnits := float64(*d) / float64(ageSuffix.Multiplier) return strconv.FormatFloat(timeUnits, 'f', -1, 64) + ageSuffix.Suffix } return time.Duration(*d).String() } func (d *Duration) Set(s string) error { v, err := parseDuration(s) *d = Duration(v) return err } var ageSuffixes = []struct { Suffix string Multiplier time.Duration }{ {Suffix: "d", Multiplier: time.Hour * 24}, {Suffix: "w", Multiplier: time.Hour * 24 * 7}, {Suffix: "M", Multiplier: time.Hour * 24 * 30}, {Suffix: "y", Multiplier: time.Hour * 24 * 365}, {Suffix: "", Multiplier: time.Second}, } func parseDurationSuffixes(age string) (time.Duration, error) { var period float64 for _, ageSuffix := range ageSuffixes { if strings.HasSuffix(age, ageSuffix.Suffix) { numberString := age[:len(age)-len(ageSuffix.Suffix)] var err error period, err = strconv.ParseFloat(numberString, 64) if err != nil { return time.Duration(0), err } period *= float64(ageSuffix.Multiplier) break } } return time.Duration(period), nil } func parseDurationFromNow(age string) (d time.Duration, err error) { if age == "off" { return time.Duration(DurationOff), nil } d, err = time.ParseDuration(age) if err == nil { return d, nil } d, err = parseDurationSuffixes(age) if err == nil { return d, nil } return d, err } func newDurationValue(val time.Duration, p *time.Duration) *Duration { *p = val return (*Duration)(p) } func DurationVar(f *pflag.FlagSet, p *time.Duration, name string, value time.Duration, usage string) { f.VarP(newDurationValue(value, p), name, "", usage) } func parseDuration(age string) (time.Duration, error) { return parseDurationFromNow(age) } func (d *Duration) Type() string { return "Duration" }