Wednesday, December 12, 2012

Date for TimeZone, or google first.

This one is about: why you should use google before start writing code!

How effectively get system Date for different TimeZone? I found few different approaches: using over-complicated String operations, SimpleDateFormat, and Calendar. Here I want to share my thoughts and find the best one  ;-)

Below you could find 3 different examples:

  1. Using String operation
  2. SimpleDateFormat
  3. Calendar

Yes, as you probably expect - Calendar will win ;-)

 

String example 1:

 /**
  * This method gets the system date for the passed time zone
  * 
  * @param strTimeZone
  * @return
  */
 public static Date getSystemDateForTimeZoneString(String strTimeZone) {

  Date systemDate = null; 

  try {
   TimeZone timeZone = TimeZone.getTimeZone(strTimeZone);
   Calendar cal = GregorianCalendar.getInstance(timeZone);

   String monthStr = null;
   String dayStr = null;
   String hoursStr = null;
   String minStr = null;
   String secStr = null;

   int month = cal.get(Calendar.MONTH) + 1;

   if (month < 10) {
    monthStr = "0" + month;
   } else {
    monthStr = "" + month;
   }
   int day = cal.get(Calendar.DAY_OF_MONTH);
   if (day < 10) {
    dayStr = "0" + day;
   } else {
    dayStr = "" + day;
   }
   int year = cal.get(Calendar.YEAR);
   int hours = cal.get(Calendar.HOUR_OF_DAY);
   if (hours < 10) {
    hoursStr = "0" + hours;
   } else {
    hoursStr = "" + hours;
   }
   int mins = cal.get(Calendar.MINUTE);
   if (mins < 10) {
    minStr = "0" + mins;
   } else {
    minStr = "" + mins;
   }

   int sec = cal.get(Calendar.SECOND);
   if (sec < 10) {
    secStr = "0" + sec;
   } else {
    secStr = "" + sec;
   }

   String currentDate = monthStr + "-" + dayStr
     + "-" + year + " " + hoursStr + ":" + minStr
     + ":" + secStr;

   SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
   try {
    systemDate = dateFormat.parse(currentDate);
   } catch (ParseException e) {
    e.printStackTrace();
   }

  } catch (Exception e) {
   e.printStackTrace();
  }
  return systemDate;
 }

 

Second implementation using SimpleDataFormat:

 public static Date getSystemDateForTimeZoneSDF(final String strTimeZone) {
  Date systemDate = new Date();
  SimpleDateFormat dateFormat = new SimpleDateFormat(
    "MM-dd-yyyy HH:mm:ss");
  dateFormat.setTimeZone(TimeZone.getTimeZone(strTimeZone));
  String timeZonedSystemDate = dateFormat.format(new Date());
  dateFormat.setTimeZone(TimeZone.getDefault());
  try {
   systemDate = dateFormat.parse(timeZonedSystemDate);
  } catch (ParseException e) {
   e.printStackTrace();
  }
  return systemDate;
 }

 

And last one, Calendar:

 

 public static Date getSystemDateForTimeZoneCalendar(final String strTimeZone) {
  Date date = new Date();
  TimeZone timeZone = TimeZone.getTimeZone(strTimeZone);

  // Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
  long msFromEpochGmt = date.getTime();

  // gives you the current offset in ms from GMT at the current date
  int offsetFromUTC = timeZone.getOffset(msFromEpochGmt);

  // create a new calendar in GMT timezone, set to this date and add the offset
  Calendar localCalendar = Calendar.getInstance(TimeZone.getDefault());
  localCalendar.setTime(date);
  localCalendar.add(Calendar.MILLISECOND, offsetFromUTC);

  return localCalendar.getTime();
 }

 

Lets run some test code:

  long start1 = System.currentTimeMillis();

  for (int i = 1; i < 100; i++) {
   getSystemDateForTimeZoneString("GMT-2:00");
  }
  long end1 = System.currentTimeMillis();
  System.out.println("String OUTPUT::" + getSystemDateForTimeZoneString("GMT-2:00")
    + " takes:" + (end1 - start1) + " ms");

  long start2 = System.currentTimeMillis();
  for (int i = 1; i < 100; i++) {
   getSystemDateForTimeZoneSDF("GMT-2:00");
  }
  long end2 = System.currentTimeMillis();
  System.out.println("SDF OUTPUT::" + getSystemDateForTimeZoneSDF("GMT-2:00")
    + " takes:" + (end2 - start2) + " ms");

  long start3 = System.currentTimeMillis();
  for (int i = 1; i < 100; i++) {
   getSystemDateForTimeZoneCalendar("GMT-2:00");
  }
  long end3 = System.currentTimeMillis();
  System.out.println("Calendar OUTPUT::" + getSystemDateForTimeZoneCalendar("GMT-2:00")
    + " takes:" + (end3 - start3) + " ms");
 }

 

 

And output:

String      OUTPUT::Tue Jan 08 10:12:08 GMT 2013 takes: 127 ms
SDF         OUTPUT::Tue Jan 08 10:12:08 GMT 2013 takes:  19 ms
Calendar   OUTPUT::Tue Jan 08 10:12:08 GMT 2013 takes:   3 ms

 

Summary:

First thought that comes when I see some code using String calculations is: do not reinvent the wheel - google!!

Of course - as expected - not String solutions are much better - if you have application that is quite a lot using function like that  - you can save a lots of processing time.