Go: proposal: time: Duration String() should omit zero units

Created on 14 May 2020  路  7Comments  路  Source: golang/go

What version of Go are you using (go version)?

1.14.2

Proposal

I propose that time.Duration.Strings() should omit zero units.

For example

fmt.Println((5 * time.Hour).String())

With this proposal, this example result will change from 5h0m0s to 5h.

  1. It's more concise. Zero units like 0m0s is meaningless.
  2. Currently, we already omit the ns, 碌s and ms units if its value is zero, so we should also emit the s and h unit to keep the String() behavior more consistent and predictable.
Proposal

Most helpful comment

At work we have a time.Duration printing function that trims the useless 0s and 0m suffixes. This is almost always a nicer way to print durations that were provided by humans (for instance, as a flag.Duration).

If we can't change the behavior of String, perhaps we could add a new method. (Display, ShortString, Str...? Nothing great is coming to mind.)

All 7 comments

Unfortunately, at this point this seems likely to break some existing programs. Is the benefit worth the cost?

Well, it will not break programs which try to parse to the duration since time.ParseDuration already handle these values.

duration, _ := time.ParseDuration("5h")
if duration == 5*time.Hour {
    fmt.Println("equal")
}

But, it will break programs that try to stringify the Duration and check the result.


This proposal is a sort of enhancing the Duration.String, which makes it more elegant. It may break some existing programs, and I not sure what the actual cost is.

If the Go team thinks that the cost is not acceptable, feel free to close it.

At work we have a time.Duration printing function that trims the useless 0s and 0m suffixes. This is almost always a nicer way to print durations that were provided by humans (for instance, as a flag.Duration).

If we can't change the behavior of String, perhaps we could add a new method. (Display, ShortString, Str...? Nothing great is coming to mind.)

FWIW, we used to print just "0" for zero and changed it to "0s" a while back. https://github.com/golang/go/issues/14058. (Not the same as this issue but related.)

It looks like right now the implementation has the invariant that it always prints a string ending in "s" - that is, there is always some number of seconds reported. Maybe a smaller unit, but always some kind of seconds. If larger units can be factored out, they are printed ahead of the seconds.

The docs are also pretty clear:

func (d Duration) String() string
    String returns a string representing the duration in the form "72h3m0.5s".
    Leading zero units are omitted. As a special case, durations less than one
    second format use a smaller unit (milli-, micro-, or nanoseconds) to ensure
    that the leading digit is non-zero. The zero duration formats as 0s.

It seems almost certain that changing this would break tests, and probably also libraries, and silently.

For better or worse, this is the documented format. It's too late to change.

Based on the discussion above, this seems like a likely decline.

@cespare I agree that a function like Display is needed, but I also think that that function should probably be in an i18n package. How about somewhere in golang.org/x/text?

No change in consensus, so declined.

@ainar-g, exactly what you want to display changes from team to team and maybe project to project. The best place for this logic is in your own code, or in a third-party library if you want to share it. (Personally I always use fmt.Sprintf("%.3fs", d.Seconds()), but I'm not adding that to the standard library either.)

Was this page helpful?
0 / 5 - 0 ratings