Java Development News:

Countdown to DST 2007

By Paulo Caroli

01 Feb 2007 | TheServerSide.com

Countdown to DST 2007

In case you have not yet act on the U.S. Daylight Saving Time (DST) change for 2007 you should definitely read this article. However, if you have already updated the Java Runtime Environment (JRE) on whichyour Java application runs, this article will provide you with a simple mechanism that will validate the JRE correctness regarding the DST transition dates.

U.S. 2007 DST changes

Most of the United Stateshas observed DST from the first Sunday of April to the last Sunday of October since 1966. In August 2005, these long-standing rules changed when the Energy Policy Act of 2005 was signed by President George W. Bush and approved by the Congress. Beginning in 2007, most of the U.S. will observe DST on the second Sunday in March and revert to standard time on the first Sunday in November.

DST change and Java Application

Systems and applications that process dates and times using the U.S. DST rules will be affected by theEnergy Policy Act of 2005. In Java-based applications there are three main areas that might require patch or update because of the DST rule change:

  • The JRE
  • The OS system
  • The Database

Most likely every system vendor in the U.S. will make available a patch or an updated release to fix the U.S. 2007 DST rule change. Make sure to look for specific database and OS system patches or update releases which will fix this DST rule change.

The DST Patch web site has a list of affected products:

http://www.dstpatch.com/

JRE updates with the correct DST are available at:

http://Java.sun.com/developer/technicalArticles/Intl/USDST/

As an alternative to updating the full JRE, Sun provides a tool - tzupdater - to modify the time zone properties within the existing JRE. This tool can be downloaded from:

http://java.sun.com/javase/downloads/index.jsp

The JRE, TimeZone, and DST

In the Java platform, the Java.util.TimeZone abstract class represents a time zone and is used to produce local time for a particular global time zone. The TimeZone consists of three basic pieces of information: an ID, a time zone offset, and the logic that is necessary to deal with DST. For example, PST, the time zone ID for Pacific Standard Time with time zone offset UTC/GMT -8 hours, and DST logic that establishes the DST period from the second Sunday of March to the first Sunday of November.

The Java Runtime Environment (JRE) stores the time zone IDs, offsets, and the rules about DST observance around the globe. Older JREs will have outdated DST rules that will be superseded by the Energy Policy Act of 2005. As a result, applications running on older JREs may report incorrect time from March 11, 2007 through April 2, 2007 and from October 29, 2007 through November 4, 2007.

Validate the JRE DST rules

In my current project multiple servers host several Java applications. Because of compatibility issuesinolder applications we are unable to maintain the same JRE release for all the servers. In order to ensure the U.S. 2007 DST fix, JRE patches and newer JRE releases were propagated to all the servers.

After updating the JREs we needed a mechanism to confirm the U.S. 2007 DST correctness for each JRE. We then created CheckDST, a Java class that validates the DST start and end date of a time zone.

import java.util.TimeZone;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * CheckDST validates the DST period for a given time zone
 * Sample usage >java CheckDST PST 03/11/2007 11/04/2007
 */
public class CheckDST{

 // sample DST data - 2007 DST data for PST Timezone
 private static final String PST_2007_START_DST = "03/11/2007";
 private static final String PST_2007_END_DST  = "11/04/2007";
 private static final String PST_TIMEZONE_LOCATION  = "PST";

 private static final  String DATE_FORMAT = "MM/dd/yyyy";

 private Date startDST;
 private Date endDST;
 private String startDSTString;
 private String endDSTString;
 private TimeZone timeZone;
 private String timezonLocation;

 public CheckDST(String timezonLocation, String entryDate, String exitDate)
   throws Exception {
  this.timezonLocation = timezonLocation;
  this.startDSTString = entryDate;;
  this.endDSTString = exitDate;
  if (!isValidTimeZone(timezonLocation)){
   throw new Exception("Not a valid Timezone: " + timezonLocation);
  }
  timeZone = TimeZone.getTimeZone(timezonLocation);
  startDST = this.stringToDate(entryDate, DATE_FORMAT);
  endDST = this.stringToDate(exitDate, DATE_FORMAT);
 }

