Timezones

Hey Lazyweb! Want to hear something batshit insane about the iCal format? Sure you do!

(I write these things down in the hope that doing so will cause some unfortunate soul in the future to waste less time learning this than I just did. "Today I learned something new and stupid!")

When you're exporting an event as an ICS file, so that someone can add it to their Apple or Google or Outlook calendar, you have to say what time the event starts.

Now some people well tell you, "just specify all your dates in UTC, that's easy and unambiguous." But here's what happens if you do that:

You have an event happening in San Francisco on Feb 21 at 8pm. You specify the time in UTC (DTSTART:20180222T040000Z). When someone adds that event to their calendar, the little box shows up in the calendar grid at 8pm just as it should. But then they double-click on it, and the text says: "Feb 22, 2018, 4AM to 5AM (GMT)".

While technically true, this is not a useful or convenient thing to say to an actual meat-based human who is expecting to attend that event.

So instead the sane thing is to specify the time in the local time zone where the event is happening: 8pm Pacific (DTSTART;TZID=US/Pacific:20180221T200000). The box still shows up in the calendar in the same place, but now when you click on it, it says the much more sensible "Feb 21, 2018, 8PM to 9PM (PST)". It even says that if your local time zone is something else. So if you're in New York and planning a trip to San Francisco, it's obvious to you that the event in SF starts at 8pm local time, not 11pm local time (which is what the clock would say in New York).

So far so good, right?

Oh, except that's not a valid ICS file.

Why? Because the TZID doesn't refer to the name of a time zone from the IANA Zoneinfo / Olson Database, which has been the gold standard historical record of such things since just about The Epoch. (This database is an absolute treasure, documenting and clarifying an ongoing global political and technical clusterfuck of nightmarish proportions. The work that went into this thing is staggering. It is a treasure of nightmares. But I digress.)

No, see, the iCalendar spec wants each ICS file to fully document its own notion of what the Daylight Savings Time rules are! You can't just say "Look, it's US/Pacific, ok? When is Daylight Savings Time? March? I dunno, whatever, do the right thing!" Instead you have to specify the switch-dates explicitly!

Here's what Apple does:

BEGIN:VTIMEZONE
  TZID:America/Los_Angeles
  BEGIN:DAYLIGHT
    TZOFFSETFROM:-0800
    RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
    DTSTART:20070311T020000
    TZNAME:PDT
    TZOFFSETTO:-0700
  END:DAYLIGHT
  BEGIN:STANDARD
    TZOFFSETFROM:-0700
    RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
    DTSTART:20071104T020000
    TZNAME:PST
    TZOFFSETTO:-0800
  END:STANDARD
END:VTIMEZONE

What that says is: "The definition of the America/Los_Angeles time zone is that as of 2007, it is UTC minus 7 hours from the 2nd Sunday in March through the 1st Sunday in November, and is UTC minus 8 hours otherwise."

This is, of course, false, because the rules were different before 2007. Because reasons.

So while it may work for this particular calendar entry, past ones have to be different. And let's say you put a far future event in your calendar -- the ten year anniversary of something or other -- and in the intervening decade, your country's bureaucrats change the Daylight Savings rules again. Oops, now it's wrong. You're still in US/Pacific, but the ICS file doesn't know that what that means has changed.

Because the authors of the ICS standard felt that indirecting through the IANA rules was a terrible idea for some reason.

Here's what the full set of US/Pacific timezone rules look like, all the way back to when the whole idiotic idea of Daylight Savings Time took hold, through today. It will definitely change again. The Olson database is constantly being updated. That's the whole point of it!

