Am not a guru when it comes to dealing with dates and timezone and it just got worse when I was dealing with Java Library to get done with a date related task. Job was to display current date in IST (India) timezone. As it may sound to be quite simple, it did give me few sweaty hours with my system on EST timezone. Let's talk code:
public class DateConversionTest {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
DateFormat dateFormat = new SimpleDateFormat();
dateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
//L1: Convert date to IST timezone
String dateString = dateFormat.format(cal.getTime());
System.out.println(dateString);
//L2: Use parse method to get Date object, as advised by java.util.Date
try{
System.out.println("Date using parse method: "+
dateFormat.parse(dateString));
}catch (ParseException e) {
e.printStackTrace();
}
//L3: Use date constructor
System.out.println("Date using constructor: " +new Date(dateString));
}
}
SimpleDateFormat provides the capability to convert date to particular timezone. I could have used Calendar for it, but let me get to it later why I opted out . The string "dateString" from DateFormat(//L1) provided the correct date in IST timezone. I had a mandate of returning "Date" object so the next step was to convert this to a Date object.
I looked up the javadoc and the constructor of java.util.Date with String parameter was deprecated and said "Deprecated. As of JDK version 1.1, replaced by DateFormat.parse(String s)."
As per the doc, I used the alternative but to my surprise the above method returned back my system date in EST timezone(look at output for details). Instead of using DateFormat I tried to replace the program with Calendar object but Calendar.getTime() would also return date in my system timezone inspite of converted dated already provided to it. This was the reason I did not use it in my test code.
After much of experiments, I tried to use the date constructor with String parameter(//L3) which finally returned the expected date in IST as stored in "dateString" object.
Output:
String date from formatter: 1/25/11 2:35 AM
Date using parse method: Mon Jan 24 16:05:00 EST 2011
Date using constructor: Tue Jan 25 02:35:00 EST 2011
Why should a deprecated constructor work as expected and DateFormat worked so strangely?
With my research it looked like DateFormat.parse internally works using Calendar object which returns date (Calendar.getTime()) based on the timezone of the JVM. (TimeZone.getDefault()). If I alter this, I get date in expected timezone. Note, JavaDoc does state that it returns date in UTC format but it always return in default timezone of JVM.
When a certain date is already provided by developer, shouldn't this auto conversion avoided by Java? I would like to hear how other developers would solve it in more effective way as it clearly doesn't leave me satisfied.