Go Time Format

Preview Go time layouts, infer one from a sample, and convert to and from strftime.

Layout

Output2024-03-09T14:07:09-05:00
t.Format(time.RFC3339)

This is time.RFC3339 — use the constant rather than retyping the layout.

Previewing

What each token means

2006Four-digit year2024
01Month, zero-padded03
02Day, zero-padded09
15Hour, 24-hour clock14
04Minute, zero-padded07
05Second, zero-padded09
Z07:00Offset with colon, or Z when UTC-05:00

Which layout parses this?

Paste a timestamp you already have and this works backwards to the layout that both parses and reproduces it.

strftime

2006-01-02 15:04:05
The layout above as strftime%Y-%m-%dT%H:%M:%S%:z

Layout constants in the time package

About Go time layouts

Go's time package does not use format specifiers. Instead of %Y-%m-%d you spell out a reference instant — Mon Jan 2 15:04:05 MST 2006 — so the layout for an ISO date is literally 2006-01-02. Each component has its own magic number, in the order 1 through 7: month, day, hour, minute, second, year, zone offset.

The same layout is used for both directions: t.Format(layout) and time.Parse(layout, value). That is convenient, but it means a layout that is subtly wrong will happily produce a wrong string in one direction and fail to parse real data in the other.

The reference time, component by component

  • 2006 year, 06 two-digit year
  • 01 month zero-padded, 1 unpadded, Jan and January by name
  • 02 day zero-padded, 2 unpadded, _2 space-padded
  • 15 hour on a 24-hour clock; 03 and 3 on a 12-hour clock
  • 04 minute, 05 second, both with unpadded 4 and 5 variants
  • -0700 and -07:00 numeric offsets, MST zone abbreviation

The mistakes that do not raise an error

Every one of these produces a plausible-looking string rather than failing, which is what makes them worth knowing:

  • Using 03 without PM. 03 is the 12-hour clock, so 14:07 and 02:07 both format as 02. If you want a 24-hour clock the token is 15, and it is the only one.
  • Z07:00 versus -07:00. The first prints a literal Z when the offset is zero, which is what RFC 3339 requires. The second always prints +00:00. That single character is the difference between valid and invalid RFC 3339.
  • .000 versus .999. Same precision, different output: .000 keeps trailing zeros, .999 strips them and omits the decimal point entirely when the fraction is zero.
  • MST does not round-trip. It prints a zone abbreviation, but time.Parse cannot resolve an abbreviation back to a real location, so parsing your own output gives a zero offset. Use Z07:00 or -0700 for anything you intend to read back.

Coming from strftime

Most directives map across cleanly, but three gaps are worth knowing about. %-H has no equivalent — Go's only 24-hour token is 15, and it always zero-pads. There are no week-number tokens at all, so %U, %W and %V need t.ISOWeek() instead. And there is no epoch token; %s is t.Unix().

Is this accurate?

The formatter here is a reimplementation of Go's own Format, including the awkward tokenising rules — _2006 is a literal underscore followed by a year, and .04 is a literal dot followed by a minute rather than a one-digit fraction. It is checked against the real Go runtime across several thousand generated layout and instant combinations, in both directions, and is required to match byte for byte.