BEGIN:VTIMEZONE
  TZID:US/Pacific
  BEGIN:DAYLIGHT
    TZOFFSETFROM:-0800
    RRULE:FREQ=YEARLY;UNTIL=19190330T100000Z;BYMONTH=3;BYDAY=-1SU
    DTSTART:19180331T020000
    TZNAME:PDT
    TZOFFSETTO:-0700
  END:DAYLIGHT
  BEGIN:STANDARD
    TZOFFSETFROM:-0700
    RRULE:FREQ=YEARLY;UNTIL=19191026T090000Z;BYMONTH=10;BYDAY=-1SU
    DTSTART:19181027T020000
    TZNAME:PST
    TZOFFSETTO:-0800
  END:STANDARD
  BEGIN:DAYLIGHT
    TZOFFSETFROM:-0800
    DTSTART:19420209T020000
    TZNAME:PDT
    TZOFFSETTO:-0700
    RDATE:19420209T020000
    RDATE:19480314T020100
  END:DAYLIGHT
  BEGIN:STANDARD
    TZOFFSETFROM:-0700
    DTSTART:19450930T020000
    TZNAME:PST
    TZOFFSETTO:-0800
    RDATE:19450930T020000
    RDATE:19490101T020000
  END:STANDARD
  BEGIN:DAYLIGHT
    TZOFFSETFROM:-0800
    RRULE:FREQ=YEARLY;UNTIL=19660424T090000Z;BYMONTH=4;BYDAY=-1SU
    DTSTART:19500430T010000
    TZNAME:PDT
    TZOFFSETTO:-0700
  END:DAYLIGHT
  BEGIN:STANDARD
    TZOFFSETFROM:-0700
    RRULE:FREQ=YEARLY;UNTIL=19610924T090000Z;BYMONTH=9;BYDAY=-1SU
    DTSTART:19500924T020000
    TZNAME:PST
    TZOFFSETTO:-0800
  END:STANDARD
  BEGIN:STANDARD
    TZOFFSETFROM:-0700
    RRULE:FREQ=YEARLY;UNTIL=20061029T090000Z;BYMONTH=10;BYDAY=-1SU
    DTSTART:19621028T020000
    TZNAME:PST
    TZOFFSETTO:-0800
  END:STANDARD
  BEGIN:DAYLIGHT
    TZOFFSETFROM:-0800
    RRULE:FREQ=YEARLY;UNTIL=19730429T100000Z;BYMONTH=4;BYDAY=-1SU
    DTSTART:19670430T020000
    TZNAME:PDT
    TZOFFSETTO:-0700
  END:DAYLIGHT
  BEGIN:DAYLIGHT
    TZOFFSETFROM:-0800
    DTSTART:19740106T020000
    TZNAME:PDT
    TZOFFSETTO:-0700
    RDATE:19740106T020000
    RDATE:19750223T020000
  END:DAYLIGHT
  BEGIN:DAYLIGHT
    TZOFFSETFROM:-0800
    RRULE:FREQ=YEARLY;UNTIL=19860427T100000Z;BYMONTH=4;BYDAY=-1SU
    DTSTART:19760425T020000
    TZNAME:PDT
    TZOFFSETTO:-0700
  END:DAYLIGHT
  BEGIN:DAYLIGHT
    TZOFFSETFROM:-0800
    RRULE:FREQ=YEARLY;UNTIL=20060402T100000Z;BYMONTH=4;BYDAY=1SU
    DTSTART:19870405T020000
    TZNAME:PDT
    TZOFFSETTO:-0700
  END:DAYLIGHT
  BEGIN:DAYLIGHT
    TZOFFSETFROM:-0800
    RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
    DTSTART:20070311T020000
    TZNAME:PDT
    TZOFFSETTO:-0700
  END:DAYLIGHT
  BEGIN:STANDARD
    TZOFFSETFROM:-0700
    RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
    DTSTART:20071104T020000
    TZNAME:PST
    TZOFFSETTO:-0800
  END:STANDARD
END:VTIMEZONE

