Go · Dates

Date and time representation in Go

I’ve been keeping a secret, that secret is I absolutely love Go. Ok, it’s not much of a secret, and it’s not that much of an admission. But there’s something that has been really getting my goat with Go. Date parsing and formatting.

Date formatting is an incredibly complex thing, not because of any tricky math, but because dates are not universal across humanity. Calendars the world over have only one thing in common, they chart the passage of time, and that’s all.

There are several categories of calendars, Solar (One year is the time it takes to complete one orbit of the sun), Lunar (Months are the time it takes for the Moon to complete all phases, and a year is set to a certain number of months), Lunar-Solar (Months are the same as the Lunar style, but ‘leap’ months are inserted such that the year is one solar year), and the Sidereal calendar (a year is based on the position of the earth as referenced by stars other than the Sun).

Westerners have adopted the Gregorian solar calendar, and much of the world has grudgingly accepted that calendar for themselves as well, when dealing with other countries at the least.

As if that’s not enough, there’s a wide variance in the way that the fields of a date are presented. Americans are fond of Month/Day/Year Hours:Minutes:Seconds (think January the first, 2020). Other parts of the world prefer Day/Month/Year Hours:Minutes:Seconds (think first of January 2020). Software developers prefer Year/Month/Day Hours:Minutes:Seconds, because that makes sorting so much easier (the magnitude of the field descends each step, a Year is made up of many Months, Months are made of many days, and so on).

It should be clear, now, that date and time handling is fraught with peril. There are no easy solutions. Most computer systems, programming languages, and operating systems, use the Gregorian calendar with several ways to represent the fields. I’m not going to enumerate them all here, but almost all of them use the initial letter of the English name of the field that they represent.

An example might be (for Year-Month-Day Hours:Minutes:Seconds)

YYYY-MM-DD HH:mm:SS

Note that there is overlap with the Month and minute field names both beginning with the letterm, so capitalisation is used to differentiate the two.

Go, for reasons of it own chose something completely different. The authors of Go took a date that has meaning to them, wrote it in the American preferred format, and then used the position of that field in their example as the name of the field.

Mon Jan 2 15:04:05 MST 2006

Translates to

01/02 03:04:05PM '06 -0700

Thus, if I want to create a format that matches what was created earlier (Year-Month-Day Hours:Minutes:Seconds)

0700-01-02 03:04:05 

Which, to me, is indecipherable.

There are two possible fixes

  • Go adds a second date representation, more inline with established representations
  • Third party libraries

When I raised this issue in May 2020, time: magic number datetime formatting I was told that there was at least one third party library go-strftime that provides a better API, and that there were no plans to change the existing Go implementation (although I am at a loss to understand why, such a change would be backwards compatible).

Published:
comments powered by Disqus