Pain in timezone support

Time Zone for countries, courtesy of Wikipedia Commons

Haven’t anticipated the addition of timezone info has caused so much grief for me, though lots of “fun” are uncovered during the process.

Four years later: GDateTime structure will be used to simplify cross platform handling of such date / time issue. Let’s see how far it can go.

strftime() is not very platform neutral

strftime() on Windows is less capable then the Unix ones. For compatibility, the date / time format would need to be expressed as %Y-%m-%d %H:%M:%S in place of just %F %T (supporting ISO C89 standard but not C99); nor does it print numerical time zones.

TZ environment variable on Windows is crap

Nowadays systems don’t use TZ variable for common purpose anymore. 1 Linux / BSD make use of Olson time zone database which automatically handles GMT offset and DST, while TZ can also be set in well-defined manner to temporarily override system setting. Windows users would be familiar with Control Panel settings instead. But TZ variable in Windows is arbitrary and there is no rigorous checking 2, resulting in hilarious scenarios:

  1. For example, I can happily use the value ABC123XYZ as timezone and it would be accepted as a timezone having -123 hours offset from UTC. The letters are merely junk — except that using 4 letters (like EEST which is a valid timezone in Istanbul) would cause functions utilitizing TZ variable to wreak havoc.

  2. Compare these 2 commands:

    set TZ=
    set TZ= 

    The first line unsets TZ variable as expected, so that Windows would retrieve regional setting from control panel. But with an extra space in 2nd line, timezone is set to UTC with Daylight Saving Time forcefully turned on!!! It costs me days of head scratching and several faulty “fixes”.

_timeb structure does not respect TZ variable

The DST value returned from _timeb structure is faulty, in that it only respects the timezone setting from Control Panel and not TZ variable. That’s one of the bug addressed in 0.6.1 version. The following table shows how the values of _timeb.dstflag and tm.tm_isdst vary with TZ and Control Panel settings (undesirable values marked in red background):

_timeb.dstflag value
  Control Panel
Use DSTNo DST
TZ (unset) 1 0
UTC 1 0
PST8PDT 1 0
tm.tm_isdst value
  Control Panel
Use DSTNo DST
TZ (unset) 1 0
UTC 0 0
PST8PDT 1 1

It is immediately apparent that _timeb.timezone ignores TZ completely. OTOH tm.tm_isdst consults both settings, so is reliable enough for use in rifiuti2.

Nice stuff: INFO file stores UTC time since 95

Enough Windows bashing. Actually, Microsoft developers are surprisingly forward-thinking in some aspects. The INFO file (in Win95, predates INFO2 used in Win98) already uses 64-bit FILETIME, when 32-bit systems were still not mature yet. And this FILETIME stores UTC time, not local time which is still dominant in system time of current Windows. That saved lots of headache when constructing event timeline.


Date ChangeLog
2015-05-28 Add description about problem in _timeb
2019-06-04 Use of GDateTime to replace the whole mess
  1. TZ variable used to be a common mechanism to set time zone for Windows 3.1. Same applies to ancient Linux systems. 

  2. Format of TZ variable is documented in _tzset() function. However, it doesn’t mention the behavior if supplied value does not satisfy documented format. In fact virtually infinite randomly invented values would be accepted.