Why can’t I convert a time zone abbreviation into a time zone?


Public Service Announcement
Daylight Savings Time begins this weekend in most parts of the United States.

Suppose you have a string of the form "Thu Mar 27 03:46:20 CST 2003". How can you parse this into something your program can manipulate, like say a SYSTEMTIME or a FILETIME?

Basically, you can't in the general case. The time zone abbreviation CST is ambiguous. It could mean U.S./Canada Central Standard Time, Australian Central Standard Time, China Standard Time, or Cuba Summer Time. There may be other possibilities as well. Without any other context, the time zone abbreviation CST could mean any of those time zones. (This doesn't stop people from asking for the feature anyway. Maybe they want fuzzy logic or psychic powers.) Note also that there is an international standard for representing dates and times in text form, including the time zone.

Okay, back to the original problem. In order to get a definite answer, you will need to restrict your domain to resolve the ambiguity. You might decide, for example, that you only care about the four continental United States time zones. Believe it or not, this is what JScript does!

var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.GetFolder("C:\\");
var fc = new Enumerator(f.files);
for (; !fc.atEnd(); fc.moveNext()) {
  WScript.echo("File: " + fc.item());
  WScript.echo("Date: " + fc.item().DateLastModified);
}

When I run this program via cscript testprogram.js, I get the following:

File: C:\AUTOEXEC.BAT
Date: Sun Jan 9 17:13:09 PST 2005
File: C:\boot.ini
Date: Tue Nov 22 11:53:48 PST 2005
File: C:\CONFIG.SYS
Date: Sun Jan 9 17:13:09 PST 2005
File: C:\hiberfil.sys
Date: Thu Dec 14 23:29:00 PST 2006
File: C:\IO.SYS
Date: Sun Jan 9 17:13:09 PST 2005
File: C:\MSDOS.SYS
Date: Sun Jan 9 17:13:09 PST 2005
File: C:\NTDETECT.COM
Date: Tue Aug 10 11:00:00 PDT 2004
File: C:\ntldr
Date: Tue Aug 10 11:00:00 PDT 2004
File: C:\pagefile.sys
Date: Thu Dec 14 23:28:59 PST 2006

Hey, look, that time zone got inserted. But if we make a tiny change to the way we print the date

var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.GetFolder("C:\\");
var fc = new Enumerator(f.files);
for (; !fc.atEnd(); fc.moveNext()) {
  WScript.echo("File: " + fc.item());
  WScript.echo("Date:", fc.item().DateLastModified);
}

the results are quite different:

File: C:\AUTOEXEC.BAT
Date: 1/9/2005 5:13:09 PM
File: C:\boot.ini
Date: 11/22/2005 11:53:48 AM
File: C:\CONFIG.SYS
Date: 1/9/2005 5:13:09 PM
File: C:\hiberfil.sys
Date: 12/14/2006 11:29:00 PM
File: C:\IO.SYS
Date: 1/9/2005 5:13:09 PM
File: C:\MSDOS.SYS
Date: 1/9/2005 5:13:09 PM
File: C:\NTDETECT.COM
Date: 8/10/2004 11:00:00 AM
File: C:\ntldr
Date: 8/10/2004 11:00:00 AM
File: C:\pagefile.sys
Date: 12/14/2006 11:28:59 PM

