Viewing By Category : timezone / Main
March 9, 2009
timezone spatial locator: updated
minor update to the project, added search/geocode functionality (seems not everyone knows how to use a map). enter a unique city/state/country name (ie, "Big Lick Mountain, PA") and the app will try to geocode the location and find the timezone there. please note that for searches that return multiple places the app will (for now) just use the first.

updated demo here. you can download the source from riaforge.

January 6, 2009
timezone spatial locator
one of the challenges of trying to use timezones (tz) in an application is that there are so darned many of them--most of which aren't relevant to a given user. for example, have a look at the timezone CFC testbed. the list of tz just goes on and on (and on). you can narrow down the list somewhat if you know the user's location (maybe via geoLocation or, oh yeah, simply asking them), but big countries like the US will still have many tz and often tz IDs won't have much meaning to users. one idea to help with this issue that i've been kicking around for a while is to use a map to help a user pick a tz relevant to them. easing back into work this week i decided now would be as good time as any to put this idea into code.

i've put up an alpha version here. it's a flex 3.x "mashup" using google maps as the UI plus geonames to supply the tz info once a user clicks on the map.

some things to note:

  • it really is alpha quality, error handling, etc. isn't very pretty
  • the normal double click to zoom in google maps behavior doesn't work as my single mouse click listener seems to be swallowing all the double clicks, so use the zoom control instead
  • it's really too big to be of much practical use, ie a much smaller widget would be better for use on a page (i am as they say "design challenged")

once i iron out all the kinks i'll post the source in the usual places.

update: seems there's an issue w/google maps API where it also fires off a single mouse click event for any double click events, so you can't easily tell the two events apart. workaround was to add shift-key to the mouse click to get tz info for single mouse click.

update: there's some kind of issue w/an iphone app doing a DDOS on the geonames web services, please change your code to use ws5.geonames.org instead of ws.geonames.org.

you can download the source, such as it is, from riaforge.

August 25, 2008
set your time--or else!
if you have servers/workstations in Thailand you probably should know that as of aug-23rd every business computer in the kingdom has to set it's time to the new TST (Thai Standard Time) or get fined a wheelbarrow full of money (from 100,000 to 500,000 baht, that's about $2500 to $15,000 US, yikes). i can understand the idea of using a timeserver to keep stuff in synch (really, who doesn't?) but man, that's a whopping big fine for being "time dumb" (especially if that's a per computer fine!). this article claims one of the reasons for doing this is so that everybody hears the national anthem at the same time.

the Royal Thai Navy's Hydrographic department is in charge of providing a national time server & it looks like they got windows covered at least (yes they devoted more than 1/2 of that page to windows 95/windows ME, no Mac, no Linux--not sure what stats they're running off).

in any case, if you're in Thailand, point your time server at:

time.navy.mi.th

and bob's your uncle. i like the idea of having a "local" time server so we swapped tout de suite. works plenty fine. the navy, as usual, did a bang up job.

June 17, 2008
whose june 17th was that again?
june 17th has been touted as "firefox download day". while i'm a long term firefox user, this june 17th business just annoys me no end. june 17th where? what time? what timezone? i've looked fairly hard for any details but all i see is this standalone, kind of useless date of june 17th.

how on earth do you think you can coordinate a global project by not giving folks useful info? geez.

i've been hitting the download link throughout the day, thinking maybe the mozilla folks were all east US coasters (really no idea, just a WAG) & i'd see something around noon here in bangkok. nope. nothing. butkis. just version 2.0.0.14.

oh well. in case anybody's missed the link, go here: http://www.spreadfirefox.com/.

December 4, 2007
another timezone two-step: venezuelan style
in case you missed the news, the politician in venezuela or should i say the Bolivarian Republic of Venezuela, has decided to implement a half hour timezone (tz) change. The tz will change from -4 hours UTC to -4.5 hours UTC. the sweet part is that the change will supposedly occur next week, 9-dec-2007. i say supposedly because it was also supposed to happen back in september or maybe august. whoopee!

everybody from cisco to ibm's doing another tz two-step (you should see the list of s/w and h/w that has to be patched). there will probably have to be a new tz definition as the old UTC-4 tz was shared by la paz, bolivia which isn't changing their tz.

if you support venezuelan users/sites better get cracking:


notice how i refrained from any comparson to woody allen's Bananas movie even though it's one of my favorites ;-)

