menu

Wednesday, October 15, 2014

Using Date and Time with Zone and DST Offset Values In Java

Using Date and Time with Zone and DST Offset Values In JavaIntroduction:                                                                                                                                       
     In java applications, the preferred way of using Date and Time calculations is to use Calendar class or Joda library.When we use Calendar or Joda,since the Zone and DST offset values are automatically taken in the consideration, especially adding or subtracting Date or Time objects will be less error prone. However, since the Calendar and Joda library are more complex than standart Date class and the since the cost of creating these objects are much more heavier than creating standart Date class, in some situations we may want to do Date and Time calculation by ourselves. In this write we point out the tricks of using standart Date and Time objects.

1.) Zone difference when substracting Time and Date:
     As you know, Turkey is in GMT(Greenwich Mean Time) +2 Time Zone.When we use getTime() method of Date or Time class we get the time from "epoch"(01.01.1970) to now in millisecond. If we use this time to construct a new Date or Time object we get a result with added 2 hours since we are in +2 Time Zone. i.e;



SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss.SSS");
SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm:ss.SSSZ");
Date d = sdf.parse("01.01.2014 23:00:00.000");
Date d1 = sdf.parse("02.01.2014 01:00:00.000");
Date diff = new Date(d1.getTime() - d.getTime());
System.out.println("diff between two dates is: " + sdfTime.format(diff));


If we look at the output of this code fragment wee see 4 instead of 2.To solve this issue,either set GMT+0 to Formatter object like;
sdfTime.setTimeZone(TimeZone.getTimeZone("Etc/GMT+0"))
or substract 2 hours when constructing Date object like;
Date diff = new Date(d1.getTime()-d.getTime()-2*60*60*1000).

The same situation is also valid when using Calendar class, and we have to give GMT+0 time zone.

In addition the TimeZone can be given in the JVM level.
TimeZone.setDefault(TimeZone.getTimeZone("Etc/GMT+0"));

2.) DST (Daylight Saving Time):
     As we know, to utilize day light clocks are forwarded 1 hour at each spring and backwarded 1 hour at each autumn. i.e; at 2014 in turkey the clocks are forwarded 1 hour at 31 March 2014 Monday and they will be backwarded at 26 October 2014 Sunday. That means at 31 March 2014 the day will be 23 hours instead of 24 hours and at 26 October 2014 the day will be 25 hours. If we are using Date and Time classes instead of Calendar we have to consider this situations.Lets explain it with an example;

SimpleDateFormat sdfAmbigious = new SimpleDateFormat("dd.MM.yyyy");
Date twentySixOctober2014 = sdfAmbigious.parse("26.10.2014");
Date twentySevenOctober2014 = new Date(twentySixOctober2014 .getTime() + (24 * 60 * 60 *1000));
System.out.println("We would have been at the next day after adding 24 hours : " + sdfAmbigious.format(twentySevenOctober2014));
If we look at the output, although we add 24h we still in the 26th October.That's because 26th October is a 25h day. 
Similarly, at the 23h day, just by adding 23h we can go to the next day.

Lets consider we are doing critical day calculations and we let a process to be done only one time at each day.If we make the control with 24h, at a day with 25h we may accidentially let two processes(i.e; at 30th minutes and 24h 30th minutes). Similary, at a day with 23h, if we look the past 24h to check whether there is a process, we may get the process of yesterday, and we may accidentially return error to the user, although there is no process at 23h day.(i.e; if there is a process at 23:59 yesterday, if we let 24h later it will go the next day after the 23h day)

Note: In turkey since there is local elections at 30.03.2014 the clocks are forwarded 1 hour at 31.03.2014 instead of 30.03.2014. Since the JRE TimeZone normally is ruled to forward the clocks at 30.03.2014, if you don't do an update the applications will work like the clocks forwarded 1 hour at 30.03.2014(http://www.oracle.com/technetwork/java/javase/tzdata-versions-138805.html)
If you don't make the related java update, you have to add 1 hour for 30 March, and substract 1 hour at 31 March in your calculations.

Note: In time calculations the beginning of time is  01.01.1970. That is, the getTime() method of Date object will return a long value indicating a time value from 01.01.1970 to the time that the Date object represent. 01.01.1970 is generally known as "Epoch" or "Unix Time" and is firstly used in 32 bits Unix machine and standardized.Unix was developed at 1969 and the first version of it is issued at 1971.At that time epoch was choosen as 1970.With a 32 bits signed integer the maximum date that can be represented from 01.01.1970 is 19-01-2038.This case is known as 2038 problem and it will be experienced at 2038 in the machines that still using 32bits.

Note: In any case, at the applications that running on the web as client-server topology, its a must to check the Zone and DST configurations at each participating system.

Conclusion:
     Like in all programming languages,in java when dealing with Date and Time calculations, we have to carefully consider Zone and DST configurations.When we use Date and Time classes directly, we have to take care of this configurations or we may either left this job to the Calendar class (again have to give Time Zone with time calculations) or left it to JODA(http://www.joda.org/joda-time/) library. 







No comments:

Post a Comment