In this modified version, we're print the time and date directly instead of using the JScript conversion. This time, the hard-coded U.S. English days of the week, months, and time zones aren't present. (I haven't checked whether OLE Automation follows local settings.)

(Reminder: Whether daylight saving time is a good idea has already been discussed, so please don't waste everybody's time by bringing it up again. Thanks.)

Comments (19)
  1. Nathan_works says:

    But I can’t tell the difference between the two lines other than a space. One’s blue, so ‘obviously’ that should be different than the first, but they are:

    WScript.echo("Date: " + fc.item().DateLastModified);

    and (in blue)

    WScript.echo("Date:", fc.item().DateLastModified);

    So just the space matters for what it prints out ? Strange.

    UTC/GMT/Zulu also can use single-letter abbr. for the offset, rather than +/- hh:mm

  2. mvadu says:
    1. "Suppose you have a string of the form "Thu Mar 27 03:46:20 CST 2003"."
    2. WScript.echo("Date: " + fc.item().DateLastModified);

    output looks like above.

    1. WScript.echo("Date:", fc.item().DateLastModified);

    In this modified version, we’re print the time and date directly instead of using the JScript conversion. Output is like a SYSTEMTIME form.

    Where are you answering the question? Your first example is showing conversion of SYSTEMTIME format in to text. You should have takes some Text date and written a script to convert it to SYSTEMTIME using JScript. Right?

  3. Actually, the JavaScript example can be much simpler (and cross-browser):

     alert(new Date)

    Incredibly, it seems that IE is indeed displaying abbreviations for the US-American time zones. For my time zone it shows UTC+0100 however. Firefox will always display GMT+0100 or similar – but for CST it also says "Central Standard Time" in parentheses. Guess that’s what you get if the standard doesn’t define the string representation of a date.

  4. Btw, this would have been a better example:

    alert(new Date("Thu Mar 27 03:46:20 CST 2003"))

    For me this displays "Thu Mar 27 2003 10:46:20 GMT+0100" in Firefox and "Thu Mar 27 10:46:20 UTC+0100 2003" in Internet Explorer. I guess you are right saying that the JavaScript implementations hack around this issue by interpreting only the US-American time zones.

  5. Ben Hutchings says:

    Nathan_works: The difference is: in the first case, the JScript interpreter does the conversion from date (DATETIME) to string, and in the second case WSH does it (probably using the OLE library).

    mvadu: The last-modified time of a file is of course a FILETIME not a SYSTEMTIME. However, FileSystemObject, being an OLE Automation object, converts this to an OLE date (DATETIME) which is in conventionally in local time.

    I think Raymond’s point is, if you know that the string was generated by JScript then the time zone part is no longer ambiguous. (If you’re wondering what it does for non-US zones, it’s showing "UTC" and "UTC+0100" for me.) Whether JScript itself implements the reverse conversion, I don’t know.

  6. Aaron says:

    I wish they’d made it explicit in the ISO standard that the offset suffix represents the offset for that date, taking into account DST rules, rather than leaving people to assume that it’s just the normal offset.

    Too many times I’ve been burned by some fool appending a -05:00 to every timestamp, thinking that this somehow helps me when it actually complicates matters much more.

    (Disclaimer: "Some fool" does not refer to Microsoft).

  7. There’s also RFC 2822 3.3

    http://www.faqs.org/rfcs/rfc2822.html

    which specifies a different standard for international date/time:

    Date: Fri, 07 Mar 2008 08:50:47 -0800

  8. mvadu says:

    @Ben Hutchings “The last-modified time of a file is of course a FILETIME not a SYSTEMTIME.”

    I know.. I was just a bit generic with the formats. But my whole point was Ray started the blog raising question about converting a text date (with a Time Zone part in it) in to a date-time structure (like FILETIME or SYETEMTIME). So he should have taken two different texts one with different ambiguous time zone texts, showing the Java script conversions.

    But his code was converting the DATETIME structure in to Text. He is not hitting what he claimed

    [I should have stopped after writing the second paragraph, since that’s the paragraph that answered the title question. I wrote the JScript stuff as an afterthought in an attempt to pre-empt nitpickers who will say “Ah, but if it can’t be done, then how come JScript can do it?”, but it obviously backfired. I wasn’t trying to show how to solve the problem with JScript; I was trying to show that JScript assumes United States time zones. -Raymond]
  9. Roie M says:

    Nathan_works: The difference is between a comma and a plus sign, not the space or lack thereof.

  10. mvadu says:

    And I think Wladimir Palant is using a better example and hitting the proper point.

  11. Just for fun:

    javascript:var d = new Date("Thu Mar 27 03:46:20 CST 2003"); alert("toString(): " + d.toString() + "ntoGMTString(): " + d.toGMTString() + "ntoLocaleString(): " + d.toLocaleString())

    My Firefox:

    toString(): Thu Mar 27 2003 02:46:20 GMT-0700 (Pacific Daylight Time)

    toGMTString(): Thu, 27 Mar 2003 09:46:20 GMT

    toLocaleString(): Thursday, March 27, 2003 2:46:20 AM

    My IE:

    toString(): Thu Mar 27 02:46:20 PDT 2003

    toGMTString(): Thu, 27 Mar 2003 09:46:20 UTC

    toLocaleString(): Thursday, March 27, 2003 2:46:20 AM

  12. Thu Mar 27 2003 02:46:20 GMT-0700 (Pacific Daylight Time)

    Thu Mar 27 02:46:20 PDT 2003

    Sorry, Raymond, I’m bringing up DST…

    Funny enough, both of these are wrong.  In 2003, the DST rules were different… DST hadn’t kicked in yet.  Windows doesn’t have a "zoneinfo"-like memory for DST rules so there’s no easy way to fix this.

  13. Austin says:

    Maurits:

    I believe Vista has "dynamic" timezones, which can properly adjust a TZ for a given year.

  14. I believe Vista has "dynamic" timezones, which can properly adjust a TZ for a given year.

    Huh?  No it doesn’t.  The output above is from IE 7 on Vista.

  15. Neil says:

    Its answer also depends on what it’s using to do the conversion. For example, as Raymond mentioned earlier Windows always converts time using the current timezone; .NET tries to guess which timezone was in effect, which is more intuitive; VC6 only worked in US timezones (and then only using the "old" DST rules.)

  16. Worf says:

    All I can say is thank $DIETY that all that nastiness is hidden away in libraries and API calls. Dates are nasty business. Though, one of these days I’ll take C library source code to see how it’s done.

    BTW, Raymond, you can extend that PSA to most of Canada too.

  17. me says:

    Of course, it can be remarked that strictly speaking, GMT is wrong. What people want to express is UTC in most cases. Thus, FF does it wrong, while IE does it right.

  18. different me says:

    Thus, FF does it wrong, while IE does it right.

    https://bugzilla.mozilla.org/show_bug.cgi?id=224744

Comments are closed.

Skip to main content