December 16, 2006
more timezone: timezones by country
been way too busy to blog about anything lately but this might be useful to somebody, somewhere. the super cool icu4j lib has had a method to retrieve timezones by country for a couple of versions now. it's something i wish core java had, but here's the next best thing--a csv file of icu4j's timezone data along w/country. the data consists of "full" country name (Thailand), 2-letter ISO-3166 country code (TH) and timezone ID. while the timezone ID are from icu4j, these should be ok for use w/core java. frankly, i've only had time to test a few countries worth of data, so if you find any that don't work, let me know and i'll see about fixing it.

November 25, 2006
oh those crazy western australians
after being rejected in three referendums (in 1975, 1984, and 1992), western australia's starting on a three year experiment with DST. great. fine. the trouble is they just passed the final legislative hurdle for this on November 21, 2006 and will start the experiment Dec 3, 2006! oh my. every monkey and his uncle is going to be scrambling to patch servers, workstations and heaven knows what devices.

don't you just love politicians ;-)

for more info:

September 29, 2006
heads up! DST changes coming
in case you missed it, the US will have some significant DST changes in 2007. instead of DST kicking in on april 2nd, in 2007 it will start march 11th and end november 4th (instead of october 29th). those are the actual dates, the "Energy Policy Act of 2005" has the DST starting on the "second Sunday in March" and ending on "the first Sunday in November".

hopefully ColdFusion 8 (aka scorpio) will upgrade it's JDK to a version that includes the new timezone data. if not--which i think is highly unlikely--or you can't upgrade in time you can do it yourself. for MX, upgrading to J2SE 1.4.2_11 or better will do the trick.

you can read more here. an interesting note from that page is that several countries follow US DST rules, something i had never considered before.

May 27, 2006
there is such a thing as timezone hell
and i know because i've been visiting there for the last 2 weeks or so. and yes, it is a few doors down from classpath hell. if you're outside the US but host in the US or if your ColdFusion application deals w/timezones, and accurate datetime data is important you might want to pay attention to this.

let me provide a bit of background first.

ColdFusion datetimes are, i think, coldfusion.runtime.OleDateTime. The actual datetime is stored as decimal day offset from the ColdFusion epoch (31-Dec-1899) which is similar to DB2's and Excel's epochs. you can prove this to yourself by doing something like:

<cfoutput>#javacast("double",now())#</cfoutput>

which should return 38864.5102546 for a datetime of {ts '2006-05-27 12:14:46'}. btw this also hints at another way to examine day only differences between dates, ie. you can do int(now()) to ditch the time bits. there's something curious about ColdFusion datetime because you can also treat them as if they were core java Dates. for example

<cfset now=now()>
<cfoutput>#now.getTime()#</cfoutput>

returns the java epoch offset (milliseconds since 1-Jan-1970), 1148707294281 for a datetime value of {ts '2006-05-27 12:21:34'} in the server's timezone. in fact pretty much all of the core java Date class methods (though many are deprecated) will work on a ColdFusion datetime. you can use toString(), toLocaleString(), toGMTString(), setYear(), etc. though if do use these methods you'll have accomodate core java's Date "quirks" such as years being year-1900, months starting at zero (ie january is month zero in core java), as well as handle tricky data type issues (mainly for setTime() which is looking for a long).

now to the heart of the issue.

it's important to understand that ColdFusion references all datetime objects relative to the ColdFusion server's timezone. if you dump coldfusion.runtime.OleDateTime you'll see a field for TimezoneOffset (similarly core java's Date has a TimezoneOffset getter but no setter). something's gotta go there, might as well be the server's timezone data (i'm sure more thought went into this than that but you get my drift). all datetimes are server datetimes as far as ColdFusion is concerned.

if your application must handle multiple timezones, ideally you'd want to store your datetimes as UTC and convert this to whatever timezone you needed. in fact that's the whole purpose of the timezone CFC. all well and good but all datetimes are server datetimes as far as ColdFusion is concerned. while your intention is that all datetimes are UTC, your ColdFusion server doesn't see that and dependng on your server's timezone, strange stuff can happen. the clearest example is what happens to datetimes on the cusp of Daylight Savings Time (DST) on ColdFusion servers in timezones that use DST (like most of the US-based ColdFusion servers). a datetime of 2006-04-02 02:01:00.0 on those servers would never exist, it would automagically get flopped over to 2006-04-02 03:01:00.0 because ColdFusion doesn't see your UTC timezone only the server's timezone. so for an hour or so twice a year, your datetimes would be wrong by an hour. oops.

lets review some potential workarounds.

  • by far the easiest solution to this problem is to simply set your server's timezone to UTC and bob's your uncle. no fuss, no muss. however i think this won't be a viable solution for many applications hosted on shared servers, so lets look at other workarounds
  • a slicker solution would be for Adobe to provide a setTimeZone() function similar to setLocale() that would force the ColdFusion server to use the selected timezone for all it's datetime operations. if you agree with me on this by all means let the ColdFusion team know.
  • a messier but certainly more portable and near term ready approach would be to use an epoch offset instead of a "real" datetime. two solutions that come to mind are to convert all your datetimes to java epoch offsets as described above or icu4j's universal time scale. right now this is the approach we're going to implement in the new version of the timezone CFC.

i'd like to thank wayne bianca for starting this research in the first place (though given what i've been doing for the last two weeks, i think ignorance is bliss) and spike for helping me stop overthinking the solution.

April 5, 2006
proposed timezone changes for icu4j
in response to some RFEs, IBM's Yoshito Umaoka has proposed some interesting changes to ICU4J's timezone (tz) classes including methods to list tz rules as well as handle iCalendar's VTIMEZONE. to summarize from his email:

  • com.ibm.icu.util.ZoneRule: an abstract class representing a tz transition rule. this class represents basic properties of zone rule such as raw UTC offset and DST offset and abstract methods to access onset information.
  • com.ibm.icu.util.TimeListZoneRule: a concrete class extending ZoneRule. this class represents zone transition point(s) defined by UTC millis.
  • com.ibm.icu.util.RecurrentZoneRule: a concrete class extending ZoneRule. this class represents recurrent zone transitions defined by a rule, such as first Sunday in April. the way to define recurrent rule is pretty similar to SimpleTimeZone.
  • com.ibm.icu.util.RuleBasedTimeZone: a class extending TimeZone. this class aggregates one or more ZoneRule instances. using this class and ZoneRule instances, you can create a custom TimeZone which supports any historical zone transitions.
  • com.ibm.icu.util.VTimeZone: a class extending TimeZone, wraps either RuleBasedTimeZone or OlsonTimeZone (default TimeZone implementation used by ICU4J). this class would have two constructor methods for creating a new VTimeZone instance from 1) TZID such as "America/New_York" and 2) RFC2445 VTIMEZONE component. this class also provides some method to write out underlying zone rules into VTIMEZONE format.

in addtion to the new classes mentioned above, he also proposes some modifications to existing classes:

  • com.ibm.icu.util.TimeZone: an additional method - "List getZoneRules()", which returns a list of ZoneRule instances for the TimeZone. the implementation in TimeZone class just throws UnsupportedOperationException.
  • com.ibm.icu.util.SimpleTimeZone / com.ibm.icu.impl.OlsonTimeZone: overrides "List getZoneRules()" to return actual ZoneRule instances for these TimeZone implementation.

the javadocs for the proposed changes have been (temporarily) put up here. if you want to participate in the discussion regarding these changes hop on over to the ICU sourceforge site and subscribe to the mailing list.

jitter bug references: 4577, 5012

to me these seem like some decent improvements and i know several folks in the ColdFusion community are interested in timezones, especially their rules.

March 29, 2006
heads up: timezone CFC updated
well, the icu4j versions were anyway. dan switzer seems to have turned up a problem with the icu4j version that i also encountered over the weekend. the icu4j version extended the core java version by simply substituting com.ibm.icu.util.TimeZone for the core java TimeZone class. unfortunately if you didn't explicitly pass in a timezone (tz), you were supposed to get the server's tz. however icu4j differs in the way this is done:
core java:
default="#tzObj.getDefault().ID#"

icu4j:
default="#variables.timeZone.getDefault().getDisplayName()#"

the tz that the core java default method was returning wasn't understood by icu4j but it didn't throw an error but silently returned the UTC tz instead. whoops.

you can pick up the new version here.

March 26, 2006
Australian DST change: a day late and a dollar short?
while i should have been more than vaguely aware of this issue, it seems even Sun was laying down on the job a bit. Australia observes DST (Daylight Saving Time or Summer Time as they say down under) just like the US and other countries. DST in Australia normally ends March 26, 2:59AM (local time). however this year, to accomodate the Commonwealth games, the DST end date was pushed back to April 2. most older JRE's (like the version that coldfusion runs on, even the updated JRE that the flex/coldfusion connector "installs") still run off the older Olsen data with Australian DST ending March 26. on March 25th i got an email from the Sun Developer Network pointing at this article about the issue including links to updated JREs. talk about cutting it close.

icu4j on the other hand, has had this and other updated timezone info for some time now.

February 15, 2006
another icu4j stealth upgrade
i seem to keep missing these....the super cool icu4j lib was updated 20-jan-2006 to version 3.4.2. it contains a few bug fixes (Chinese date format/calendar, currency rounding bug for de_CH locale, etc.) but the biggest deal is that this release dumps the dependency on core java timezone data. while i normally use core java's timezone classes this puppy has several methods that i find pretty cool. for instance, one of the biggest headaches w/using timezone data is that there is just so darned many of them. filtering these down into something reasonable often results in some compromises that always leave me feeling like we're missing something. now we can do filtering that at least looks more reasonable, say like using a user's country:

<cfscript>
tz=createObject("java","com.ibm.icu.util.TimeZone");
//get TZ based on country
zones=tz.getAvailableIDs("TH");
</cfscript>

<cfdump var="#zones#">

how cool is that?

January 17, 2006
SMS timezone gotcha
been spending some time lately researching SMS technology. first off the whole industry is great, never seen so much jargon in my whole life (anyone doing i18n work will tell you, we simply love our jargon): SMSC, MT, PDU, MSC, HLR, MSISDN, yadda yadda yadda, bing bam boom, i could go on all day ;-) this stuff just rolls off your tongue.

one kind of subtle gotcha i've run into was timezones (tz). i'd always assumed it worked like email, you could control the display datetimes on the client as they were stamped with enough info to figure out how to display the email datetime in the client's tz. nope. what you get is either the aggregator's tz or the aggregator's service provider tz or some kind of compromise tz if the service provider handles many tz. whether or not your device can assemble it into your tz is another story.

if you're lucky or smart enough to handle just the one national market using a national aggregator/telecom, you'd never notice this. it bites your ankles though when you "go inter" as they say here in Thailand. depending on where the client device and aggregator's servers are located, you could get the rather cool phenomena of SMS coming from the future (shades of the 4400). while i think it's pretty cool, users however have a rather different opinion. no amount of cajoling or threatening will make any difference, you're stuck with that tz. probably something you might want to keep in mind.

you can read a bit more here.

August 6, 2005
more timezone stuff
i got an email from a coldfusion developer in iran (Behrang Noroozinia) complaining that my timezone CFC wasn't casting to his timezone (tz) correctly. double checking i found that was i was using decimal hours with cf's dateAdd function which only accepts integers. i guess nobody else noticed as most users live in tz w/whole number offsets from UTC. in iran however they have an offset of 3.5 hours (plus 1 hour for DST). interesting that dateAdd didn't throw an error but instead truncated the decimal hours. in any case, even if you don't live in iran, if you use the timezone CFC you should download this fixed version.

ps: the experimental DST bits are on hold now, s. isaac dealey was kind enough to review the logic and sent me a bunch of stuff to look over. hopefully i can get to it this weekend.

July 28, 2005
oh boy, timezone DST info
info concerning DST (daylight saving time) is one of the more requested additions to my timezone CFC. many folks have wanted to know when a particular timezone's DST starts and ends, what are it's rules, etc. i've resisted adding it as i thought the only "good" way to get at this data was via the Olsen timezone data which is kind of soggy and hard to light. a couple of days ago somebody in the forums asked about this again while i was twiddling my thumbs waiting on some tests (inserting/returning monster thumping BLOBs into sql server via cf7 w/out croaking the JVM). so i poked and prodded the java.util.TimeZone and java.util.SimpleTimeZone classes until something fell out: parse what a toString() returns on the timezone object. pretty simple, except the DST start/end logic wasn't what i'd call simple and there were several bits that weren't very well documented. for instance, here's what you get from dump the Mexico/BajaNorte timzone:
sun.util.calendar.ZoneInfo[id="Mexico/BajaNorte",offset=-28800000,dstSavings=3600000,
useDaylight=true,transitions=149,lastRule=java.util.SimpleTimeZone[id=Mexico/BajaNorte,
offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,
startMonth=3,startDay=1,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=2,
endMonth=9,endDay=-1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]]

the interesting bits are the "lastRule". you can see the startDay, startMonth (remembering that java months start at 0), etc. the trouble comes in deciphering the logic for the DST start/end date parts. endDay=-1?? what the heck? if you read the javadocs API for these classes, the logic is spelt out in the API but setting up cf's logic to handle this was getting messy. that's when i noticed startMode and endMode. these values seemed like a way to short circuit that messy logic, unfortunately, these aren't really documented in the APIs. to make a long story shorter, some googling and peeking inside source code i came up with these:

  • DOM_MODE (1): Daylight savings time start/ends on the exact day of the month specified by day of month. For example, the fifth day of the month.
  • DOW_IN_MONTH_MODE (2): Daylight savings time start/ends on the day of the week specified by dayofweek that occurs in the month as specified by day of month. For example, the last Sunday of the month.
  • DOW_GE_DOM_MODE (3): The absolute value of dayofweek gives the day of the week occurring on or after the day of the month specified by day of month for which daylight savings time start/ends. For example, the first Sunday on or after the fifteenth of the month.
  • DOW_LE_DOM_MODE (4): The absolute value of dayofweek gives the day of the week occurring on or before the day of the month specified by day of month for which daylight savings time start/ends. For example, the first Sunday on or before the fifteenth of the month.
you'll find an experimental version of the timezoneCFC here. for starters i'm not 100% sure about the DST start/end logic. next the returned DST start/end times aren't (yet) compensating for the start/end time modes (standard, wall, UTC). and of course it's experimental.

in any case, i'd appreciate folks testing this and if possible maybe having a look at the DST start/end logic and letting me know of any problems.

thanks.

February 16, 2005
cf datetime numeric units
i goofed again. when we tested the reworked timezone CFC, the test harness randomly tested just timezones but not dates. and by some bizzaro world circumstance, all the timezones it tested didn't use daylight savings time (DST). so the timezone offsets it reported passed 100%. when i was cleaning up the tests today i noticed that and ran the test against a list of timezones that use DST and dates in/out of DST. oops. all the offsets it returned were all the same as the raw offset (sans DST), even when the dates were in the DST period for that timezone. oh my.

trying to fix that blunder led me into the bowels of cf where i had some trouble getting my head around the exact numeric units that cf uses for datetime objects. i was doing a javacast("long",arguments.thisDate) thinking i'd get milliseconds since java epoch to pass into java.util.TimeZone's getOffset method, ie assuming a cf datetime was a java.util.Date. but that snippet actually returns 38399 for today (16-feb-2005). which certainly doesn't look like the number of milliseconds since 1-jan-1970. recalling i blogged something about binary time scales, i whipped out a calculator to see when cf's "epoch" actually started. 38399 turns out to be the number of days since 31-dec-1899. that makes the cf datetime object type (which is actually a coldfusion.runtime.OleDateTime) more like "Excel_Time" or "DB2_Time" which measure dates in days since their epoch started (31-dec-1899).

well the timezone CFC's fixed up now. and i learned a bit more about cf (and not to assume too much about how cf works).

February 15, 2005
new and improved timezone CFC
our code re-working frenzy continues. trying to squeeze more speed out of our venerable timezone CFC (circa AD 2003), we revisited each method looking for "dumb things". one thing we noticed was its use of the gregorian calendar to determine a timezone's offset. why we did it that way has long since been forgotten (but probably someone who knew java better than we did told us to, we were looking at using other calendars, the fact that it worked at all was a novelty, etc.).

in any case functions (castFromUTC/castToUTC/etc) that used code like this:

// get selected timezone
tZ=tzObj.getTimeZone(arguments.thisTZ);
// set gregorian calendar to selected timezone
gregorianObj.setTimeZone(tZ);
// set gregorian calendar to selected datetime
gregorianObj.setTime(arguments.thisDate);
// calculate offset
thisOffset=(gregorianObj.get(gregorianObj.DST_OFFSET)/1000) + (gregorianObj.get(gregorianObj.ZONE_OFFSET)/1000);
return dateAdd("s",thisOffset,thisDate);

were re-worked to use:

// get selected timezone
var timezone=tzObj.getTimeZone(arguments.thisTZ);
// get offset in hours, also considers DST var thisOffset=timezone.getOffset(javacast("long",arguments.thisDate))/3600000;
// send cast date back to caller
return dateAdd("h",thisOffset,arguments.thisDate);

and sped things up 2x-3x. you can see the new CFC in action here.