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();
        for (String tz : tzlist) {
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.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)+"]"