(I didn't build that by hand; I coaxed Apple to spit it out by creating and exporting an event in the 1800s.)

Previously, previously, previously, previously, previously, previously, previously, previously, previously, previously, previously, previously, previously.

Tags: , , ,

25 Responses:

  1. J Osborne says:

    It will definitely change again.

    No, the one saving grace of having Trump as President is the significantly increased chance of a war that will forever end time zone issues. Also humans, but you gotta look at the bright side. No more time zone fuckery after the big one!

    • jwz says:

      "In this, the Seventh Year of the Reign of The Lord Humungus, The Warrior of the Wasteland, The Ayatollah of Rock and Rolla..."

  2. Jon R says:

    It seems to me that the iCalendar working group had two choices: include the time zone definition in the event description, which carries the risk that the software reading the event may have better knowledge of the time zone than the software creating it, or don't include the time zone definition in the event description, which carries the risk that the software creating the event may have better knowledge of the time zone than the software reading it.

    Given that the person creating the event is in a better position to judge whether the event is being created at the correct time than the person receiving it, I would suggest that the decision they made is less "batshit insane" and more "practical and sensible". Also, if the zone is described in the event and there are multiple attendees then at least they will still all turn up at the same time, rather than potentially having different ideas about when it is.

    It seems possible as well that the tzdata file was less ubiquitous in 1997 when they were creating the iCalendar file format. Unfortunately, the IETF Calendaring and Scheduling Working Group's mail archives appear to be lost in the mists of time.

    At least Apple does use the tzdata zone names, e.g. "Europe/London", when referring to the time zones - unlike Microsoft who tend to say things like "GMT Standard Time", by which, in the British summer, they mean not GMT but GMT+1. Now that's batshit insane.

    • jwz says:

      It seems possible as well that the tzdata file was less ubiquitous in 1997

      Absolutely false. That's like saying, "Well, maybe this whole POSIX thing wasn't really going to catch on." I was on the "tz" mailing list in the 80s. It predates Linux by more than a decade.

      I'm going with "batshit insane".

      Also, it's been another twenty years. Make your own list of all the things that didn't exist yet twenty years ago. They could have fixed this face-palm in the spec any old time in there.

      • Jon R says:

        For some reason you've attacked my throwaway aside and completely ignored my actual argument as to why including the zone definition is not insane.

        I'm not even arguing that what they did was the best solution. I'm just saying that there is no perfect solution to the problem, and what they went with is not unreasonable. Would I do it the same way if I was creating something similar today? Probably not - I was also surprised when I discovered the way it works. But what they did is not stupid nor is it objectively worse than your suggestion.

        • jwz says:

          Well you are right that they had two choices, and obviously I think the choice they made was batshit. There's no perfect solution, but in the world we live in, any imperfect solution that doesn't include the words "The Olson Database" is koo-koo-bananas.

      • Zygo says:

        I'm pretty sure the first time I owned a machine capable of reliably live-updating zoneinfo was in 1997, and I lived in a place that gets that kind of service earlier than other places. Before that, Internet availability was a distinctly discontiguous affair, with a fee structure that punished anyone who fetched extra data with their email.

        People also assumed they'd buy machines and they'd just continue to work without updates until they crumbled into dust. How many people were still using Windows 3.1 in 1997? Just a few years before, Microsoft was worried about literally going out of business because of people not wanting software updates.

        Having the sender send a copy of the timezone definition with every ICS event was a reasonable workaround for the time. It was a pretty horrible time.

        > They could have fixed this face-palm in the spec any old time in there

        Well...yes, except that there would be a 20-year waiting period while we want for all the old-format-reading enterprise mail servers to fall over and die so that we can finally invite their users to international conference calls again.

        • jwz says:

          Well...yes, except that there would be a 20-year waiting period while we want for all the old-format-reading enterprise mail servers to fall over and die so that we can finally invite their users to international conference calls again.

          I mean, you could just fax them the schedule I guess?

    • tfb says:

      I pretty regularly create iCal events which repeat every year for ever (birthdays, anniversaries and so on). As things stand there's no way, at all, for those events to be right in general. That's just useless.

      • Jon R says:

        Not the best example given birthdays, anniversaries, etc don't even have times, only dates. And if they did, what do you even mean by the "right" definition of, for example, "exactly ten years from 2017-06-01 13:00:00, US/Pacific time", if the definition of the US/Pacific time zone changes between now and 2027?

        Dates, times and calendars are not simple and there is very rarely "one true correct answer" to anything but the most trivial of questions.

        • tfb says:

          My repeating events often do have times in fact. And 'the right definition' is 'I want to the event to go off at 9AM', say, not at 8AM because it's got some antique version of the DST change hardwired into it.

  3. MattF says:

    If you're really into this, you could go down the rabbit hole in Wikipedia entitled Time in Indiana. There's a rumor that the original idea of the old TV series "Eerie Indiana" grew out of the saying that in Indiana, no one knows what time it is.

    • Elusis says:

      Having grown up in Indiana, I can confirm this. Going to college and my mother moving to the north part of the state meant having to constantly re-calculate what time it would be when I called either parent using a calendar, an atlas, and an old priest and a young priest.

  4. Wirehead says:

    I am really really proud that one of the first things I did at my first job out of college, before they moved DST and everybody else knew, was to realize that time zones were completely nuts and therefore this Windows app I was working on should download the current state of the time zones on startup, no matter how locked-down the machine was. Naturally, the built-in bundled Windows support for time zones was totally not up to snuff and I think there was a reason why I didn't just try to use the Olson database, probably because Visual Studio.

    That being said, I am looking forward to Mars colonization because I have totally paid my dues with respect to time zone code and sometimes I just want to watch the world burn. I already get perverse glee over the way that Bitcoin causes issues with finance code, given that it has the properties of the semi-mythological Eldritch Horror Stock Exchange that would break the standard assumptions of every piece of finance code I'd ever seen.

  5. Nick Lamb says:

    Blergh, US/Pacific. Where is "US/Pacific" ?

    The Right Thing™ in timezone naming is the city name style. Any time now some lunatic can redefine "US/Pacific" by 30 minutes, probably by a vote in a chamber of people who don't know the first thing about anything. But "America/Los_Angeles" ain't going anywhere without the agreement of the people who live in it.

    This is like my view on the bridge naming. Nobody you meet from London in England knows where "William Pitt Bridge" is. It's called Blackfriars by the people who live there, so that is its name. Even the signs on the bridge say "Blackfriars" these days because if they said "William Pitt" that would be confusing and wrong. Nobody knows who the Blackfriars are either any more, but that's what it's called anyway. If I say the meeting is at 10:45 "Los Angeles time" you know when that is, or if you don't you can find out very easily, because that's the time people think it is in Los Angeles. "Pacific Time" just adds a layer of potential confusion.

  6. Steve Allen says:

    Recent changes to zoneinfo/tzdb documented in the tz mail list have clarified that "America/Los_Angeles" is not a time zone as defined in US law, but rather a "tz region" as defined in the context of tzdb. The question of how to choose the appropriate zoneinfo name was also just discussed in the tz mail list. There is no answer that works for the future because if the bureaucrats overlording a US state (say California or Washington) decide that state will no longer observe daylight time then the response of zoneinfo will be to create a new "tz region" with a name of the largest city in the region that differs from the way Los Angeles works in that future.

  7. Once I had the misfortune of working at a company which produced groupware in PHP. Twice a year, during Daylight Savings Season - for us it was a season, you see, because the time shifts are spread over the course of about a month or so when you have the entire globe to consider - support calls spiked considerably, all related to strange untoward events happening with the calendar portion of the app.

    Long story short, we planned 1.5 engineers (me being the uncleaved engineer) for 3 months for a refactor; it took roughly 12 months with 2.2 engineers. The other mostly-uncleaved engineer became my girlfriend for a few years and I still live with her. When we were done with the refactor, thousands of lines of code had been eliminated, test coverage was quintupled, and DST-related support calls were eliminated. My presentation on the effort was canceled because the hidebound Yale-educated company president was incensed at how much labor cost had been sunk into it and felt I was a substandard engineer. She was later fired, far too late for the health of the company, but so it goes.

    Our secret: for every time we stored, we recorded "intent time," which was a combination of the user-specified time and time zone; then, on every subsequent read operation, the time we output was derived from querying the the intent time vis-a-vis tzinfo. The system was durable versus acts of Congress/the Duma/etc, and basically everything else.

  8. farktronix says:

    They added a way to specify timezones by reference back in 2016 with RFC 7809. You'll love this quote from that RFC:

    "Observation and experiments have shown that, in the vast majority of cases, CalDAV clients have typically ignored time zone definitions in data received from servers, and instead make use of their own "built-in" definitions for the corresponding time zone identifier."

    • jwz says:

      Wow.

      Seems like that's only for the CALDAV protocol, though, not in ICS files.

      • farktronix says:

        Yep, but that comment from the RFC means you can probably leave out the TIMEZONE section in your standalone iCalendar files as long as you're using Olson names because most clients don't use the TIMEZONE section as the source of timezone information anyway.

        • jwz says:

          Yeah, I had been doing that for years, and it seemed to be working fine. The only reason I even noticed this was that the ICS validator I had been using went offline, and the new one I switched to complains about it.

    • Steve Allen says:

      Many of those CalDAV clients, devices such as iPhones, and other online calendar services only tolerate time zones as found in the ICU TimeZone Classes, which are an API wrapped around the Unicode CLDR time zone info, which encodes a subset of tzdb (most of the easy tz regions and none of the weird tz regions), and by the time I get here I am so far down the rabbit hole that I forget what the goal of any of these projects are, other than to say "No, we don't want to do it that way."

  • Previously