I updated a retry loop for the Go 1 preview and discovered that most of my old time code was really unit conversion wearing a wristwatch. The redesigned time package makes the unit part of the value.

The simple version now reads like the requirement:

deadline := time.Now().Add(250 * time.Millisecond)
for time.Now().Before(deadline) {
	if try() {
		return nil
	}
	time.Sleep(10 * time.Millisecond)
}
return errors.New("deadline exceeded")

The surprise was that 250 * time.Millisecond is not special parser syntax. time.Millisecond is a duration constant, and multiplication produces a time.Duration. The type gives nanoseconds a meaningful wrapper while ordinary arithmetic remains available. I no longer need a comment explaining whether an unadorned 250 is milliseconds, microseconds, or a small act of sabotage.

The package also separates an instant, a duration, and a location. A Time value identifies an instant and can be displayed in a location. A Duration is elapsed nanoseconds and has no calendar opinion. A Location contains the rules needed to interpret civil time. Treating these as distinct concepts prevents a surprising amount of accidental arithmetic.

Formatting takes a concrete reference layout rather than a string of percent directives. At first I found that peculiar. Then I noticed that the layout shows the desired result directly: year where a year goes, month where a month goes, and so on. It is memorable once learned, although “once learned” is performing useful labour in that sentence.

I prefer deadlines expressed by adding a duration to a starting time. Repeatedly subtracting hand-converted integer timestamps makes overflow and unit mistakes easy. I also prefer passing Duration through APIs instead of accepting an integer plus an implied unit.

The caveat is calendar time. Adding twenty-four hours is exactly twenty-four elapsed hours; it is not universally the same as “same local clock tomorrow” when location rules change. Parsing also needs an explicit layout and, when local interpretation matters, the appropriate location.

Because this is preview code, package details can still move before the release. The conceptual split already pays for the migration, though. My retry loop now contains time values instead of rumours about time values.