Tuesday, January 6, 2015

Introduce date and timezone in JDK

This article shares some knowledge I known about TimeZone in JDK.

  1. TimeZone

Known that the whole world has divided to lots of TimeZones. Each TimeZone is a region that having a uniform standard time that is a relative time from GMT/UTC for legal, commercial, sociable purposes. E.g. "Asia/Shanghai" is GMT+8, and its time is forward 8 hours from GMT.

  1. DST
Daylight Saving Time is a way of making better use of the natural daylight by setting your clock forward one hour during the summer months, and back again in the fall. The dates of forward and back are not confirmed, they depend on TimeZone. Surely not every TimeZone supports DST. E.g. in 2015, forward and back days of "Europe/London" are "Sunday, 29 March, 01:00" and "Sunday, 25 October, 02:00", but "American/LosAngeles" are "Sunday, 8 March, 02:00" and "Sunday, 1 November, 02:00".
  1. Relative Classes in JDK
Acquired millisecond via System.currentTimeMillis() is a really time point that is number of milliseconds since January 1, 1970, 00:00:00 GMT. So wherever are you, you will receive same millisecond value to in a time point. E.g. executing the code in London, Los_Angeles, Shanghai at same time, they will return the same number of milliseconds.

  • java.util.Date
The class represents a specific instant in time, with millisecond precision. If you create a new java.util.Date object, it assigns JVM's TimeZone. 
(1) toString() method will format the time in JVM's TimeZone and format string include date and time parts, e.g. "Wed Jan 07 14:00:58 CST 2015". 
(2) getTime() will return the number of milliseconds since January 1, 1970, 00:00:00 GMT. 
  • java.sql.Date
This class is a thin wrapper of java.util.Date with millisecond precision, so that allows JDBC to identify it as SQL DATE value.  To confirm with the SQL DATE, setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated. The milliseconds value represents same as java.util.Date (the number of milliseconds since January 1, 1970, 00:00:00 GMT).
(1) toString() method will format the date in "yyyy-mm-dd", e.g."2015-01-07".


  • java.sql.Timestamp
This class is a thin wrapper of java.util.Date with nanoseconds precision, so allows JDBC to identify it as SQL TIMESTAMP value. 
(1) The returned value of getTime() includes fractional seconds. 
(2) toString() method formats the time in "yyyy-mm-dd hh:mm:ss.fffffffff" where "fffffffff" indicates nanoseconds, e.g. "2015-01-07 14:11:25.017"
  • Calendar
Calendar is used to convert between a special instant time and a set of Calendar fields such as year, month, day of month, hour, minute, second. It can pass a specific TimeZone via constructor or setTimeZone.
(1) Calendar.ZONE_OFFSET 
The field represents the raw offset for specified TimeZone in Calendar. For example, timezone is "Europe/London", the time is 2015-01-01, the value of Calendar.ZONE_OFFSET field will be 0.
(2) Calendar.DST_OFFSET 
The field represents the DST offset of time for specified TimeZone in Calendar. For example, timezone is "Europe/London", case one: time is 2015-01-01, the value of Calendar.ZONE_OFFSET field will be 0; case two: time is 2015-06-01 that is in DST, the value of Calendar.ZONE_OFFSET field will be 3600000.
junit test case example:
   @Test
   public void test_timezone_dst_offset(){
      Calendar cal_DST_End = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
      cal_DST_End.set(Calendar.YEAR, 2015);
      cal_DST_End.set(Calendar.MONTH, 0);
      cal_DST_End.set(Calendar.DAY_OF_MONTH, 1);

      Calendar cal_DST_Start = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
      cal_DST_Start.set(Calendar.YEAR, 2015);
      cal_DST_Start.set(Calendar.MONTH, 5);
      cal_DST_Start.set(Calendar.DAY_OF_MONTH, 1);
      
      assertEquals(0,cal_DST_Start.get(Calendar.ZONE_OFFSET));
      assertEquals(0,cal_DST_End.get(Calendar.ZONE_OFFSET));
      assertEquals(0,cal_DST_End.get(Calendar.DST_OFFSET));
      assertEquals(3600000,cal_DST_Start.get(Calendar.DST_OFFSET));
  }
  • TimeZone
TimeZone represents a time zone offset and also figure out daylight saving time.
(1) getTimeZone(String ID), you need to pass a ID of expected time zone, such as "America/Los_Angeles"
(2) getOffset(long date), Returns the offset of the passed date in specified TimeZone. If the specified date is in effect in daylight saving time, the offset value is adjusted with daylight saving time. For example, timezone is "Europe/London", case one: time is 2015-01-01, the returned offset value will be 0; case two: time is 2015-06-01 that is effect in DST, the value will be 3600000.
(3) getRawOffset, Returns the amount of time to add to UTC to get standard time in specified time zone. This does not include the daylight saving time. The offset value equals with the value of Calendar.ZONE_OFFSET.
(4) getDSTSavings(), Returns the amount of time to add to local standard time to get local wall clock time. The default value always returns 3600000 milliseconds if the daylight saving time is effect, or returns 0.
junit test case example:
   @Test
   public void test_timezone_dst_offset(){
      Calendar cal_DST_End = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
      cal_DST_End.set(Calendar.YEAR, 2015);
      cal_DST_End.set(Calendar.MONTH, 0);
      cal_DST_End.set(Calendar.DAY_OF_MONTH, 1);

      Calendar cal_DST_Start = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
      cal_DST_Start.set(Calendar.YEAR, 2015);
      cal_DST_Start.set(Calendar.MONTH, 5);
      cal_DST_Start.set(Calendar.DAY_OF_MONTH, 1);
      
      assertEquals(3600000,TimeZone.getTimeZone("Europe/London").getDSTSavings());//DST effect
      assertEquals(0, TimeZone.getTimeZone("Asia/Shanghai").getDSTSavings());//DST not effect

      assertEquals(0,TimeZone.getTimeZone("Europe/London").getRawOffset());          
      assertEquals(3600000,TimeZone.getTimeZone("Europe/London").getOffset(cal_DST_Start.getTimeInMillis()));
assertEquals(0,TimeZone.getTimeZone("Europe/London").getOffset(cal_DST_End.getTimeInMillis()));
   }

No comments:

Post a Comment