Wednesday, June 22, 2011

Local time of any country based on GMT with Java

In a recent change request for one application i was working on, it was requested to update the time stamp a certain task was done based on the location of the user. We have a separate Country table stored which has the GMT action and the GMT off set defined in minutes.

I was searching for a way to get the local time of a certain country using the Calendar object. There were many sites that gave various information which led to me finding a work around by testing with various parameters. This is what i came up with in the end.


Following i have encapsulated the final outcome into a method so it would be easier to understand and use if anyone ever needs it;

 public static final String GMT_STR = "GMT";
	public static final String COLON_STR = ":";
	public static final String ZERO = "0";
	
	/**
	 * This method will take as parameters the GMT off set in minutes
	 * as well as the GMT actions i.e + or - and based on that will
	 * output the calendar object representing that specific time in that
	 * location. The GMT is defined in minutes so that the calculation is
	 * simplified.
	 * @param gmtOffSetMins 
	 * @param gmtAction
	 * @return
	 */
	public static Calendar getLocalTime(int gmtOffSetMins,
			String gmtAction) {

		// This will get the quotient part of the division
		int gmtHours = (gmtOffSetMins / 60);
		// This will get the remainder of the division which will give us the
		// minutes portion
		Integer gmtMins = Integer.valueOf((gmtOffSetMins % 60));
		if (gmtMins < 10) {
			gmtMins = Integer.valueOf("0"+gmtMins);
		}
		
		/**
		 * This will produce a String in the format of GMT+5:30
		 */
		String gmtString = null;
		if (gmtMins == 0) {
			gmtString = GMT_STR + gmtAction + gmtHours + COLON_STR + gmtMins+ ZERO;
		} else {
			gmtString = GMT_STR + gmtAction + gmtHours + COLON_STR + gmtMins;
		}

		/**
		 * This calendar object will give you the local time of the specific country
		 * based on the gmt offset hours and the action passed. 
		 */
		return Calendar.getInstance(TimeZone.getTimeZone(TimeZone.getTimeZone(
				gmtString.trim()).getID()));

	}

Thats all you need. The returned calendar will have the local time of that specific country depending on the GMT minutes and action you passed. Note that i have given the GMT in minutes to ease the calculation. Normally you will get the GMT in hours so you will need to convert that to minutes.

Ofcourse when daylight savings come into play you will need to change this accordingly. For our application this was not needed so we didnt do that change. To handle daylight savings we will have to keep the day light saving changes somewhere and deduct or add appropriately to the base GMT.

If you guys know anyway of doing this in a much simpler way or you have any suggestions for improvements pls do leave by a comment which is as always much appreciated.

Cheers Guys!!!!

8 comments:

  1. BUG:
    Line 24:
    gmtMins = Integer.valueOf(gmtMins + "0");

    gmtMins = Integer.valueOf("0" + gmtMins);

    ReplyDelete
  2. Hi Ivan,

    Thx for pointing that out. Appreciate it. Fixed :)

    ReplyDelete
  3. And in the comment, it is gmtOffSetHrs , but in code, it is gmtOffSetMins

    ReplyDelete
  4. Hi Carfiel,

    Thx for the look out. I actaully used hours before and later made it minutes to make calculations easier. Thx for leaving the comment and increasing the level of accuracy of the post.

    Cheers

    ReplyDelete
  5. I live in NY and I can't figure out what GMT Time I should put as my settings on here. Can you help me?

    ReplyDelete
  6. Hi NYynakeeGIRL01,

    Check this site:http://www.timeanddate.com/worldclock/city.html?n=179

    That will give you the value you should pass to the method. If you have any other query leave by a comment.

    ReplyDelete
  7. Two suggestions:

    First, consider simply storing the TimeZone id for the country rather than the offset. In the simple case it saves you the math and string manipulation. More importantly it gives you a lot more flexibility.

    Second, and here's where the flexibility comes in, TimeZones are usually not fixed offsets. Little things like Daylight Savings rules come into play. Now I'm not familiar with your application, so I con't know why DST doesn't apply in your case. But in most it does, and as you say, the code above doesn't deal with that case.

    For example, if you wanted to store the TimeZone for a fixed offset, ignoring daylight time, for New York, you could store "GMT:-05:00" (what the code above generates) or simply "EST" as the zone. But if you wanted dst aware behavior, simply store "America/New_York".

    Let the underlying zoneinfo database do it's job. Don't try to out think it.

    See http://en.wikipedia.org/wiki/Tz_database http://www.twinsun.com/tz/tz-link.htm and http://www.oracle.com/technetwork/java/javase/timezones-137583.html

    ReplyDelete
  8. Hi,
    Thx alot for the suggestions. Yes you are correct, that would have been the elegant way of solving the problem. i did not go for that as i wanted to use what we already had(which was the gmt offset) within a table in our database). The long term and best solution is that as you highlighted.

    Thx alot for leaving by a comment. Appreciate it.

    Cheers

    ReplyDelete