1. 24
  1.  

  2. 12

    This is a good example of the kind of decision made in the Go language and runtime ecosystem that really drives me up the wall.

    The interface feels altogether too brittle and implicit; users are instructed: “To define your own format, write down what the reference time would look like formatted your way”. This, apparently, because the developers feel that strftime is a kitchen sink, a bad interface: no one remembers all the letters”. Nevermind that now I need to remember, instead, how the “reference time” is structured in order to use the interface; detail which I will then have to refer to (oh no!) the documentation to rediscover.

    The strftime model allows people to explicitly construct a date format string with many different layouts, without suffering the ambiguity of a “do what I mean” style interface such as the Go language time package. It is fine to provide a simple alternative, but I find it galling to have, as a goal, purposefully excluded a more expressive, more robust interface which would also (shock, horror!) be compatible with date(1) and strftime(3C) as used basically everywhere else.

    1. 7

      Have you tried it? I used it in a project recently and while it was different than usual, I found it to be quite good, and my guesses (“what will happen if I put January here instead of 01”) generally worked the way I expected.

      1. 6

        For the larger, less dense formats (2005-01-02 blah) it reads ok. In practice for me (the company I work for is an all golang group), it’s extremely annoying. Let me give two examples of what annoys me:

        strftime in C

        int datebuf_len = 255;
        char datebuf[255];
        time_t tt;
        struct tm * tm;
        
        time(&tt);
        tm = localtime(&tt);
        strftime(datebuf, datebuf_len, "%m/%d/%Y", tm);
        

        Now, when I wonder what 05/06/2015 means, I know it’s month then day. Let’s look at the go code

        time.Format in Go

        //  Don't forget, this is the format date: Mon Jan 2 15:04:05 -0700 MST 2006
        ts := time.Now().Format("02/01/2006")
        

        Much shorter, and they get a lot of points for that, but the interface itself is less documenting. strftime’s %s can be a little annoying to look up, but the most used % symbols? They’re obvious and self documenting. This mistake is smaller than many of the other mistakes in Go, and I assume it’ll either be fixed, or another person’s time library will become the standard.

        edit: and laughably.. yet ultimately convenient to my thesis - I have a bug in my code. The day and month are flipped between the C and Go implementations.

        1. 7

          One thing to notice is that the units get progressively larger numerically. I.e 01 is month, while 02 is day, 03 hour, etc. I find it fairly clever, and mostly easy to work with given that progression.

          But of course, for some reason, years are 06, despite obviously being bigger than months, so there’s that big giant caveat.

          1. 3

            ts := time.Now().Format("02/01/2006")

            Why wouldn’t you do

            const ShortDate = "02/01/2006"
            (...)
            ts := time.Now().Format(ShortDate)
            

            Or, say you’re hitting multiple APIs that each give differently formatted timestamps (heh heh heh surely that never happens)

            func (api ApiTarget) Time() string {
                time.Now().Format(api.MySpecialSnowflakeTime)
            }
            

            I guess the reason I’m making these observations is that I’ve been faced with integrating five different APIs which means I get five different timestamp formats (and that’s assuming the API gives a consistent time format (heh heh heh), so for me

            FooTimestamp = "02/01/06"
            BarTimestamp = "January 02, 2006"
            BazTimestamp = "1 . 2 . 2006" // i hate this guy
            (...)
            

            reads really nicely.

            1. 3

              We’re arguing about the date format itself. I’m saying FooTimestamp doesn’t make any sense without BarTimestamp right next to it telling you which is 1 and which is 2.

              However - I agree whole heartedly with your suggestion, which is give the format strings names, and refer to them by those names instead of having developers individually recreate them.

              1. 1

                We’re arguing about the date format itself. I’m saying FooTimestamp doesn’t make any sense without BarTimestamp right next to it telling you which is 1 and which is 2.

                I guess they should’ve made the reference date Jan 13, but I guess that drops the nice property apg pointed out of having the values increase (except for the year, so maybe this isn’t that bad of a change).

                I dunno. I’m not really a Go developer but when I relate it to my workflow I’d definitely take the block above over

                FooTimestamp = "%m/%d/%y"
                BarTimestamp = "%B %d, %Y"
                BazTimestamp = "%m . %d . %Y"
                

                I’ve called strftime enough times to know that I’ll probably mess those up without the manpage.

        2. 5

          I like their idea, but not the implementation as much. I can never get strftime formats right. Every attempt requires a few rounds of guess and check and “oh god, why would anybody want that??”.

          What I think is cooler is a string like “yyyy-mm-dd” with all the parts filled in. Simpler than memorizing some weird standard date.

          (At Fog Creek we had some function that was almost the opposite of what go does. It brute forced turning a bunch of dates into strings in the local locale to see what happened. I forget why though.)

        3. 5

          %P - Meridian indicator (“am” or “pm”)

          %p - Meridian indicator (“AM” or “PM”)

          That’s a little messed up.

          1. 3
            1. 4

              I haven’t had a chance to cut myself on this API yet, but another datapoint: “Go’s date formatting stuff is so much more intuitive to me than strftime. Took about 5 mins to learn. People don’t like it? Weird.”

              1. 1

                Through this we see both sides of what Dennis Ritchie used to say about C. In The Art of UNIX Programming, Mike Lesk commented:

                Dennis used to say to me, when I would ask for some particularly extravagant feature in C, “If you want PL/1, you know where to get it”. (http://www.catb.org/esr/writings/taoup/html/ch04s03.html)

                Some limited subset of strftime doesn’t seem extravagant to me – I was just as peeved as other posters here when I wanted to format dates in go the first time.

                But if you want concision in a language, or in this case a standard library, you have to give up things. The odds are high, then, that you’ll also have to give up a few that you yourself might want.