I have mixed feelings about the Go time package's time formatting strings

January 9, 2022

Over on Twitter, Thomas H. Ptacek said something about how Go's time.Parse specifies the format of times to parse. I retweeted it because I have feelings in the same direction, but really I have some mixed feelings about Go's approach here. Let's start with the documentation, which is best found in the Constants section of the time package.

To summarize, you both parse and format times by telling Go how a magic time would look either on input or on output. This magic time is Monday, January 2, 15:04:05, 2006, in time zone seven hours west of GMT, which is chosen so all sets of digits are different (including the hours if they're not in 24 hour format). A typical time format string from one of my programs is '2006-01-02 15:04:05 -0700'.

Perhaps the most common alternate time format approach is to mimic C's strftime() and strptime(). If you're using C, you're getting whatever format options your platform C library provides. If you're in a non-C language, you might be getting the POSIX standard or a platform version, potentially with non-POSIX things, such as Linux's glibc version. See, for example, the Python documentation.

(So the first problem with using the C strftime() format is that there isn't 'a' such format, there are a bunch of different ones. If you're implementing your own standard library (as Go is), you would have to decide which extensions and features you do and don't support.)

As someone who doesn't use it all of the time, the C strftime() approach has two drawbacks for me, which both come from the fact that it uses more or less opaque %-markers. First, it's opaque when encountered in code. If I hit a strftime() or strptime() format string, I generally have little idea what the output or input will look like, because I don't remember the %-operators off the top of my head; to work out what it does, I'm going to have to try it out somehow (often I reach for date or Python). Second, it's uncertain to write; after looking up the formatting operators I think I want in the manpage, hopefully I've picked the right ones and written my string correctly but I'm absolutely going to have to check my assumptions somehow.

The Go approach feels excessively clever, but it's also somewhat more obvious than strptime()'s opaque operators. Once I've looked up the magic time in the time documentation (which I have to do regularly), I can be pretty certain that '2006-01-02 15:04' is going to do what I expect. And if I encounter that in Go source code, either for formatting or parsing time, I can predict pretty well what it's going to do without even remembering the magic time.

To get more clarity and explicitness, you'd probably want to have explicit names for each time field, perhaps something like '%{year}-%{month}-%{day} %{24hr}-%{min}'. But this requires coming up with good names for all of the fields and then figuring out things like how to specify how many digits the day uses (ie, is it '2' or '02'). All of these are solvable but they're more complex and more verbose, which is not what the Go developers are generally enthused about.

(Perhaps there's a radically different and better way lurking in other languages. In a way I'd hope so; you'd hope that by now someone in some language has come up with a really good solution.)

The cleverness of Go's time formatting strings makes me vaguely twitchy, but on the whole I think I prefer it to the C strftime() approach that dominates other languages. But I do wish there was a way to make time.Parse() less exposed to accidentally reversing the two arguments.

(One obvious API would be to have a time analog to regexp's ability to pre-compile regular expressions. Then you could precompile your time format and call 'precomp.Parse(inputstr)' to parse the actual time. As a bonus, this might improve efficiency when repeatedly parsing input with the same format ('layout'), which is something that various programs do regularly.)

Written on 09 January 2022.
« Good web scraping is not just about avoiding load
The complexity of seeing if your Prometheus Alertmanager is truly healthy »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sun Jan 9 22:57:37 2022
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.