What time is it?

; Date: Mon Dec 05 2005

Tags: Java

Since the Quality Team is so widespread (as I blogged before, Santa Clara CA, Beijing China, Bangalore India, Hyderabad India, St. Petersburg Russia and Dublin Ireland) we have a constant question of what time we need to hold meetings so the majority of us can participate. It's tough because for most purposes Santa Clara and the other teams are on opposite sides of the world and we're asleep when the others are awake, and vice versa.

On my recent trip to Bangalore I found the kworldclock tool to be immensly valuable. I wanted to know when to call home to talk with my sweetie. What kworldclock does is show on a world map where the sun's shadow is currently located. Similarly on British Airways flights during the trip I was able understand better what I was doing in relation to the sun, because BA has a similar display in the airplanes.

(ASIDE: the flight back was a veeery long day, beginning in Bangalore at 4:00 AM, flying to London arriving around 12:00 leaving around 2:00, flying to Seattle arriving around 5:00 PM and then to San Francisco arriving around 7:30 PM. I was chasing the sun across the planet, spent around 24 hours of my time returning home, and it didn't get dark until sometime during the flight from Seattle to San Francisco. That is, except for this brief period flying over Greenland where we were in the perma-dark area near/above the arctic circle)

Anyway .. back to the time zones and my concern about what time it is. The kworldclock has a nice feature that it lets you list selected time zones at the bottom of the screen. Unfortunately kworldclock doesn't exist for every platform, and I'd like to have similar functionality on other systems.

What I have here for todays blog entry is the underlying Java code which does the minimalist functionality I need. That is, given a set of time zones, print a table showing the current time in each.

The first thing to see is that the Date class doesn't have the required functionality. You can make a Date object and it gives you the current time, or you can initialize it for some other time. But, how do you know the time in some other timezone? Further it's getYear and other methods are deprecated in favor of the Calendar class anyway.

What you do is make a TimeZone object, and then initialize a Calendar (or GregorianCalendar) object using that TimeZone. With the Calendar object in hand you then use "get" to retrieve the various fields and print them out.

Let's first get the TimeZone objects:

    TimeZone tzsca = TimeZone.getTimeZone("America/Los_Angeles");
    TimeZone tziec = TimeZone.getTimeZone("Asia/Calcutta");    // same as Bangalore
    TimeZone tzmoscow = TimeZone.getTimeZone("Europe/Moscow"); // same as St. Petersburg
    TimeZone tzprague = TimeZone.getTimeZone("Europe/Prague");
    TimeZone tzdublin  = TimeZone.getTimeZone("Europe/Dublin");
    TimeZone tzlondon  = TimeZone.getTimeZone("Europe/London");
    TimeZone tztokyo  = TimeZone.getTimeZone("Asia/Tokyo");
    TimeZone tznsk  = TimeZone.getTimeZone("Asia/Novosibirsk");
    TimeZone tzhongkong  = TimeZone.getTimeZone("Asia/Hong_Kong");
    TimeZone tzshanghai  = TimeZone.getTimeZone("Asia/Shanghai");    // same as Beijing
    TimeZone tzseoul  = TimeZone.getTimeZone("Asia/Seoul");
    TimeZone tzbroomfield  = TimeZone.getTimeZone("America/Denver"); // same as Broomfield
    TimeZone tzboston  = TimeZone.getTimeZone("America/New_York");   // same as Boston

An important thing to note are the comments saying "same as NNN". I think its unfortunate that the names by which you retrieve TimeZone objects use specific cities, but they're often not the city I'm interested in. This is because each time zone covers a vertical area and the TimeZone names are based on some specific city in that vertical area. So rather than America/Boston we have America/New_York or instead of Asia/Bangalore we have Asia/Calcutta.

This is fine if you understand the time zones in the country you're interested in. In my case St. Petersburg Russia isn't a TimeZone name and I don't know enough about Russia to know which other city to use. Fortunately one of my coworkers is from Russia, and he happened to walk by just as I was wondering about this and I asked him. He says Moscow is the correct city to use. I also had a similar problem with Beijing (turns out Shanghai is probably the correct answer).

This code prints a list of TimeZone names

        String[] tzlist = TimeZone.getAvailableIDs();
        Arrays.sort(tzlist);
        for (String tz : tzlist) {
            System.out.println(tz);
        }

The next is, printing the time for each selected time zone.

    public static void printTimeZone(TimeZone tz) {
        GregorianCalendar cal = new GregorianCalendar(tz);
        System.out.println(tz.getDisplayName()+" ["+tz.getID()+"]"
            +": "+cal.get(Calendar.MONTH)
            +" "+cal.get(Calendar.DAY_OF_MONTH)
            +", "+cal.get(Calendar.YEAR)
            +" @ "+cal.get(Calendar.HOUR_OF_DAY)
            +":"+cal.get(Calendar.MINUTE)
            +":"+cal.get(Calendar.SECOND)
            +" "+cal.get(Calendar.ZONE_OFFSET)/(60*60*1000));
    }

That gives me some nice output as below. I could have made a Formatter, I suppose to straighten it out even better.

Pacific Standard Time [America/Los_Angeles]: 11 5, 2005 @ 14:21:5 -8
Mountain Standard Time [America/Denver]: 11 5, 2005 @ 15:21:5 -7
Eastern Standard Time [America/New_York]: 11 5, 2005 @ 17:21:5 -5
Greenwich Mean Time [Europe/Dublin]: 11 5, 2005 @ 22:21:5 0
Greenwich Mean Time [Europe/London]: 11 5, 2005 @ 22:21:5 0
Central European Time [Europe/Prague]: 11 5, 2005 @ 23:21:5 1
Moscow Standard Time [Europe/Moscow]: 11 6, 2005 @ 1:21:5 3
India Standard Time [Asia/Calcutta]: 11 6, 2005 @ 3:51:5 5
Novosibirsk Time [Asia/Novosibirsk]: 11 6, 2005 @ 4:21:5 6
Hong Kong Time [Asia/Hong_Kong]: 11 6, 2005 @ 6:21:5 8
China Standard Time [Asia/Shanghai]: 11 6, 2005 @ 6:21:5 8
Korea Standard Time [Asia/Seoul]: 11 6, 2005 @ 7:21:5 9
Japan Standard Time [Asia/Tokyo]: 11 6, 2005 @ 7:21:5 9

Now looking at this table I see a few problems.

First is the name of the month isn't printed, but instead the number. In Mustang we have added the getDisplayName method to get this automatically, and one also supplies a Locale. Without the getDisplayName method one can obviously make an array of month names, but what about localizing the month names to different languages?

The pre-getDisplayName implementation looks like this:

    static final String months[] = {
        "January", "February", "March", "April", "May",
        "June", "July", "August", "September", "October",
        "November", "December"
    };
...
            +": "+months[cal.get(Calendar.MONTH)]
...

Second, what about the three-letter code for the timezone? I don't see a method anywhere to retrieve it.

The last is the printing of the timezone offset isn't quite right.

So, with a little bit of work one can get pretty close to a simple tool to solve the problem I started with. We don't have a fancy-schmancy worldclock style display, but at least it lets me know what time it is.

UPDATE: I found out how to get the three-letter timezone code:

...
   +" ["+tz.getDisplayName(tz.inDaylightTime(cal.getTime()), TimeZone.SHORT, lc)+"]"
...

Source: (web.archive.org) weblogs.java.net

Comments

i already ported the original to Java. you can get it as part of the linked .tgz at http://www.jessies.org/~enh/software/salma-hayek/ and run it with something unfriendly like "java -cp classes/ e.toys.world.WorldClock".

you'll also need to download NASA's land_ocean_ice_2048.jpg and land_ocean_ice_lights_2048.jpg and stick them in ~/Desktop.

i didn't say it was easy, but it's easier than porting it yourself!

Posted by: elliotth on December 05, 2005 at 04:25 PM

If you haven't seen it, you may be interested in Joda-Time - http://joda-time.sourceforge.net. We have more up to date time zone information than the JDK for one thing :-)

Posted by: scolebourne on December 06, 2005 at 06:02 AM

Since a few time-interested folks may be looking at this thread, I want to hijack it for a question that's been bugging me for a couple of months. What is going to happen to Java runtimes when US daylight savings rules change in 2007? As I understand it, installations have the rules for each timezone hardcoded in the TimeZone class. Seems like everyone will have to upgrade JREs. Is Microsoft going to patch XP, or was this a conspiracy to compel an upgrade to Vista?

Posted by: erickson on December 06, 2005 at 09:30 AM

erickson, The timezone rules are hard coded in the JDK. This means that all existing JDKs are broken wrt this change. You can 'fix' it by creating your own rules using the JDK TimeZone subclasses but this will be repeated by many people and isn't simple. This problem is already faced by some other countries, eg Brazil, where the rules are only specified one year at a time. This is one reason why Joda-Time is useful, as it has its own set of time zone rules, and you can choose to update them at any time just by running an ant script with the latest raw Olson data.

Posted by: scolebourne on December 06, 2005 at 09:44 AM

Time zone data is no longer hard coded since 1.4.0. The Java implementation of zic (zone info compiler) isn't public yet, though. The 2007 U.S. DST rule change support went to:

Java SE 6 (Mustang) b58 (tzdata2005n) J2SE 5.0u6 b03 (tzdata2005m) 1.4.2_11 b01 (tzdata2005n)

However, 1.3.1 does hard code time zone data based on SimpleTimeZone. We are looking into a way to workaround, er..., support it in 1.3.1_xx. Posted by: mokutsu on December 06, 2005 at 09:29 PM

"Without the getDisplayName method one can obviously make an array of month names, but what about localizing the month names to different languages?"

What about using SimpleDateFormat?

        Calendar cal = new GregorianCalendar();
        DateFormat df = new SimpleDateFormat("EEEE, d MMMM yyyy");
        System.out.println(df.format(cal.getTime()));
        
        Locale.setDefault(Locale.FRANCE);

        df = new SimpleDateFormat("EEEE, d MMMM yyyy");
        System.out.println(df.format(cal.getTime()));

Gives us the following:

Wednesday, 7 December 2005
mercredi, 7 décembre 2005

Posted by: gressil on December 07, 2005 at 02:03 AM

Oh, ah, I didn't use SimpleDateFormat because I didn't see it. I remembered there was a class name like that, but I was looking in java.util and I see now that it's in java.text.

Posted by: robogeek on December 07, 2005 at 11:14 AM

About the Author(s)

David Herron : David Herron is a writer and software engineer focusing on the wise use of technology. He is especially interested in clean energy technologies like solar power, wind power, and electric cars. David worked for nearly 30 years in Silicon Valley on software ranging from electronic mail systems, to video streaming, to the Java programming language, and has published several books on Node.js programming and electric vehicles.