Skip to content

fix(read): Duration() parses Go duration strings (e.g. "300s", "1h30m")#218

Merged
inhere merged 1 commit into
gookit:masterfrom
j-ibarra:fix-duration-parse-string
Jul 4, 2026
Merged

fix(read): Duration() parses Go duration strings (e.g. "300s", "1h30m")#218
inhere merged 1 commit into
gookit:masterfrom
j-ibarra:fix-duration-parse-string

Conversation

@j-ibarra

@j-ibarra j-ibarra commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

The Config.Duration getter reads the value as an int64 and returns time.Duration(n) — i.e. nanoseconds — so:

  • a duration string like "300s" cannot be read at all: it fails integer parsing and yields 0 (not even the default);
  • a bare number like 300 is interpreted as 300ns.

Duration-string parsing existed only on the struct-binding path (the ParseTime decode hook via reflects.ToTimeOrDuration), never on the Duration() getter — so config.Duration("ttl") on a ttl: 300s value silently returns the wrong result.

This parses the stored value as a Go duration string first (time.ParseDuration), falling back to the previous int64-nanoseconds behaviour for bare integers, then to the default:

func (c *Config) Duration(key string, defVal ...time.Duration) time.Duration {
	str, exist := c.getString(key)
	if !exist {
		if len(defVal) > 0 { return defVal[0] }
		return 0
	}
	if dur, err := time.ParseDuration(str); err == nil { // "300s", "1h30m", ...
		return dur
	}
	if n, err := strconv.ParseInt(str, 10, 64); err == nil { // bare int = nanoseconds (unchanged)
		return time.Duration(n)
	}
	if len(defVal) > 0 { return defVal[0] }
	return 0
}

Backwards compatible: bare integers keep their nanosecond meaning; only previously-unreadable duration strings change (from 0/error to the parsed value). No existing test asserted the old getter behaviour (the existing TestDuration covers the Decode/ParseTime path). Adds a getter test covering "300s"/"1h30m"/"20m", a bare integer, and the malformed/missing default fallbacks. Full package test suite passes.

The Config.Duration getter read the value as an int64 and returned
time.Duration(n) — i.e. nanoseconds — so a duration string like "300s" could
not be read at all (it failed integer parsing and yielded 0), and a bare
number was interpreted as nanoseconds. Duration parsing existed only on the
struct-binding path (ParseTime decode hook), not the getter.

Parse the stored value as a Go duration string first (time.ParseDuration),
falling back to the previous int64-nanoseconds behaviour for bare integers,
then to the default. Backwards compatible; adds a getter test.
@inhere inhere merged commit 94aa2e8 into gookit:master Jul 4, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants