I have mixed feelings about the Go time
package's time formatting strings
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.)
|
|