From ef6e53bb5f521e4d400849b79bc72e89fe2a7484 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Mon, 11 May 2020 18:41:11 -0400 Subject: core: Add support for `d` duration unit (#3323) * caddy: Add support for `d` duration unit * Improvements to ParseDuration; add unit tests Co-authored-by: Matthew Holt --- caddy.go | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'caddy.go') diff --git a/caddy.go b/caddy.go index 00a56e7..1184bc9 100644 --- a/caddy.go +++ b/caddy.go @@ -486,7 +486,7 @@ func Validate(cfg *Config) error { // Duration can be an integer or a string. An integer is // interpreted as nanoseconds. If a string, it is a Go // time.Duration value such as `300ms`, `1.5h`, or `2h45m`; -// valid units are `ns`, `us`/`µs`, `ms`, `s`, `m`, and `h`. +// valid units are `ns`, `us`/`µs`, `ms`, `s`, `m`, `h`, and `d`. type Duration time.Duration // UnmarshalJSON satisfies json.Unmarshaler. @@ -497,7 +497,7 @@ func (d *Duration) UnmarshalJSON(b []byte) error { var dur time.Duration var err error if b[0] == byte('"') && b[len(b)-1] == byte('"') { - dur, err = time.ParseDuration(strings.Trim(string(b), `"`)) + dur, err = ParseDuration(strings.Trim(string(b), `"`)) } else { err = json.Unmarshal(b, &dur) } @@ -505,6 +505,34 @@ func (d *Duration) UnmarshalJSON(b []byte) error { return err } +// ParseDuration parses a duration string, adding +// support for the "d" unit meaning number of days, +// where a day is assumed to be 24h. +func ParseDuration(s string) (time.Duration, error) { + var inNumber bool + var numStart int + for i := 0; i < len(s); i++ { + ch := s[i] + if ch == 'd' { + daysStr := s[numStart:i] + days, err := strconv.ParseFloat(daysStr, 64) + if err != nil { + return 0, err + } + hours := days * 24.0 + hoursStr := strconv.FormatFloat(hours, 'f', -1, 64) + s = s[:numStart] + hoursStr + "h" + s[i+1:] + i-- + continue + } + if !inNumber { + numStart = i + } + inNumber = (ch >= '0' && ch <= '9') || ch == '.' || ch == '-' || ch == '+' + } + return time.ParseDuration(s) +} + // GoModule returns the build info of this Caddy // build from debug.BuildInfo (requires Go modules). // If no version information is available, a non-nil -- cgit v1.2.3