Why not auto convert week-based time zone information to date-based?


When I described the two ways that the TIME_ZONE_INFORMATION structure represents the rules for daylight saving time, commenter Voo argued (and I hope I interpreted the message correctly) that either there should be two functions, one for each of the ways, or have Get­Time­Zone­Information­For­Year function calculate the day automatically from the week and return that. That way, callers always see the correct day.

Okay, there are multiple things in play here, but they all boil down to "no code is an island".

If all you needed to support was a way to answer the question "When does daylight saving time start and end in this specific year", then certainly the nth week rules could be interpreted by the Get­Time­Zone­Information­For­Year function, so that all that came out of the function was a specific date and time.

But that's not the only function that deals with time zone information. For starters, we have Get­Time­Zone­Information. Since this function is not dependent on the year, it wouldn't know what year to use to calculate the date on which the third Sunday falls. It would have to leave the structure in generic form.

Now, maybe you say, "Yeah, these two functions return the same structure, and you just have to know that one of the functions will autoconvert and the other won't." Some people will find that confusing.

Maybe you solve that problem by saying, "These two functions return different structures, reflecting their different natures." Some people will be frustrated by that, because they will have to write two versions of the same function, one for each structure.

(I'm not event going to bother adding Get­Dynamic­Time­Zone­Information. to the mix.)

And then there's the question of whether it's okay that the Get function returns a structure that cannot be passed into the corresponding Set function. (Which is a bit of a pointless question here, seeing as there is no Set­Time­Zone­Information­For­Year function, but maybe someday it will show up.) It also means that you cannot compare two TIME_ZONE_INFORMATION structures from different years to see whether the time zone transition rules are the same in those years. (This is, admitted, a fringe scenario.)

Two functions seems the less crazy way out. There would be a Get­Unexpanded­Time­Zone­Information­For­Year which returns the unprocesed information and a Get­Expanded­Time­Zone­Information­For­Year that does the date lookup for the appropriate year. Though personally, I would keep Get­Time­Zone­Information­For­Year as-is and add a Calculate­Daylight­Saving­Transition­Dates­For­Year function. That way, you could use it to expand other things.

I suspect no such Calculate­Daylight­Saving­Transition­Dates­For­Year function exists because the kernel folks have a general bias against writing functions that you could have written yourself, so that they can focus on writing functions that you can't write yourself because it requires special access to things that only the kernel has access to. (Like querying the current time zone.)

Comments (17)
  1. Martin Bonner says:

    I approve of the kernel folks bias. It's really hard to put a security vulnerability in a function that doesn't exist.

  2. Nick says:

    Maybe this means we'll get a bonus time- or time-zone-related post next Friday, the last work day before the US and Canada begin Daylight Saving Time (in the places that observe it).

  3. jgh says:

    Calculate­Daylight­Saving­Transition­Dates­For­Year is also impossible to write as the kernal does not have access to a time machine. In 1960 would you know what that function should have returned if passed "UK" and "1970" ?

  4. Mark Y says:

    Um, why doesn't the time zone live in user space? The current time probably needs to go through the kernel, since that's direct hardware access, but why the time zone?

    1. The current timezone is a global setting, not user-level (unless you're running in Terminal Services mode, in which case remote logins can provide a timezone for the session). It's managed in the kernel with the rest of the date/time functions. I have no idea why it's not a user setting, but them's the breaks.

      1. Mark Y says:

        Per-user time zone sounds like a recipe for havoc. You can't trust file times that way, at the least.

        1. Simon says:

          Sure you can... the file times are all in UTC, and displayed according to the user's timezone.

      2. Andy Balholm says:

        The time zone is a kernel setting because the kernel uses local time (at least for some purposes). The kernel uses local time because the hardware clock is assumed to be in local time, and so are FAT timestamps. These are local time for compatibility with DOS. DOS used local time because… well, it was the obvious choice for a single-user system with no network connection.

        The time zone is a user-mode setting on Unix systems, because they use UTC for almost everything, and convert to and from local time on input and output. Unix uses UTC because… well, it was the obvious choice for a multi-user system with people dialing in by teletype from all over.

        1. Yeah. I guess my point was that this expectation could've been changed with Windows NT, but they opted not to. Probably because of compatibility with DOS applications (or more likely, OS/2 applications).

    2. skSdnW says:

      Try debugging GetSystemTimeAsFileTime and you will see that all it does is read the time from a special page of memory that is read-only in usermode.

      1. Mark Y says:

        So it is in user space! (In the sense that there is no need to make a system call to read it.)

  5. Kevin says:

    >(Which is a bit of a pointless question here, seeing as there is no Set­Time­Zone­Information­For­Year function, but maybe someday it will show up.)

    What would that do, fire up the handy-dandy Microsoft Time Machine (TM) and bribe the local government to change the time zone for a given year?

    1. Alex Cohn says:

      This is a valid concern. Unfortunately, other OSs follow the same path, even though they cannot easily get updated. This way, the user is sometimes forced to change the time zone only to avoid automatic DST switch on a device that was programmed for an outdated version of a local law.

  6. Ray Koopa says:

    Of course, the best solution is to get rid of DST in general. But that's luckily not a problem Microsoft has to solve.

    1. Engywuck says:

      I once read the not-totally-unconvincing argument that DST is actually (somewhat) *more* natural than same-time-all-year.
      The reasoning was something like: in ancient times without clocks humans started to rise when the sun rises (plus/minus a fixed delta). Only after clocks and artificial lighting was introduced the "office starts all days at nine" was introduced, meaning you have to get up unnaturally early in winter (and late in summer). DST tries to emulate the everyday changing rising of the sun to some degree, but because nobody wants to change their clocks everyday (or business starting time, train schedules etc) does so in one one-hour increment, which is obviously non-ideal in itself, too. With electronic clocks this could be done, but it's probably too late now :-)

      1. I think it would make a lot of sense for businesses to say "from March–November, we're open from 8am–5pm, and from November–March, we're open from 9am–6pm" or similar, rather than deal with everyone changing their clocks and all the repercussions thereof.

  7. Karellen says:

    Not included in the classic "{More ,}Falsehoods Programmers Believe About Time" articles, but relevant to the question “When does daylight saving time start and end in this specific year”:
    • Daylight saving time changes occur no more than once per direction per year.

    How do the GetTimeZoneInformation*() functions handle zones/years with more than once change per year?

Comments are closed.

Skip to main content