Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4221082

Across the European Union summer-time should end at 1 a.m. GMT.

XMLWordPrintable



      Name: mf23781 Date: 03/17/99


      Across the European Union summer-time should end at 1 a.m. GMT.

      See http://europa.eu.int/eur-lex/en/lif/en_397L0044.html for the
      Community legislation in force.

      The current code seems to make summer-time end 1 hour earlier than that.

      The code in TimeZone.java and SimpleTimeZone.java seems to indicate that
      the European directive 97/44/EC is being followed, but things don't
      quite seem to work.

      test case summer.java:

      ------------------------------------------------------------------------------------
      import java.util.*;
      import java.text.*;
      public class summer {
          public static void main(String[] args) {
              int errors = 0;

              TimeZone tGMT = TimeZone.getTimeZone("GMT" /*not "Europe/London"*/);
              TimeZone tParis = TimeZone.getTimeZone("ECT" /*"Europe/Paris"*/);
              TimeZone tIstanbul = TimeZone.getTimeZone("EET" /*"Europe/Istanbul"*/);
              Calendar cGMT = Calendar.getInstance(tGMT, Locale.UK);
              Calendar cParis = Calendar.getInstance(tParis, Locale.UK);
              Calendar cAthens = Calendar.getInstance(tIstanbul, Locale.UK);
              String ss = "dd MMMM yyyy HH:mm:ss.SSS z";
              SimpleDateFormat sdf = new SimpleDateFormat(ss);
              SimpleDateFormat sdfGMT = new SimpleDateFormat(ss);
              sdfGMT.setCalendar(cGMT);
              SimpleDateFormat sdfParis = new SimpleDateFormat(ss);
              sdfParis.setCalendar(cParis);
              SimpleDateFormat sdfAthens = new SimpleDateFormat(ss);
              sdfAthens.setCalendar(cAthens);

              Date dt;
              String s1, s2;

              cGMT.clear();
              cGMT.set(1999, 3 - 1, 28, 0, 59, 59);
              dt =cGMT.getTime();
              s1 = "Time in GMT is "+sdfGMT.format(dt);
              s2 = "Time in GMT is 28 March 1999 00:59:59.000 GMT+00:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              s1 = "Time in Paris is "+sdfParis.format(dt);
              s2 = "Time in Paris is 28 March 1999 01:59:59.000 GMT+01:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              s1 = "Time in Athens is "+sdfAthens.format(dt);
              s2 = "Time in Athens is 28 March 1999 02:59:59.000 GMT+02:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              System.out.println();

              cGMT.clear();
              cGMT.set(1999, 3 - 1, 28, 1, 00, 00);
              dt =cGMT.getTime();
              s1 = "Time in GMT is "+sdfGMT.format(dt);
              s2 = "Time in GMT is 28 March 1999 01:00:00.000 GMT+00:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              s1 = "Time in Paris is "+sdfParis.format(dt);
              s2 = "Time in Paris is 28 March 1999 03:00:00.000 GMT+02:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              s1 = "Time in Athens is "+sdfAthens.format(dt);
              s2 = "Time in Athens is 28 March 1999 04:00:00.000 GMT+03:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              System.out.println();

              cGMT.clear();
              cGMT.set(1999, 10 - 1, 31, 0, 59, 59);
              dt =cGMT.getTime();
              s1 = "Time in GMT is "+sdfGMT.format(dt);
              s2 = "Time in GMT is 31 October 1999 00:59:59.000 GMT+00:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              s1 = "Time in Paris is "+sdfParis.format(dt);
              s2 = "Time in Paris is 31 October 1999 02:59:59.000 GMT+02:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              s1 = "Time in Athens is "+sdfAthens.format(dt);
              s2 = "Time in Athens is 31 October 1999 03:59:59.000 GMT+03:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              System.out.println();

              cGMT.clear();
              cGMT.set(1999, 10 - 1, 31, 1, 00, 00);
              dt =cGMT.getTime();
              s1 = "Time in GMT is "+sdfGMT.format(dt);
              s2 = "Time in GMT is 31 October 1999 01:00:00.000 GMT+00:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              s1 = "Time in Paris is "+sdfParis.format(dt);
              s2 = "Time in Paris is 31 October 1999 02:00:00.000 GMT+01:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              s1 = "Time in Athens is "+sdfAthens.format(dt);
              s2 = "Time in Athens is 31 October 1999 03:00:00.000 GMT+02:00";
              System.out.println(s1);
              if (!s1.equals(s2)) {
                  System.out.println("Error: expected "+s2);
                  ++errors;
              }

              System.out.println();



              System.out.println("Testing for summer time change-over through the year - please wait");

              SimpleDateFormat sdfParis2 = new SimpleDateFormat("z");
              sdfParis2.setCalendar(cParis);

              cGMT.clear();
              cGMT.set(1999, 1 - 1, 1, 0, 0, 0);
              dt =cGMT.getTime();
              long l1 = dt.getTime();

              cGMT.clear();
              cGMT.set(2000, 1 - 1, 1, 0, 0, 0);
              dt =cGMT.getTime();
              long l2 = dt.getTime();

              Date dd = new Date(l1);

              System.out.println("Time in GMT is "+sdfGMT.format(dd));
              System.out.println("Time in Paris is "+sdfParis.format(dd));
              String ssref = sdfParis2.format(dd), sx = null;
              System.out.println(ssref);
              Date pd = null;
              for (long l3 = l1; l3 < l2; l3 += 10000) {
                 dd = new Date(l3);
                 sx = sdfParis2.format(dd);
                 if (!sx.equals(ssref)) {
                     System.out.println();
                     System.out.println("Time in GMT is "+sdfGMT.format(pd));
                     System.out.println("Time in Paris is "+sdfParis.format(pd));
                     System.out.println("Time in GMT is "+sdfGMT.format(dd));
                     System.out.println("Time in Paris is "+sdfParis.format(dd));
                     ssref = sx;
                 }
                 pd = dd;
              }

              if (errors > 0) throw new RuntimeException("" + errors + " error(s) detected");
          }
      }

      ------------------------------------------------------------------------------------

      Output is:-


      Time in GMT is 31 October 1999 00:59:59.000 GMT+00:00
      Time in Paris is 31 October 1999 01:59:59.000 GMT+01:00
      Error: expected Time in Paris is 31 October 1999 02:59:59.000 GMT+02:00
      Time in Athens is 31 October 1999 02:59:59.000 GMT+02:00
      Error: expected Time in Athens is 31 October 1999 03:59:59.000 GMT+03:00

      Time in GMT is 31 October 1999 01:00:00.000 GMT+00:00
      Time in Paris is 31 October 1999 02:00:00.000 GMT+01:00
      Time in Athens is 31 October 1999 03:00:00.000 GMT+02:00




      The code in SimpleTimeZone.java

              // Compare the date to the starting and ending rules. For the ending
              // rule comparison, we add the dstSavings to the millis passed in to convert
              // them from standard to wall time. +1 = date>rule, -1 = date<rule, 0 =
              // date==rule.
              int startCompare = compareToRule(month, day, dayOfWeek, millis,
                                               startMode, startMonth, startDayOfWeek,
                                               startDay, startTime);
              int endCompare = compareToRule(month, day, dayOfWeek, millis + dstSavings,
                                             endMode, endMonth, endDayOfWeek,
                                             endDay, endTime);


      This compares wall-clock time (including summer time adjustment for the ending
      time) against the endTime of the rule, so the endTime must be held in wall-clock
      time.

      In TimeZone.java:

             new SimpleTimeZone(1 * millisPerHour, "Europe/Paris" /*CE%sT*/,
                     Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2 * millisPerHour,
                     Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2 * millisPerHour, 1 * millisPerHour),
             // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S
             // Rule EU 1996 max - Oct lastSun 1:00u 0 -


      so the rule is stated, in the comment, in UTC (the 1:00u) but the offset for ending,
      in the actual code, doesn't include the summer-time adjustment of 1 hour in addition
      to the timezone offset.

      This same mistake has been made for all rules specified as xx:00u

      ---------------------------------------------------------------------------------------------

      Browsing this same code shows some summertime offsets coded as negative numbers. I doubt if
      these are correct, because summertime start and end are normally early morning, but also it
      is clear that the algorithm in compareToRule assumes a positive offset and could yield an
      incorrect result with a negative offset.

      The European Union legislation specifies that the 1am GMT change applies only to the EU itself
      and not its overseas territories.


      (Review ID: 55690)

      ======================================================================

            okutsu Masayoshi Okutsu
            miflemi Mick Fleming
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: