Chronos is one of the many Smalltalk-related blogs syndicated on Planet Smalltalk
χρόνος

Discussion of the Essence# programming language, and related issues and technologies.

Blog Timezone: America/Los_Angeles [Winter: -0800 hhmm | Summer: -0700 hhmm] 
Your local time:  

2006-01-26

Comparative Examples: Chronos (and Smalltalk) vs. Java's Calendar Class

David Herron blogs about his attempt to use Java to show the local date and time of a widespread set of team members in Santa Clara CA, Beijing China, Bangalore India, Hyderabad India, St. Petersburg Russia and Dublin Ireland. His situation is becoming much more common, especially among IT professionals.

To see his Java code, and the resulting output, click here.

Here's the equivalent code using Chronos (and Smalltalk):


| universalNow printPolicy |
printPolicy := ConfigurableChronosPrintPolicy applying: #(showTimeZoneVerbosely).
universalNow := Timepoint utNow.
#('America/Los_Angeles' 'Asia/Calcutta' 'Europe/Moscow' 'Europe/Prague' 'Europe/Dublin'
'Europe/London' 'Asia/Tokyo' 'Asia/Novosibirsk' 'Asia/Hong_Kong' 'Asia/Shanghai'
'Asia/Seoul' 'America/Denver' 'America/New_York')
do: [:tzKey |
| localTimeNow |
localTimeNow := universalNow >> tzKey.
Transcript
cr;
show: (localTimeNow % printPolicy)]

The code above produces the following output:

2006-01-26T19:51:43.248535-08:00 (PST:America/Los_Angeles)
2006-01-27T09:21:43.248535+05:30 (IST:Asia/Calcutta)
2006-01-27T06:51:43.248535+03:00 (MSK:Europe/Moscow)
2006-01-27T04:51:43.248535+01:00 (CET:Europe/Prague)
2006-01-27T03:51:43.248535+00:00 (GMT:Europe/Dublin)
2006-01-27T03:51:43.248535+00:00 (GMT:Europe/London)
2006-01-27T12:51:43.248535+09:00 (JST:Asia/Tokyo)
2006-01-27T09:51:43.248535+06:00 (NOVT:Asia/Novosibirsk)
2006-01-27T11:51:43.248535+08:00 (HKT:Asia/Hong_Kong)
2006-01-27T11:51:43.248535+08:00 (CST:Asia/Shanghai)
2006-01-27T12:51:43.248535+09:00 (KST:Asia/Seoul)
2006-01-26T20:51:43.248535-07:00 (MST:America/Denver)
2006-01-26T22:51:43.248535-05:00 (EST:America/New_York)


To get output formatted as RFC 2822, just replace "% printPolicy" with "% #rfc2822". To get output formatted according to the user's default preferences, replace "% printPolicy" with "localePrintString".

With the following improvements, we can sort the output by time zone offset, and get much more readable output:


| universalNow printPolicy |
printPolicy := ConfigurableChronosPrintPolicy applying:
#(showDayOfWeekAbbreviation
useDayMonthYearOrder
useMonthAbbreviation
dateSeparator: $
dateAndTimeSeparator: $
hideSubsecondFraction
timeZoneSeparator: $
timeZoneElementSeparator: nil
showTimeZoneVerbosely).
universalNow := Timepoint utNow.
#('America/Los_Angeles' 'Asia/Calcutta' 'Europe/Moscow' 'Europe/Prague' 'Europe/Dublin'
'Europe/London' 'Asia/Tokyo' 'Asia/Novosibirsk' 'Asia/Hong_Kong' 'Asia/Shanghai'
'Asia/Seoul' 'America/Denver' 'America/New_York')
collect: [:tzKey | universalNow >> tzKey])
asSortedCollection:
[:localTimeA :localTimeB | localTimeA offset > localTimeB offset])
do: [:localTime | Transcript cr; show: localTime % printPolicy]


The improved code produces the following output:

Fri, 27 Jan 2006 14:29:43 +0900 (KST: Asia/Seoul)
Fri, 27 Jan 2006 14:29:43 +0900 (JST: Asia/Tokyo)
Fri, 27 Jan 2006 13:29:43 +0800 (CST: Asia/Shanghai)
Fri, 27 Jan 2006 13:29:43 +0800 (HKT: Asia/Hong_Kong)
Fri, 27 Jan 2006 11:29:43 +0600 (NOVT: Asia/Novosibirsk)
Fri, 27 Jan 2006 10:59:43 +0530 (IST: Asia/Calcutta)
Fri, 27 Jan 2006 08:29:43 +0300 (MSK: Europe/Moscow)
Fri, 27 Jan 2006 06:29:43 +0100 (CET: Europe/Prague)
Fri, 27 Jan 2006 05:29:43 +0000 (GMT: Europe/London)
Fri, 27 Jan 2006 05:29:43 +0000 (GMT: Europe/Dublin)
Fri, 27 Jan 2006 00:29:43 -0500 (EST: America/New_York)
Thu, 26 Jan 2006 22:29:43 -0700 (MST: America/Denver)
Thu, 26 Jan 2006 21:29:43 -0800 (PST: America/Los_Angeles)


Perhaps David should have considered using Joda Time, if he's determined to use Java.


2 comments:

Anonymous said...

The Java code you're using for comparison is rubbish. There are many better ways of doing this...

Alan Lovejoy said...

Yes, there are much better ways to code David's example. In fact, I listed one: use Joda-Time. But even if one uses java.util.GregorianCalendar, there are better ways--as is pointed out in the comments to David's post.

I didn't state it, but the point I'm really trying to make is that most coders don't handle dates and times very well at all, and should always defer as much of the job as possible to the expertise of a well-designed date/time library--which Sun's java.util package is not (a widely-held opinion, by the way, even among the Javangelistas.)