 public static void main(String[] args) {
  try {
   CheckDST checkDST;
   if (args.length==0){
    checkDST = new CheckDST(PST_TIMEZONE_LOCATION, PST_2007_START_DST,
      PST_2007_END_DST);
   }else{
    checkDST = new CheckDST(args[0], args[1], args[2]);
   }
   System.out.println("Testing JRE TimeZone DST transitioning for: "
     + checkDST.timezonLocation);
   if (checkDST.entryDSTWorksProperly()){
    System.out.print("SUCCESS ");
   }else{
    System.out.print("FAILURE ");
   }
   System.out.println("for DST entry date " + checkDST.startDSTString);

   if (checkDST.exitDSTWorksProperly()){
    System.out.print("SUCCESS ");
   }else{
    System.out.print("FAILURE ");
   }
   System.out.println("for DST exit date " + checkDST.endDSTString);
  } catch (Exception e) {
   e.printStackTrace();
   System.out.println("Please make sure to use a valid Timezone and enter
     the date in the following format MM/dd/YY.");
   System.out.println("e.g. >java CheckDST PST 03/11/2007 11/04/2007");
  }

 }

 public static boolean dstStartDateIsTransitioningProperly(TimeZone timezone, Date  startDST){
  return (!timezone.inDaylightTime(previousDay(startDST)) &&
    timezone.inDaylightTime(dayAfter(startDST)));
 }

 public static boolean dstExitDateIsTransitioningProperly(TimeZone timezone, Date endDST){
  return (timezone.inDaylightTime(previousDay(endDST)) &&
    !timezone.inDaylightTime(dayAfter(endDST)));
 }

 public static boolean isValidTimeZone(String timezoneLocation) {
  String[] allTimeZoneIds = TimeZone.getAvailableIDs();
  boolean foundTimezone = false;
  for (int i = 0; i < allTimeZoneIds.length; i++) {
   if (timezoneLocation.equals(allTimeZoneIds[i])) {
    foundTimezone = true;
    break;
   }
  }
  return foundTimezone;
 }

 public boolean entryDSTWorksProperly()   {
  return dstStartDateIsTransitioningProperly(this.timeZone, this.startDST);
 }

 public boolean exitDSTWorksProperly()  {
  return dstExitDateIsTransitioningProperly(this.timeZone, this.endDST);
 }

 private Date stringToDate(String dateStr, String dateFormat)
   throws java.text.ParseException {
  SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
  return simpleDateFormat.parse(dateStr);
 }

 private static Date previousDay(Date date) {
  return new Date(date.getTime() - 1000 * 60 * 60 * 24);
 }

 private static Date dayAfter(Date date) {
  return new Date(date.getTime() + 1000 * 60 * 60 * 24);
 }

}

As shownin the CheckDST source code, a DST period is validated by invoking the timezone. inDaylightTime(date) for a day before and a day after the DST start and the DST end date. In case the transition is unsuccessful, a failure message indicates the problem.

For example, when running >java CheckDST PST 03/11/2007 11/04/2007 in a JRE with outdated DST rules the system output will be the following:

When running >java CheckDST PST 03/11/2007 11/04/2007 in JRE 1.5.0_08 (current DST rules) the system output will be the following:

The command javaCheckDST <timezoneID> <start DST> <end DST> will test any time zone DST rule. For example, javaCheckDST CET 03/25/2007 03/25/2007 validates the DST for the CET, the Central European Time time zone against 03/25/2007, the DST start date, and 10/28/2007, the DST end date.

If CheckDST is invoked with no arguments, PST03/11/2007 11/04/2007(the 2007 DST rule for PST time zone) are used as implicit parameters respectively for the time zone ID, DST start date and DST end date.

Unit Test the DST rules

The following code representsa sample JUnit-based unit test for validating the DST rules for a time zone.

import junit.framework.TestCase;

public class PST2007DSTTest extends TestCase {

 // excpected U.S. DST entry and exit days
 private static final String US_2007_START_DST = "03/11/2007";
 private static final String US_2007_END_DST  = "11/04/2007";

 public void testDSTTransition() {
  try {
   CheckDST checkDST = new CheckDST("PST", US_2007_START_DST, US_2007_END_DST);
   assertTrue(checkDST.entryDSTWorksProperly());
   assertTrue(checkDST.exitDSTWorksProperly());
  } catch (Exception e) {
   fail(e.getMessage());
  }
 }
}

The unit test presented above validates the PST time zone for the expected 2007 DST period. When executed in a JRE with outdated U.S. 2007 DST rules the unit test will fail; on the other hand, when executed against a JRE with valid U.S. 2007 DST rules the unit test WILL pass.

Conclusion

The CheckDST presented in this article provides an easy way for validating the JRE against DST transitioning data. I haveshowed youhow to use the CheckDST in command line as well as a JUnit-based unit test. Make sure to verify the other parts of your System against the U.S. 2007 DST.

The correct DST entry and exit dates mustbe selected from trusted sources. For this article, the dates were selected from The World Clock web site: www.timeanddate.com/worldclock/full.html .

Bio

Paulo Caroli, www.caroli.org, is an application architect for ThoughtWorks, an outstanding application development and consulting company. Paulo has a master's degree in software engineering and is a Sun Certified Architect for Java Technology, but moreover, following ThoughtWorks leadership, has been successfully applying Agile techniques such as XP and TDD.

Reference

Downloaded CheckDST.class
http://www.geocities.com/paulocaroli/src/CheckDST.class

DST Patch web site
http://www.dstpatch.com/

U.S. 2007 DST change article by Sun
http://Java.sun.com/developer/technicalArticles/Intl/USDST/

tzupdater, JRE DST update tool
http://java.sun.com/javase/downloads/index.jsp

The World Clock web site
www.timeanddate.com/worldclock/full.html .