From 88e340642106f713ffa960cb77b6e79ec8084781 Mon Sep 17 00:00:00 2001 From: Alan Liu Date: Fri, 12 May 2000 23:21:32 +0000 Subject: [PATCH] Add TimeZone and SimpleTimeZone to com.ibm.util. X-SVN-Rev: 1360 --- .../com/ibm/demo/calendar/CalendarApp.java | 7 +- .../com/ibm/demo/calendar/CalendarCalc.java | 9 +- .../com/ibm/demo/calendar/CalendarFrame.java | 10 +- .../com/ibm/demo/calendar/CalendarPanel.java | 7 +- .../ibm/demo/holiday/HolidayCalendarDemo.java | 7 +- .../icu/dev/demo/calendar/CalendarApp.java | 7 +- .../icu/dev/demo/calendar/CalendarCalc.java | 9 +- .../icu/dev/demo/calendar/CalendarFrame.java | 10 +- .../icu/dev/demo/calendar/CalendarPanel.java | 7 +- .../dev/demo/holiday/HolidayCalendarDemo.java | 7 +- .../ibm/icu/dev/test/calendar/AstroTest.java | 5 +- .../dev/test/calendar/CalendarRegression.java | 38 +- .../icu/dev/test/calendar/CalendarTest.java | 5 +- .../dev/test/calendar/CompatibilityTest.java | 2 - .../ibm/icu/dev/test/calendar/TestCase.java | 6 +- .../test/timezone/TimeZoneBoundaryTest.java | 674 ++++++ .../dev/test/timezone/TimeZoneRegression.java | 851 +++++++ .../icu/dev/test/timezone/TimeZoneTest.java | 701 ++++++ icu4j/src/com/ibm/icu/text/DateFormat.java | 10 +- .../com/ibm/icu/text/DateFormatSymbols.java | 10 +- .../com/ibm/icu/text/SimpleDateFormat.java | 14 +- .../com/ibm/icu/util/BuddhistCalendar.java | 9 +- icu4j/src/com/ibm/icu/util/Calendar.java | 1 - icu4j/src/com/ibm/icu/util/EasterHoliday.java | 6 +- .../com/ibm/icu/util/GregorianCalendar.java | 11 +- .../src/com/ibm/icu/util/HebrewCalendar.java | 14 +- .../src/com/ibm/icu/util/IslamicCalendar.java | 9 +- .../com/ibm/icu/util/JapaneseCalendar.java | 9 +- .../src/com/ibm/icu/util/SimpleDateRule.java | 6 +- .../src/com/ibm/icu/util/SimpleTimeZone.java | 1461 ++++++++++++ .../ibm/icu/util/SimpleTimeZoneAdapter.java | 157 ++ icu4j/src/com/ibm/icu/util/TimeZone.java | 2036 +++++++++++++++++ .../src/com/ibm/test/calendar/AstroTest.java | 5 +- .../ibm/test/calendar/CalendarRegression.java | 38 +- .../com/ibm/test/calendar/CalendarTest.java | 5 +- .../ibm/test/calendar/CompatibilityTest.java | 2 - icu4j/src/com/ibm/test/calendar/TestCase.java | 6 +- .../test/timezone/TimeZoneBoundaryTest.java | 674 ++++++ .../ibm/test/timezone/TimeZoneRegression.java | 851 +++++++ .../com/ibm/test/timezone/TimeZoneTest.java | 701 ++++++ icu4j/src/com/ibm/text/DateFormat.java | 10 +- icu4j/src/com/ibm/text/DateFormatSymbols.java | 10 +- icu4j/src/com/ibm/text/SimpleDateFormat.java | 14 +- icu4j/src/com/ibm/util/BuddhistCalendar.java | 9 +- icu4j/src/com/ibm/util/Calendar.java | 1 - icu4j/src/com/ibm/util/EasterHoliday.java | 6 +- icu4j/src/com/ibm/util/GregorianCalendar.java | 11 +- icu4j/src/com/ibm/util/HebrewCalendar.java | 14 +- icu4j/src/com/ibm/util/IBMCalendar.java | 5 +- icu4j/src/com/ibm/util/IslamicCalendar.java | 9 +- icu4j/src/com/ibm/util/JapaneseCalendar.java | 9 +- icu4j/src/com/ibm/util/SimpleDateRule.java | 6 +- icu4j/src/com/ibm/util/SimpleTimeZone.java | 1461 ++++++++++++ .../com/ibm/util/SimpleTimeZoneAdapter.java | 157 ++ icu4j/src/com/ibm/util/TimeZone.java | 2036 +++++++++++++++++ 55 files changed, 11948 insertions(+), 207 deletions(-) create mode 100755 icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java create mode 100755 icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneRegression.java create mode 100755 icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java create mode 100755 icu4j/src/com/ibm/icu/util/SimpleTimeZone.java create mode 100755 icu4j/src/com/ibm/icu/util/SimpleTimeZoneAdapter.java create mode 100755 icu4j/src/com/ibm/icu/util/TimeZone.java create mode 100755 icu4j/src/com/ibm/test/timezone/TimeZoneBoundaryTest.java create mode 100755 icu4j/src/com/ibm/test/timezone/TimeZoneRegression.java create mode 100755 icu4j/src/com/ibm/test/timezone/TimeZoneTest.java create mode 100755 icu4j/src/com/ibm/util/SimpleTimeZone.java create mode 100755 icu4j/src/com/ibm/util/SimpleTimeZoneAdapter.java create mode 100755 icu4j/src/com/ibm/util/TimeZone.java diff --git a/icu4j/src/com/ibm/demo/calendar/CalendarApp.java b/icu4j/src/com/ibm/demo/calendar/CalendarApp.java index 811eaa37b7..4ff0d483a3 100755 --- a/icu4j/src/com/ibm/demo/calendar/CalendarApp.java +++ b/icu4j/src/com/ibm/demo/calendar/CalendarApp.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/demo/calendar/Attic/CalendarApp.java,v $ - * $Date: 2000/03/10 03:47:42 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:21:23 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -21,9 +21,6 @@ import java.awt.event.*; import java.net.*; import java.io.*; -import java.text.DateFormat; -import java.util.SimpleTimeZone; - import com.ibm.util.*; import com.ibm.text.*; diff --git a/icu4j/src/com/ibm/demo/calendar/CalendarCalc.java b/icu4j/src/com/ibm/demo/calendar/CalendarCalc.java index 1aed8439b4..06aa971d70 100755 --- a/icu4j/src/com/ibm/demo/calendar/CalendarCalc.java +++ b/icu4j/src/com/ibm/demo/calendar/CalendarCalc.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/demo/calendar/Attic/CalendarCalc.java,v $ - * $Date: 2000/04/26 18:40:15 $ - * $Revision: 1.6 $ + * $Date: 2000/05/12 23:21:23 $ + * $Revision: 1.7 $ * ***************************************************************************************** */ @@ -28,7 +28,8 @@ import java.text.ParsePosition; import com.ibm.util.Calendar; //import java.util.GregorianCalendar; import com.ibm.util.GregorianCalendar; -import java.util.TimeZone; +//import java.util.TimeZone; +import com.ibm.util.TimeZone; import java.util.Locale; import com.ibm.util.*; @@ -568,4 +569,4 @@ class RollAddField { } int field; String name; -}; \ No newline at end of file +}; diff --git a/icu4j/src/com/ibm/demo/calendar/CalendarFrame.java b/icu4j/src/com/ibm/demo/calendar/CalendarFrame.java index 7dd73ea26d..52fc9a44b3 100755 --- a/icu4j/src/com/ibm/demo/calendar/CalendarFrame.java +++ b/icu4j/src/com/ibm/demo/calendar/CalendarFrame.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/demo/calendar/Attic/CalendarFrame.java,v $ - * $Date: 2000/04/26 18:40:15 $ - * $Revision: 1.6 $ + * $Date: 2000/05/12 23:21:23 $ + * $Revision: 1.7 $ * ***************************************************************************************** */ @@ -20,7 +20,8 @@ import com.ibm.util.BuddhistCalendar; import com.ibm.util.JapaneseCalendar; import com.ibm.util.IslamicCalendar; import com.ibm.text.SimpleDateFormat; -import java.util.SimpleTimeZone; +//import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; import java.applet.Applet; import java.awt.*; import java.awt.event.*; @@ -37,7 +38,8 @@ import com.ibm.util.GregorianCalendar; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; -import java.util.TimeZone; +//import java.util.TimeZone; +import com.ibm.util.TimeZone; /** * A Frame is a top-level window with a title. The default layout for a frame diff --git a/icu4j/src/com/ibm/demo/calendar/CalendarPanel.java b/icu4j/src/com/ibm/demo/calendar/CalendarPanel.java index ce04db9de0..48477a44e6 100755 --- a/icu4j/src/com/ibm/demo/calendar/CalendarPanel.java +++ b/icu4j/src/com/ibm/demo/calendar/CalendarPanel.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/demo/calendar/Attic/CalendarPanel.java,v $ - * $Date: 2000/03/31 18:49:02 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:21:23 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -24,7 +24,8 @@ import java.io.*; //import java.text.DateFormat; import com.ibm.text.DateFormat; -import java.util.SimpleTimeZone; +//import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; //import java.util.*; import java.util.Date; import java.util.Locale; diff --git a/icu4j/src/com/ibm/demo/holiday/HolidayCalendarDemo.java b/icu4j/src/com/ibm/demo/holiday/HolidayCalendarDemo.java index 8db17ff3a9..b21aaccca4 100755 --- a/icu4j/src/com/ibm/demo/holiday/HolidayCalendarDemo.java +++ b/icu4j/src/com/ibm/demo/holiday/HolidayCalendarDemo.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/demo/holiday/Attic/HolidayCalendarDemo.java,v $ - * $Date: 2000/04/26 19:13:48 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:21:32 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -23,7 +23,8 @@ import java.io.*; //import java.text.SimpleDateFormat; import com.ibm.text.SimpleDateFormat; import java.text.DateFormatSymbols; -import java.util.SimpleTimeZone; +//import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; import java.util.Locale; import java.util.Vector; import java.util.Date; diff --git a/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarApp.java b/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarApp.java index a2c4ac929d..61aa785c06 100755 --- a/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarApp.java +++ b/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarApp.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarApp.java,v $ - * $Date: 2000/03/10 03:47:42 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:21:23 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -21,9 +21,6 @@ import java.awt.event.*; import java.net.*; import java.io.*; -import java.text.DateFormat; -import java.util.SimpleTimeZone; - import com.ibm.util.*; import com.ibm.text.*; diff --git a/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarCalc.java b/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarCalc.java index b8b1ed2397..ec1d2b51bb 100755 --- a/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarCalc.java +++ b/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarCalc.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarCalc.java,v $ - * $Date: 2000/04/26 18:40:15 $ - * $Revision: 1.6 $ + * $Date: 2000/05/12 23:21:23 $ + * $Revision: 1.7 $ * ***************************************************************************************** */ @@ -28,7 +28,8 @@ import java.text.ParsePosition; import com.ibm.util.Calendar; //import java.util.GregorianCalendar; import com.ibm.util.GregorianCalendar; -import java.util.TimeZone; +//import java.util.TimeZone; +import com.ibm.util.TimeZone; import java.util.Locale; import com.ibm.util.*; @@ -568,4 +569,4 @@ class RollAddField { } int field; String name; -}; \ No newline at end of file +}; diff --git a/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarFrame.java b/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarFrame.java index 2a93bc1a34..9f50777703 100755 --- a/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarFrame.java +++ b/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarFrame.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarFrame.java,v $ - * $Date: 2000/04/26 18:40:15 $ - * $Revision: 1.6 $ + * $Date: 2000/05/12 23:21:23 $ + * $Revision: 1.7 $ * ***************************************************************************************** */ @@ -20,7 +20,8 @@ import com.ibm.util.BuddhistCalendar; import com.ibm.util.JapaneseCalendar; import com.ibm.util.IslamicCalendar; import com.ibm.text.SimpleDateFormat; -import java.util.SimpleTimeZone; +//import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; import java.applet.Applet; import java.awt.*; import java.awt.event.*; @@ -37,7 +38,8 @@ import com.ibm.util.GregorianCalendar; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; -import java.util.TimeZone; +//import java.util.TimeZone; +import com.ibm.util.TimeZone; /** * A Frame is a top-level window with a title. The default layout for a frame diff --git a/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java b/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java index d9f9b5d9a2..cc8660e2a6 100755 --- a/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java +++ b/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java,v $ - * $Date: 2000/03/31 18:49:02 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:21:23 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -24,7 +24,8 @@ import java.io.*; //import java.text.DateFormat; import com.ibm.text.DateFormat; -import java.util.SimpleTimeZone; +//import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; //import java.util.*; import java.util.Date; import java.util.Locale; diff --git a/icu4j/src/com/ibm/icu/dev/demo/holiday/HolidayCalendarDemo.java b/icu4j/src/com/ibm/icu/dev/demo/holiday/HolidayCalendarDemo.java index 3ef5153e7e..7dc2856a83 100755 --- a/icu4j/src/com/ibm/icu/dev/demo/holiday/HolidayCalendarDemo.java +++ b/icu4j/src/com/ibm/icu/dev/demo/holiday/HolidayCalendarDemo.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/demo/holiday/HolidayCalendarDemo.java,v $ - * $Date: 2000/04/26 19:13:48 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:21:32 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -23,7 +23,8 @@ import java.io.*; //import java.text.SimpleDateFormat; import com.ibm.text.SimpleDateFormat; import java.text.DateFormatSymbols; -import java.util.SimpleTimeZone; +//import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; import java.util.Locale; import java.util.Vector; import java.util.Date; diff --git a/icu4j/src/com/ibm/icu/dev/test/calendar/AstroTest.java b/icu4j/src/com/ibm/icu/dev/test/calendar/AstroTest.java index cf0afb72ae..f5fe8f51a6 100755 --- a/icu4j/src/com/ibm/icu/dev/test/calendar/AstroTest.java +++ b/icu4j/src/com/ibm/icu/dev/test/calendar/AstroTest.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/calendar/AstroTest.java,v $ - * $Date: 2000/03/21 02:20:08 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:19:12 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -15,7 +15,6 @@ package com.ibm.test.calendar; // AstroTest import com.ibm.test.*; -import java.util.SimpleTimeZone; import com.ibm.util.*; import com.ibm.util.CalendarAstronomer.*; diff --git a/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java b/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java index b15d2e699c..7e82722d96 100755 --- a/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java +++ b/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java @@ -1,8 +1,6 @@ package com.ibm.test.calendar; import com.ibm.util.*; import java.util.Date; -import java.util.TimeZone; -import java.util.SimpleTimeZone; import java.util.Locale; import com.ibm.text.*; @@ -771,23 +769,25 @@ public class CalendarRegression extends com.ibm.test.TestFmwk { // I am disabling this test -- it is currently failing because of a bug // in Sun's latest change to STZ.getOffset(). I have filed a Sun bug // against this problem. -//! /** -//! * Prove that GregorianCalendar is proleptic (it used to cut off -//! * at 45 BC, and not have leap years before then). -//! */ -//! public void Test4125892() { -//! GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance(); -//! DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G"); -//! cal.clear(); -//! cal.set(Calendar.ERA, GregorianCalendar.BC); -//! cal.set(Calendar.YEAR, 81); // 81 BC is a leap year (proleptically) -//! cal.set(Calendar.MONTH, Calendar.FEBRUARY); -//! cal.set(Calendar.DATE, 28); -//! cal.add(Calendar.DATE, 1); -//! if (cal.get(Calendar.DATE) != 29 || -//! !cal.isLeapYear(-80)) // -80 == 81 BC -//! errln("Calendar not proleptic"); -//! } + + // Re-enabled after 'porting' TZ and STZ from java.util to com.ibm.util. + /** + * Prove that GregorianCalendar is proleptic (it used to cut off + * at 45 BC, and not have leap years before then). + */ + public void Test4125892() { + GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance(); + DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G"); + cal.clear(); + cal.set(Calendar.ERA, GregorianCalendar.BC); + cal.set(Calendar.YEAR, 81); // 81 BC is a leap year (proleptically) + cal.set(Calendar.MONTH, Calendar.FEBRUARY); + cal.set(Calendar.DATE, 28); + cal.add(Calendar.DATE, 1); + if (cal.get(Calendar.DATE) != 29 || + !cal.isLeapYear(-80)) // -80 == 81 BC + errln("Calendar not proleptic"); + } /** * Calendar and GregorianCalendar hashCode() methods need improvement. diff --git a/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarTest.java b/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarTest.java index 26adda5610..1dec295579 100755 --- a/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarTest.java +++ b/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarTest.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarTest.java,v $ - * $Date: 2000/03/21 02:20:08 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:19:12 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -18,7 +18,6 @@ import com.ibm.text.DateFormat; import com.ibm.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -import java.util.SimpleTimeZone; import com.ibm.util.*; /** diff --git a/icu4j/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java b/icu4j/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java index 15e7bf4be8..4bbce5cffd 100755 --- a/icu4j/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java +++ b/icu4j/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java @@ -7,8 +7,6 @@ package com.ibm.test.calendar; import com.ibm.util.*; import java.util.Date; -import java.util.TimeZone; -import java.util.SimpleTimeZone; import java.util.Locale; import java.text.*; import java.io.*; diff --git a/icu4j/src/com/ibm/icu/dev/test/calendar/TestCase.java b/icu4j/src/com/ibm/icu/dev/test/calendar/TestCase.java index 214d7c5466..37055afbb4 100755 --- a/icu4j/src/com/ibm/icu/dev/test/calendar/TestCase.java +++ b/icu4j/src/com/ibm/icu/dev/test/calendar/TestCase.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/calendar/TestCase.java,v $ - * $Date: 2000/03/21 02:20:08 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:19:12 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -16,7 +16,7 @@ import com.ibm.test.*; import com.ibm.util.Calendar; import com.ibm.util.GregorianCalendar; import java.util.Date; -import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; import java.util.Locale; /** diff --git a/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java b/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java new file mode 100755 index 0000000000..ca63f6ec16 --- /dev/null +++ b/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java @@ -0,0 +1,674 @@ +/* + @test 1.9 99/06/15 + @summary test Time Zone Boundary +*/ + +package com.ibm.test.timezone; +import com.ibm.text.*; +import com.ibm.util.*; +import com.ibm.test.*; +import java.util.Date; + +/** + * A test which discovers the boundaries of DST programmatically and verifies + * that they are correct. + */ +public class TimeZoneBoundaryTest extends TestFmwk +{ + static final int ONE_SECOND = 1000; + static final int ONE_MINUTE = 60*ONE_SECOND; + static final int ONE_HOUR = 60*ONE_MINUTE; + static final long ONE_DAY = 24*ONE_HOUR; + static final long ONE_YEAR = (long)(365.25 * ONE_DAY); + static final long SIX_MONTHS = ONE_YEAR / 2; + + static final int MONTH_LENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31}; + + // These values are empirically determined to be correct + static final long PST_1997_BEG = 860320800000L; + static final long PST_1997_END = 877856400000L; + + // Minimum interval for binary searches in ms; should be no larger + // than 1000. + static final long INTERVAL = 10; // Milliseconds + + // When long zone names are supported again, switch this to the + // long zone name. + static final String AUSTRALIA = "AET"; // Australia/Adelaide + static final long AUSTRALIA_1997_BEG = 872524800000L; // 877797000000L + static final long AUSTRALIA_1997_END = 859651200000L; // 859653000000L + + public static void main(String[] args) throws Exception { + new TimeZoneBoundaryTest().run(args); + } + + /** + * Date.toString().substring() Boundary Test + * Look for a DST changeover to occur within 6 months of the given Date. + * The initial Date.toString() should yield a string containing the + * startMode as a SUBSTRING. The boundary will be tested to be + * at the expectedBoundary value. + */ + void findDaylightBoundaryUsingDate(Date d, String startMode, long expectedBoundary) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + if (d.toString().indexOf(startMode) == -1) + { + logln("Error: " + startMode + " not present in " + d); + } + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + SIX_MONTHS; + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + String s = new Date(mid).toString(); + // logln(s); + if (s.indexOf(startMode) != -1) + { + min = mid; + } + else + { + max = mid; + } + } + + logln("Date Before: " + showDate(min)); + logln("Date After: " + showDate(max)); + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + // This test cannot be compiled until the inDaylightTime() method of GregorianCalendar + // becomes public. + // static void findDaylightBoundaryUsingCalendar(Date d, boolean startsInDST) + // { + // // Given a date with a year start, find the Daylight onset + // // and end. The given date should be 1/1/xx in some year. + // + // GregorianCalendar cal = new GregorianCalendar(); + // cal.setTime(d); + // if (cal.inDaylightTime() != startsInDST) + // { + // logln("Error: inDaylightTime(" + d + ") != " + startsInDST); + // } + // + // // Use a binary search, assuming that we have a Standard + // // time at the midpoint. + // long min = d.getTime(); + // long max = min + (long)(365.25 / 2 * 24*60*60*1000); + // + // while ((max - min) > INTERVAL) + // { + // long mid = (min + max) >> 1; + // cal.setTime(new Date(mid)); + // if (cal.inDaylightTime() == startsInDST) + // { + // min = mid; + // } + // else + // { + // max = mid; + // } + // } + // + // logln("Calendar Before: " + showDate(min)); + // logln("Calendar After: " + showDate(max)); + // } + + void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, long expectedBoundary) + { + findDaylightBoundaryUsingTimeZone(d, startsInDST, expectedBoundary, + TimeZone.getDefault()); + } + + void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, + long expectedBoundary, TimeZone tz) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + SIX_MONTHS; + + if (tz.inDaylightTime(d) != startsInDST) + { + errln("FAIL: " + tz.getID() + " inDaylightTime(" + + d + ") != " + startsInDST); + startsInDST = !startsInDST; // Flip over; find the apparent value + } + + if (tz.inDaylightTime(new Date(max)) == startsInDST) + { + errln("FAIL: " + tz.getID() + " inDaylightTime(" + + (new Date(max)) + ") != " + (!startsInDST)); + return; + } + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + boolean isIn = tz.inDaylightTime(new Date(mid)); + if (isIn == startsInDST) + { + min = mid; + } + else + { + max = mid; + } + } + + logln(tz.getID() + " Before: " + showDate(min, tz)); + logln(tz.getID() + " After: " + showDate(max, tz)); + + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + private static String showDate(long l) + { + return showDate(new Date(l)); + } + + private static String showDate(Date d) + { + return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) + + " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) + + " \"" + d + "\" = " + + d.getTime(); + } + + private static String showDate(long l, TimeZone z) + { + return showDate(new Date(l), z); + } + + private static String showDate(Date d, TimeZone zone) + { + DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + fmt.setTimeZone(zone); + return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) + + " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) + + " \"" + d + "\" = " + + fmt.format(d); + } + + private static String showNN(int n) + { + return ((n < 10) ? "0" : "") + n; + } + + /** + * Given a date, a TimeZone, and expected values for inDaylightTime, + * useDaylightTime, zone and DST offset, verify that this is the case. + */ + void verifyDST(Date d, TimeZone time_zone, + boolean expUseDaylightTime, boolean expInDaylightTime, + int expZoneOffset, int expDSTOffset) + { + logln("-- Verifying time " + d + + " in zone " + time_zone.getID()); + + if (time_zone.inDaylightTime(d) == expInDaylightTime) + logln("PASS: inDaylightTime = " + time_zone.inDaylightTime(d)); + else + errln("FAIL: inDaylightTime = " + time_zone.inDaylightTime(d)); + + if (time_zone.useDaylightTime() == expUseDaylightTime) + logln("PASS: useDaylightTime = " + time_zone.useDaylightTime()); + else + errln("FAIL: useDaylightTime = " + time_zone.useDaylightTime()); + + if (time_zone.getRawOffset() == expZoneOffset) + logln("PASS: getRawOffset() = " + expZoneOffset/(double)ONE_HOUR); + else + errln("FAIL: getRawOffset() = " + time_zone.getRawOffset()/(double)ONE_HOUR + + "; expected " + expZoneOffset/(double)ONE_HOUR); + + GregorianCalendar gc = new GregorianCalendar(time_zone); + gc.setTime(d); + int offset = time_zone.getOffset(gc.get(gc.ERA), gc.get(gc.YEAR), gc.get(gc.MONTH), + gc.get(gc.DAY_OF_MONTH), gc.get(gc.DAY_OF_WEEK), + ((gc.get(gc.HOUR_OF_DAY) * 60 + + gc.get(gc.MINUTE)) * 60 + + gc.get(gc.SECOND)) * 1000 + + gc.get(gc.MILLISECOND)); + if (offset == expDSTOffset) + logln("PASS: getOffset() = " + offset/(double)ONE_HOUR); + else + errln("FAIL: getOffset() = " + offset/(double)ONE_HOUR + + "; expected " + expDSTOffset/(double)ONE_HOUR); + } + + public void TestBoundaries() + { + TimeZone pst = TimeZone.getTimeZone("PST"); + TimeZone save = TimeZone.getDefault(); + try { + TimeZone.setDefault(pst); + + // DST changeover for PST is 4/6/1997 at 2 hours past midnight + Date d = new Date(97,Calendar.APRIL,6); + + // i is minutes past midnight standard time + for (int i=60; i<=180; i+=15) + { + boolean inDST = (i >= 120); + Date e = new Date(d.getTime() + i*60*1000); + verifyDST(e, pst, true, inDST, -8*ONE_HOUR, + inDST ? -7*ONE_HOUR : -8*ONE_HOUR); + } + } finally { + TimeZone.setDefault(save); + } + + if (true) + { + // This only works in PST/PDT + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + logln("========================================"); + findDaylightBoundaryUsingDate(new Date(97,0,1), "PST", PST_1997_BEG); + logln("========================================"); + findDaylightBoundaryUsingDate(new Date(97,6,1), "PDT", PST_1997_END); + } + + // if (true) + // { + // logln("========================================"); + // findDaylightBoundaryUsingCalendar(new Date(97,0,1), false); + // logln("========================================"); + // findDaylightBoundaryUsingCalendar(new Date(97,6,1), true); + // } + + if (true) + { + // Southern hemisphere test + logln("========================================"); + TimeZone z = TimeZone.getTimeZone(AUSTRALIA); + findDaylightBoundaryUsingTimeZone(new Date(97,0,1), true, AUSTRALIA_1997_END, z); + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,6,1), false, AUSTRALIA_1997_BEG, z); + } + + if (true) + { + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,0,1), false, PST_1997_BEG); + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true, PST_1997_END); + } + + // This just shows the offset for April 4-7 in 1997. This is redundant + // with a test above, so we disable it. + if (false) + { + TimeZone z = TimeZone.getDefault(); + logln(z.getOffset(1, 97, 3, 4, 6, 0) + " " + new Date(97, 3, 4)); + logln(z.getOffset(1, 97, 3, 5, 7, 0) + " " + new Date(97, 3, 5)); + logln(z.getOffset(1, 97, 3, 6, 1, 0) + " " + new Date(97, 3, 6)); + logln(z.getOffset(1, 97, 3, 7, 2, 0) + " " + new Date(97, 3, 7)); + } + } + + + //---------------------------------------------------------------------- + // Can't do any of these without a public inDaylightTime in GC + //---------------------------------------------------------------------- + + + // static GregorianCalendar cal = new GregorianCalendar(); + // + // static void _testUsingBinarySearch(Date d, boolean startsInDST) + // { + // // Given a date with a year start, find the Daylight onset + // // and end. The given date should be 1/1/xx in some year. + // + // // Use a binary search, assuming that we have a Standard + // // time at the midpoint. + // long min = d.getTime(); + // long max = min + (long)(365.25 / 2 * ONE_DAY); + // + // // First check the max + // cal.setTime(new Date(max)); + // if (cal.inDaylightTime() == startsInDST) + // { + // logln("Error: inDaylightTime(" + (new Date(max)) + ") != " + (!startsInDST)); + // } + // + // cal.setTime(d); + // if (cal.inDaylightTime() != startsInDST) + // { + // logln("Error: inDaylightTime(" + d + ") != " + startsInDST); + // } + // + // while ((max - min) > INTERVAL) + // { + // long mid = (min + max) >> 1; + // cal.setTime(new Date(mid)); + // if (cal.inDaylightTime() == startsInDST) + // { + // min = mid; + // } + // else + // { + // max = mid; + // } + // } + // + // logln("Binary Search Before: " + showDate(min)); + // logln("Binary Search After: " + showDate(max)); + // } + // + // static void _testUsingMillis(Date d, boolean startsInDST) + // { + // long millis = d.getTime(); + // long max = millis + (long)(370 * ONE_DAY); // A year plus extra + // + // boolean lastDST = startsInDST; + // while (millis < max) + // { + // cal.setTime(new Date(millis)); + // boolean inDaylight = cal.inDaylightTime(); + // + // if (inDaylight != lastDST) + // { + // logln("Switch " + (inDaylight ? "into" : "out of") + // + " DST at " + (new Date(millis))); + // lastDST = inDaylight; + // } + // + // millis += 15*ONE_MINUTE; + // } + // } + // + // static void _testUsingFields(int y, boolean startsInDST) + // { + // boolean lastDST = startsInDST; + // for (int m = 0; m < 12; ++m) + // { + // for (int d = 1; d <= MONTH_LENGTH[m]; ++d) + // { + // for (int h = 0; h < 24; ++h) + // { + // for (int min = 0; min < 60; min += 15) + // { + // cal.clear(); + // cal.set(y, m, d, h, min); + // boolean inDaylight = cal.inDaylightTime(); + // if (inDaylight != lastDST) + // { + // lastDST = inDaylight; + // log("Switch " + (lastDST ? "into" : "out of") + // + " DST at " + y + "/" + (m+1) + "/" + d + // + " " + showNN(h) + ":" + showNN(min)); + // logln(" " + cal.getTime()); + // + // cal.set(y, m, d, h-1, 45); + // log("Before = " + //+ y + "/" + (m+1) + "/" + d + //+ " " + showNN(h-1) + ":" + showNN(45)); + // logln(" " + cal.getTime()); + // } + // } + // } + // } + // } + // } + // + // public void Test1() + // { + // logln(Locale.getDefault().getDisplayName()); + // logln(TimeZone.getDefault().getID()); + // logln(new Date(0)); + // + // if (true) + // { + // logln("========================================"); + // _testUsingBinarySearch(new Date(97,0,1), false); + // logln("========================================"); + // _testUsingBinarySearch(new Date(97,6,1), true); + // } + // + // if (true) + // { + // logln("========================================"); + // logln("Stepping using millis"); + // _testUsingMillis(new Date(97,0,1), false); + // } + // + // if (true) + // { + // logln("========================================"); + // logln("Stepping using fields"); + // _testUsingFields(1997, false); + // } + // + // if (false) + // { + // cal.clear(); + // cal.set(1997, 3, 5, 10, 0); + // // cal.inDaylightTime(); + // logln("Date = " + cal.getTime()); + // logln("Millis = " + cal.getTime().getTime()/3600000); + // } + // } + + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + + void _testUsingBinarySearch(SimpleTimeZone tz, Date d, long expectedBoundary) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + (long)(365.25 / 2 * ONE_DAY); + + // First check the boundaries + boolean startsInDST = tz.inDaylightTime(d); + + if (tz.inDaylightTime(new Date(max)) == startsInDST) + { + logln("Error: inDaylightTime(" + (new Date(max)) + ") != " + (!startsInDST)); + } + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + if (tz.inDaylightTime(new Date(mid)) == startsInDST) + { + min = mid; + } + else + { + max = mid; + } + } + + logln("Binary Search Before: " + showDate(min)); + logln("Binary Search After: " + showDate(max)); + + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + /* + static void _testUsingMillis(Date d, boolean startsInDST) + { + long millis = d.getTime(); + long max = millis + (long)(370 * ONE_DAY); // A year plus extra + + boolean lastDST = startsInDST; + while (millis < max) + { + cal.setTime(new Date(millis)); + boolean inDaylight = cal.inDaylightTime(); + + if (inDaylight != lastDST) + { + logln("Switch " + (inDaylight ? "into" : "out of") + + " DST at " + (new Date(millis))); + lastDST = inDaylight; + } + + millis += 15*ONE_MINUTE; + } + } + */ + + /** + * Test new rule formats. + */ + public void TestNewRules() + { + //logln(Locale.getDefault().getDisplayName()); + //logln(TimeZone.getDefault().getID()); + //logln(new Date(0)); + + if (true) + { + // Doesn't matter what the default TimeZone is here, since we + // are creating our own TimeZone objects. + + SimpleTimeZone tz; + + logln("-----------------------------------------------------------------"); + logln("Aug 2ndTues .. Mar 15"); + tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_1", + Calendar.AUGUST, 2, Calendar.TUESDAY, 2*ONE_HOUR, + Calendar.MARCH, 15, 0, 2*ONE_HOUR); + //logln(tz.toString()); + logln("========================================"); + _testUsingBinarySearch(tz, new Date(97,0,1), 858416400000L); + logln("========================================"); + _testUsingBinarySearch(tz, new Date(97,6,1), 871380000000L); + + logln("-----------------------------------------------------------------"); + logln("Apr Wed>=14 .. Sep Sun<=20"); + tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_2", + Calendar.APRIL, 14, -Calendar.WEDNESDAY, 2*ONE_HOUR, + Calendar.SEPTEMBER, -20, -Calendar.SUNDAY, 2*ONE_HOUR); + //logln(tz.toString()); + logln("========================================"); + _testUsingBinarySearch(tz, new Date(97,0,1), 861184800000L); + logln("========================================"); + _testUsingBinarySearch(tz, new Date(97,6,1), 874227600000L); + } + + /* + if (true) + { + logln("========================================"); + logln("Stepping using millis"); + _testUsingMillis(new Date(97,0,1), false); + } + + if (true) + { + logln("========================================"); + logln("Stepping using fields"); + _testUsingFields(1997, false); + } + + if (false) + { + cal.clear(); + cal.set(1997, 3, 5, 10, 0); + // cal.inDaylightTime(); + logln("Date = " + cal.getTime()); + logln("Millis = " + cal.getTime().getTime()/3600000); + } + */ + } + + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + // Long Bug + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + + //public void Test3() + //{ + // findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true); + //} + + /** + * Find boundaries by stepping. + */ + void findBoundariesStepwise(int year, long interval, TimeZone z, int expectedChanges) + { + Date d = new Date(year - 1900, Calendar.JANUARY, 1); + long time = d.getTime(); // ms + long limit = time + ONE_YEAR + ONE_DAY; + boolean lastState = z.inDaylightTime(d); + int changes = 0; + logln("-- Zone " + z.getID() + " starts in " + year + " with DST = " + lastState); + logln("useDaylightTime = " + z.useDaylightTime()); + while (time < limit) + { + d.setTime(time); + boolean state = z.inDaylightTime(d); + if (state != lastState) + { + logln((state ? "Entry " : "Exit ") + + "at " + d); + lastState = state; + ++changes; + } + time += interval; + } + if (changes == 0) + { + if (!lastState && !z.useDaylightTime()) logln("No DST"); + else errln("FAIL: DST all year, or no DST with true useDaylightTime"); + } + else if (changes != 2) + { + errln("FAIL: " + changes + " changes seen; should see 0 or 2"); + } + else if (!z.useDaylightTime()) + { + errln("FAIL: useDaylightTime false but 2 changes seen"); + } + if (changes != expectedChanges) + { + errln("FAIL: " + changes + " changes seen; expected " + expectedChanges); + } + } + + public void TestStepwise() + { + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("EST"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("ACT"), 0); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone(AUSTRALIA), 2); + } +} diff --git a/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneRegression.java b/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneRegression.java new file mode 100755 index 0000000000..f962d7f994 --- /dev/null +++ b/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneRegression.java @@ -0,0 +1,851 @@ +/** + * @test 1.18 99/09/21 + * @bug 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429 + * @bug 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960 + */ + +package com.ibm.test.timezone; +import com.ibm.util.*; +import java.io.*; +import com.ibm.text.*; +import com.ibm.test.*; +import java.util.Date; +import java.util.Locale; + +public class TimeZoneRegression extends TestFmwk { + + public static void main(String[] args) throws Exception { + new TimeZoneRegression().run(args); + } + + public void Test4052967() { + logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***"); + String id = TimeZone.getDefault().getID(); + logln("user.timezone: " + System.getProperty("user.timezone", "")); + logln("TimeZone.getDefault().getID(): " + id); + logln(new Date().toString()); + logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***"); + } + + public void Test4073209() { + TimeZone z1 = TimeZone.getTimeZone("PST"); + TimeZone z2 = TimeZone.getTimeZone("PST"); + if (z1 == z2) errln("Fail: TimeZone should return clones"); + } + + public void Test4073215() { + SimpleTimeZone z = (SimpleTimeZone) TimeZone.getTimeZone("GMT"); + if (z.useDaylightTime()) + errln("Fail: Fix test to start with non-DST zone"); + z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0); + z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0); + if (!z.useDaylightTime()) + errln("Fail: DST not active"); + if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) || + !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) || + z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) { + errln("Fail: DST not working as expected"); + } + } + + /** + * The expected behavior of TimeZone around the boundaries is: + * (Assume transition time of 2:00 AM) + * day of onset 1:59 AM STD = display name 1:59 AM ST + * 2:00 AM STD = display name 3:00 AM DT + * day of end 0:59 AM STD = display name 1:59 AM DT + * 1:00 AM STD = display name 1:00 AM ST + */ + public void Test4084933() { + TimeZone tz = TimeZone.getTimeZone("PST"); + + long offset1 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)); + long offset2 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1); + + long offset3 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)); + long offset4 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1); + + /* + * The following was added just for consistency. It shows that going *to* Daylight + * Savings Time (PDT) does work at 2am. + */ + + long offset5 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)); + long offset6 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1); + + long offset7 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)); + long offset8 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1); + + long SToffset = -8 * 60*60*1000L; + long DToffset = -7 * 60*60*1000L; + if (offset1 != SToffset || offset2 != SToffset || + offset3 != SToffset || offset4 != DToffset || + offset5 != DToffset || offset6 != SToffset || + offset7 != SToffset || offset8 != SToffset) + errln("Fail: TimeZone misbehaving"); + } + + public void Test4096952() { + String[] ZONES = { "GMT", "MET", "IST" }; + boolean pass = true; + try { + for (int i=0; i= ONE_DAY) { + millis -= ONE_DAY; + ++date; + dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7); + } + + tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA), + testCal.get(Calendar.YEAR), + testCal.get(Calendar.MONTH), + date, + dow, + millis); + tzRawOffset = testTZ.getRawOffset(); + tzOffsetFloat = new Float((float)tzOffset/(float)3600000); + tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000); + + Date testDate = testCal.getTime(); + + boolean inDaylightTime = testTZ.inDaylightTime(testDate); + SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm"); + sdf.setCalendar(testCal); + String inDaylightTimeString; + + boolean passed; + + if (inDaylightTime) + { + inDaylightTimeString = " DST "; + passed = (tzOffset == (tzRawOffset + 3600000)); + } + else + { + inDaylightTimeString = " "; + passed = (tzOffset == tzRawOffset); + } + + String output = testTZ.getID() + " " + sdf.format(testDate) + + " Offset(" + tzOffsetFloat + ")" + + " RawOffset(" + tzRawOffsetFloat + ")" + + " " + millis/(float)3600000 + " " + + inDaylightTimeString; + + if (passed) + output += " "; + else + output += "ERROR"; + + if (passed) logln(output); else errln(output); + return passed; + } + + /** + * CANNOT REPRODUDE + * + * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never + * should have been made public. It's simply too hard to use correctly. + * + * The original test code failed to do the following: + * (1) Call Calendar.setTime() before getting the fields! + * (2) Use the right millis (as usual) for getOffset(); they were passing + * in the MILLIS field, instead of the STANDARD MILLIS IN DAY. + * When you fix these two problems, the test passes, as expected. + */ + public void Test4126678() { + // Note: this test depends on the PST time zone. + TimeZone initialZone = TimeZone.getDefault(); + Calendar cal = Calendar.getInstance(); + TimeZone tz = TimeZone.getTimeZone("PST"); + TimeZone.setDefault(tz); + cal.setTimeZone(tz); + + Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0); + // the dt value is local time in PST. + if (!tz.inDaylightTime(dt)) + errln("We're not in Daylight Savings Time and we should be.\n"); + + cal.setTime(dt); + int era = cal.get(Calendar.ERA); + int year = cal.get(Calendar.YEAR); + int month = cal.get(Calendar.MONTH); + int day = cal.get(Calendar.DATE); + int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); + int millis = cal.get(Calendar.MILLISECOND) + + (cal.get(Calendar.SECOND) + + (cal.get(Calendar.MINUTE) + + (cal.get(Calendar.HOUR) * 60) * 60) * 1000) - + cal.get(Calendar.DST_OFFSET); + + long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis); + long raw_offset = tz.getRawOffset(); + if (offset == raw_offset) + errln("Offsets should not match when in DST"); + + // restore the initial time zone so that this test case + // doesn't affect the others. + TimeZone.setDefault(initialZone); + } + + /** + * TimeZone.getAvailableIDs(int) throws exception for certain values, + * due to a faulty constant in TimeZone.java. + */ + public void Test4151406() { + int max = 0; + for (int h=-28; h<=30; ++h) { + // h is in half-hours from GMT; rawoffset is in millis + int rawoffset = h * 1800000; + int hh = (h<0) ? -h : h; + String hname = ((h<0) ? "GMT-" : "GMT+") + + ((hh/2 < 10) ? "0" : "") + + (hh/2) + ':' + + ((hh%2==0) ? "00" : "30"); + try { + String[] ids = TimeZone.getAvailableIDs(rawoffset); + if (ids.length > max) max = ids.length; + logln(hname + ' ' + ids.length + + ((ids.length > 0) ? (" e.g. " + ids[0]) : "")); + } catch (Exception e) { + errln(hname + ' ' + "Fail: " + e); + } + } + logln("Maximum zones per offset = " + max); + } + + public void Test4151429() { + try { + TimeZone tz = TimeZone.getTimeZone("GMT"); + String name = tz.getDisplayName(true, Integer.MAX_VALUE, + Locale.getDefault()); + errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()"); + } catch(IllegalArgumentException e) {} + } + + /** + * SimpleTimeZone accepts illegal DST savings values. These values + * must be non-zero. There is no upper limit at this time. + */ + public void Test4154525() { + final int GOOD = 1, BAD = 0; + int[] DATA = { + 1, GOOD, + 0, BAD, + -1, BAD, + 60*60*1000, GOOD, + Integer.MIN_VALUE, BAD, + // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time + }; + for (int i=0; i) should work but throws " + ex) + : ", ) should fail but doesn't")); + } + + ex = null; + try { + SimpleTimeZone temp = new SimpleTimeZone(0, "Z", + GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME, + month, day, dayOfWeek, time); + } catch (IllegalArgumentException e) { + ex = e; + } + if ((ex == null) != shouldBeGood) { + errln("SimpleTimeZone(, month=" + month + ", day=" + day + + ", dayOfWeek=" + dayOfWeek + ", time=" + time + + (shouldBeGood ? (") should work but throws " + ex) + : ") should fail but doesn't")); + } + } + } + + /** + * SimpleTimeZone.getOffset accepts illegal arguments. + */ + public void Test4154650() { + final int GOOD=1, BAD=0; + final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST; + final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000; + int[] DATA = { + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0, + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000, + }; + + TimeZone tz = TimeZone.getDefault(); + for (int i=0; i " + zone[i]); + d = new Date(d.getTime() + ONE_HOUR); + } + if (zone[0].equals(zone[1]) && + (zone[1].equals(zone[2]) != transitionExpected) && + zone[2].equals(zone[3])) { + logln("Ok: transition " + transitionExpected); + } else { + errln("Fail: boundary transition incorrect"); + } + } + + // restore the initial time zone so that this test case + // doesn't affect the others. + TimeZone.setDefault(initialZone); + } + + /** + * TimeZone broken in last hour of year + */ + public void Test4173604() { + SimpleTimeZone pst = (SimpleTimeZone)TimeZone.getTimeZone("PST"); + int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000); + int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000); + int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0); + if (o22 != o23 || o22 != o00) { + errln("Offsets should be the same (for PST), but got: " + + "12/31 22:00 " + o22 + + ", 12/31 23:00 " + o23 + + ", 01/01 00:00 " + o00); + } + + GregorianCalendar cal = new GregorianCalendar(); + cal.setTimeZone(pst); + cal.clear(); + cal.set(1998, Calendar.JANUARY, 1); + int lastDST = cal.get(Calendar.DST_OFFSET); + int transitions = 0; + int delta = 5; + while (cal.get(Calendar.YEAR) < 2000) { + cal.add(Calendar.MINUTE, delta); + if (cal.get(Calendar.DST_OFFSET) != lastDST) { + ++transitions; + Calendar t = (Calendar)cal.clone(); + t.add(Calendar.MINUTE, -delta); + logln(t.getTime() + " " + t.get(Calendar.DST_OFFSET)); + logln(cal.getTime() + " " + (lastDST=cal.get(Calendar.DST_OFFSET))); + } + } + if (transitions != 4) { + errln("Saw " + transitions + " transitions; should have seen 4"); + } + } + + /** + * getDisplayName doesn't work with unusual savings/offsets. + */ + public void Test4176686() { + // Construct a zone that does not observe DST but + // that does have a DST savings (which should be ignored). + int offset = 90 * 60000; // 1:30 + SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_"); + z1.setDSTSavings(45 * 60000); // 0:45 + + // Construct a zone that observes DST for the first 6 months. + SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_"); + z2.setDSTSavings(45 * 60000); // 0:45 + z2.setStartRule(Calendar.JANUARY, 1, 0); + z2.setEndRule(Calendar.JULY, 1, 0); + + // Also check DateFormat + DateFormat fmt1 = new SimpleDateFormat("z"); + fmt1.setTimeZone(z1); // Format uses standard zone + DateFormat fmt2 = new SimpleDateFormat("z"); + fmt2.setTimeZone(z2); // Format uses DST zone + Date dst = new Date(1970-1900, Calendar.FEBRUARY, 1); // Time in DST + Date std = new Date(1970-1900, Calendar.AUGUST, 1); // Time in standard + + // Description, Result, Expected Result + String[] DATA = { + "getDisplayName(false, SHORT)/std zone", + z1.getDisplayName(false, TimeZone.SHORT), "GMT+01:30", + "getDisplayName(false, LONG)/std zone", + z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30", + "getDisplayName(true, SHORT)/std zone", + z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30", + "getDisplayName(true, LONG)/std zone", + z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30", + "getDisplayName(false, SHORT)/dst zone", + z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30", + "getDisplayName(false, LONG)/dst zone", + z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30", + "getDisplayName(true, SHORT)/dst zone", + z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15", + "getDisplayName(true, LONG)/dst zone", + z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15", + "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30", + "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30", + "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30", + "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15", + }; + + for (int i=0; i " + DATA[i+1] + ", exp " + DATA[i+2]); + } + } + } + + /** + * SimpleTimeZone allows invalid DOM values. + */ + public void Test4184229() { + SimpleTimeZone zone = null; + try { + zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 startDay"); + } catch(IllegalArgumentException e) { + logln("(a) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 endDay"); + } catch(IllegalArgumentException e) { + logln("(b) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000); + errln("Failed. No exception has been thrown for DOM -1 startDay +savings"); + } catch(IllegalArgumentException e) { + logln("(c) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000); + errln("Failed. No exception has been thrown for DOM -1 endDay +savings"); + } catch(IllegalArgumentException e) { + logln("(d) " + e.getMessage()); + } + // Make a valid constructor call for subsequent tests. + zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0); + try { + zone.setStartRule(0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings"); + } catch(IllegalArgumentException e) { + logln("(e) " + e.getMessage()); + } + try { + zone.setStartRule(0, -1, 0); + errln("Failed. No exception has been thrown for DOM -1 setStartRule"); + } catch(IllegalArgumentException e) { + logln("(f) " + e.getMessage()); + } + try { + zone.setEndRule(0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings"); + } catch(IllegalArgumentException e) { + logln("(g) " + e.getMessage()); + } + try { + zone.setEndRule(0, -1, 0); + errln("Failed. No exception has been thrown for DOM -1 setEndRule"); + } catch(IllegalArgumentException e) { + logln("(h) " + e.getMessage()); + } + } + + /** + * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get + * of 2/29/1996 (leap day). + */ + public void Test4208960 () { + SimpleTimeZone tz = (SimpleTimeZone)TimeZone.getTimeZone("PST"); + try { + int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29, + Calendar.THURSDAY, 0); + } catch (IllegalArgumentException e) { + errln("FAILED: to get TimeZone.getOffset(2/29/96)"); + } + try { + int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29, + Calendar.THURSDAY, 0); + errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception."); + } catch (IllegalArgumentException e) { + logln("got IllegalArgumentException"); + } + } +} + +//eof diff --git a/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java b/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java new file mode 100755 index 0000000000..ec8662b4fc --- /dev/null +++ b/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java @@ -0,0 +1,701 @@ +/** + * @test 1.22 99/09/21 + * @bug 4028006 4044013 4096694 4107276 4107570 4112869 4130885 + * @summary test TimeZone + * @build TimeZoneTest + */ + +package com.ibm.test.timezone; +import com.ibm.text.*; +import com.ibm.util.*; +import com.ibm.test.*; +import java.util.Date; +import java.util.Locale; +import java.util.Hashtable; +import java.util.ResourceBundle; + +public class TimeZoneTest extends TestFmwk +{ + static final int millisPerHour = 3600000; + + public static void main(String[] args) throws Exception { + new TimeZoneTest().run(args); + } + + /** + * Bug 4130885 + * Certain short zone IDs, used since 1.1.x, are incorrect. + * + * The worst of these is: + * + * "CAT" (Central African Time) should be GMT+2:00, but instead returns a + * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST, + * or AZOST, depending on which zone is meant, but in no case is it CAT. + * + * Other wrong zone IDs: + * + * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time, + * GMT-5:00. European Central time is abbreviated CEST. + * + * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time, + * GMT-11:00. Solomon Island time is SBT. + * + * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for + * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST. + * + * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in + * another bug.] It should be "AKST". AST is Atlantic Standard Time, + * GMT-4:00. + * + * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time, + * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct + * from MST with daylight savings. + * + * In addition to these problems, a number of zones are FAKE. That is, they + * don't match what people use in the real world. + * + * FAKE zones: + * + * EET (should be EEST) + * ART (should be EEST) + * MET (should be IRST) + * NET (should be AMST) + * PLT (should be PKT) + * BST (should be BDT) + * VST (should be ICT) + * CTT (should be CST) + + * ACT (should be CST) + + * AET (should be EST) + + * MIT (should be WST) + + * IET (should be EST) + + * PRT (should be AST) + + * CNT (should be NST) + * AGT (should be ARST) + * BET (should be EST) + + * + * + A zone with the correct name already exists and means something + * else. E.g., EST usually indicates the US Eastern zone, so it cannot be + * used for Brazil (BET). + */ + public void TestShortZoneIDs() throws Exception { + + ZoneDescriptor[] JDK_116_REFERENCE_LIST = { + new ZoneDescriptor("MIT", -660, false), + new ZoneDescriptor("HST", -600, false), + new ZoneDescriptor("AST", -540, true), + new ZoneDescriptor("PST", -480, true), + new ZoneDescriptor("PNT", -420, false), + new ZoneDescriptor("MST", -420, true), + new ZoneDescriptor("CST", -360, true), + new ZoneDescriptor("IET", -300, false), + new ZoneDescriptor("EST", -300, true), + new ZoneDescriptor("PRT", -240, false), + new ZoneDescriptor("CNT", -210, true), + new ZoneDescriptor("AGT", -180, false), + new ZoneDescriptor("BET", -180, true), + // new ZoneDescriptor("CAT", -60, false), // Wrong: + // As of bug 4130885, fix CAT (Central Africa) + new ZoneDescriptor("CAT", 120, false), // Africa/Harare + new ZoneDescriptor("GMT", 0, false), + new ZoneDescriptor("UTC", 0, false), + new ZoneDescriptor("ECT", 60, true), + new ZoneDescriptor("ART", 120, true), + new ZoneDescriptor("EET", 120, true), + new ZoneDescriptor("EAT", 180, false), + new ZoneDescriptor("MET", 210, true), + // new ZoneDescriptor("NET", 240, false); + // As of bug 4191164, fix NET + new ZoneDescriptor("NET", 240, true), + new ZoneDescriptor("PLT", 300, false), + new ZoneDescriptor("IST", 330, false), + new ZoneDescriptor("BST", 360, false), + new ZoneDescriptor("VST", 420, false), + new ZoneDescriptor("CTT", 480, false), + new ZoneDescriptor("JST", 540, false), + new ZoneDescriptor("ACT", 570, false), + new ZoneDescriptor("AET", 600, true), + new ZoneDescriptor("SST", 660, false), + // new ZoneDescriptor("NST", 720, false), + // As of bug 4130885, fix NST (New Zealand) + new ZoneDescriptor("NST", 720, true), // Pacific/Auckland + }; + + Hashtable hash = new Hashtable(); + + String[] ids = TimeZone.getAvailableIDs(); + for (int i=0; i i2.offset) return 1; + if (i1.offset < i2.offset) return -1; + if (i1.daylight && !i2.daylight) return 1; + if (!i1.daylight && i2.daylight) return -1; + return i1.id.compareTo(i2.id); + } + } + + static final String EXPECTED_CUSTOM_ID = "Custom"; + static final String formatMinutes(int min) { + char sign = '+'; + if (min < 0) { sign = '-'; min = -min; } + int h = min/60; + min = min%60; + return "" + sign + h + ":" + ((min<10) ? "0" : "") + min; + } + /** + * As part of the VM fix (see CCC approved RFE 4028006, bug + * 4044013), TimeZone.getTimeZone() has been modified to recognize + * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and + * GMT[+-]hh. Test this behavior here. + * + * Bug 4044013 + */ + public void TestCustomParse() throws Exception { + Object[] DATA = { + // ID Expected offset in minutes + "GMT", null, + "GMT0", null, + "GMT+0", new Integer(0), + "GMT+1", new Integer(60), + "GMT-0030", new Integer(-30), + "GMT+15:99", new Integer(15*60+99), + "GMT+", null, + "GMT-", null, + "GMT+0:", null, + "GMT-:", null, + "GMT+0010", new Integer(10), // Interpret this as 00:10 + "GMT-10", new Integer(-10*60), + "GMT+30", new Integer(30), + "GMT-3:30", new Integer(-(3*60+30)), + "GMT-230", new Integer(-(2*60+30)), + }; + for (int i=0; i generic GMT"); + // When TimeZone.getTimeZone() can't parse the id, it + // returns GMT -- a dubious practice, but required for + // backward compatibility. + if (exp != null) { + throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + + " for " + id + ", got parse failure"); + } + } + else { + int ioffset = zone.getRawOffset()/60000; + String offset = formatMinutes(ioffset); + logln(id + " -> " + zone.getID() + " GMT" + offset); + if (exp == null) { + throw new Exception("Expected parse failure for " + id + + ", got offset of " + offset + + ", id " + zone.getID()); + } + else if (ioffset != exp.intValue() || + !zone.getID().equals(EXPECTED_CUSTOM_ID)) { + throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + + ", id Custom, for " + id + + ", got offset of " + offset + + ", id " + zone.getID()); + } + } + } + } + + /** + * Test the basic functionality of the getDisplayName() API. + * + * Bug 4112869 + * Bug 4028006 + * + * See also API change request A41. + * + * 4/21/98 - make smarter, so the test works if the ext resources + * are present or not. + */ + public void TestDisplayName() { + TimeZone zone = TimeZone.getTimeZone("PST"); + String name = zone.getDisplayName(Locale.ENGLISH); + logln("PST->" + name); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected \"Pacific Standard Time\""); + + //***************************************************************** + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + //***************************************************************** + Object[] DATA = { + new Boolean(false), new Integer(TimeZone.SHORT), "PST", + new Boolean(true), new Integer(TimeZone.SHORT), "PDT", + new Boolean(false), new Integer(TimeZone.LONG), "Pacific Standard Time", + new Boolean(true), new Integer(TimeZone.LONG), "Pacific Daylight Time", + }; + + for (int i=0; i" + zone2.inDaylightTime(new Date())); + name = zone2.getDisplayName(Locale.ENGLISH); + logln("Modified PST->" + name); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected \"Pacific Standard Time\""); + + // Make sure we get the default display format for Locales + // with no display name data. + Locale zh_CN = Locale.SIMPLIFIED_CHINESE; + name = zone.getDisplayName(zh_CN); + //***************************************************************** + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + //***************************************************************** + logln("PST(zh_CN)->" + name); + + // Now be smart -- check to see if zh resource is even present. + // If not, we expect the en fallback behavior. + ResourceBundle enRB = ResourceBundle.getBundle("java.text.resources.DateFormatZoneData", + Locale.ENGLISH); + ResourceBundle zhRB = ResourceBundle.getBundle("java.text.resources.DateFormatZoneData", + zh_CN); + boolean noZH = enRB == zhRB; + + if (noZH) { + logln("Warning: Not testing the zh_CN behavior because resource is absent"); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected Pacific Standard Time"); + } + else if (!name.equals("Pacific Standard Time") && + !name.equals("GMT-08:00") && + !name.equals("GMT-8:00") && + !name.equals("GMT-0800") && + !name.equals("GMT-800")) { + errln("Fail: Expected GMT-08:00 or something similar"); + errln("************************************************************"); + errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED"); + errln("************************************************************"); + } + + // Now try a non-existent zone + zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); + name = zone2.getDisplayName(Locale.ENGLISH); + logln("GMT+90min->" + name); + if (!name.equals("GMT+01:30") && + !name.equals("GMT+1:30") && + !name.equals("GMT+0130") && + !name.equals("GMT+130")) + errln("Fail: Expected GMT+01:30 or something similar"); + } + + public void TestGenericAPI() { + String id = "NewGMT"; + int offset = 12345; + + SimpleTimeZone zone = new SimpleTimeZone(offset, id); + if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); + + TimeZone zoneclone = (TimeZone)zone.clone(); + if (!zoneclone.equals(zone)) errln("FAIL: clone or operator== failed"); + zoneclone.setID("abc"); + if (zoneclone.equals(zone)) errln("FAIL: clone or operator!= failed"); + // delete zoneclone; + + zoneclone = (TimeZone)zone.clone(); + if (!zoneclone.equals(zone)) errln("FAIL: clone or operator== failed"); + zoneclone.setRawOffset(45678); + if (zoneclone.equals(zone)) errln("FAIL: clone or operator!= failed"); + + // C++ only + /* + SimpleTimeZone copy(*zone); + if (!(copy == *zone)) errln("FAIL: copy constructor or operator== failed"); + copy = *(SimpleTimeZone*)zoneclone; + if (!(copy == *zoneclone)) errln("FAIL: assignment operator or operator== failed"); + */ + + TimeZone saveDefault = TimeZone.getDefault(); + TimeZone.setDefault(zone); + TimeZone defaultzone = TimeZone.getDefault(); + if (defaultzone == zone) errln("FAIL: Default object is identical, not clone"); + if (!defaultzone.equals(zone)) errln("FAIL: Default object is not equal"); + TimeZone.setDefault(saveDefault); + // delete defaultzone; + // delete zoneclone; + } + + public void TestRuleAPI() + { + // ErrorCode status = ZERO_ERROR; + + int offset = (int)(60*60*1000*1.75); // Pick a weird offset + SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone"); + if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); + + // Establish our expected transition times. Do this with a non-DST + // calendar with the (above) declared local offset. + GregorianCalendar gc = new GregorianCalendar(zone); + gc.clear(); + gc.set(1990, Calendar.MARCH, 1); + long marchOneStd = gc.getTime().getTime(); // Local Std time midnight + gc.clear(); + gc.set(1990, Calendar.JULY, 1); + long julyOneStd = gc.getTime().getTime(); // Local Std time midnight + + // Starting and ending hours, WALL TIME + int startHour = (int)(2.25 * 3600000); + int endHour = (int)(3.5 * 3600000); + + zone.setStartRule(Calendar.MARCH, 1, 0, startHour); + zone.setEndRule (Calendar.JULY, 1, 0, endHour); + + gc = new GregorianCalendar(zone); + // if (failure(status, "new GregorianCalendar")) return; + + long marchOne = marchOneStd + startHour; + long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time + + long expMarchOne = 636251400000L; + if (marchOne != expMarchOne) + { + errln("FAIL: Expected start computed as " + marchOne + + " = " + new Date(marchOne)); + logln(" Should be " + expMarchOne + + " = " + new Date(expMarchOne)); + } + + long expJulyOne = 646793100000L; + if (julyOne != expJulyOne) + { + errln("FAIL: Expected start computed as " + julyOne + + " = " + new Date(julyOne)); + logln(" Should be " + expJulyOne + + " = " + new Date(expJulyOne)); + } + + _testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(), + new Date(90, Calendar.JUNE, 15).getTime(), marchOne); + _testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(), + new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne); + + if (zone.inDaylightTime(new Date(marchOne - 1000)) || + !zone.inDaylightTime(new Date(marchOne))) + errln("FAIL: Start rule broken"); + if (!zone.inDaylightTime(new Date(julyOne - 1000)) || + zone.inDaylightTime(new Date(julyOne))) + errln("FAIL: End rule broken"); + + zone.setStartYear(1991); + if (zone.inDaylightTime(new Date(marchOne)) || + zone.inDaylightTime(new Date(julyOne - 1000))) + errln("FAIL: Start year broken"); + + // failure(status, "TestRuleAPI"); + // delete gc; + // delete zone; + } + + void _testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary) + { + // ErrorCode status = ZERO_ERROR; + boolean startsInDST = tz.inDaylightTime(new Date(min)); + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + if (tz.inDaylightTime(new Date(max)) == startsInDST) { + logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST)); + return; + } + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + while ((max - min) > INTERVAL) { + long mid = (min + max) / 2; + if (tz.inDaylightTime(new Date(mid)) == startsInDST) { + min = mid; + } + else { + max = mid; + } + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + } + logln("Binary Search Before: " + min + " = " + new Date(min)); + logln("Binary Search After: " + max + " = " + new Date(max)); + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && + mindelta <= INTERVAL && + mindelta >= 0 && + mindelta <= INTERVAL) + logln("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); + else + errln("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); + } + + static final int INTERVAL = 100; + + // Bug 006; verify the offset for a specific zone. + public void TestPRTOffset() + { + TimeZone tz = TimeZone.getTimeZone( "PRT" ); + if( tz == null ) { + errln( "FAIL: TimeZone(PRT) is null" ); + } + else{ + if (tz.getRawOffset() != (-4*millisPerHour)) + errln("FAIL: Offset for PRT should be -4"); + } + + } + + // Test various calls + public void TestVariousAPI518() + { + TimeZone time_zone = TimeZone.getTimeZone("PST"); + Date d = new Date(97, Calendar.APRIL, 30); + + logln("The timezone is " + time_zone.getID()); + + if (time_zone.inDaylightTime(d) != true) + errln("FAIL: inDaylightTime returned false"); + + if (time_zone.useDaylightTime() != true) + errln("FAIL: useDaylightTime returned false"); + + if (time_zone.getRawOffset() != -8*millisPerHour) + errln( "FAIL: getRawOffset returned wrong value"); + + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(d); + if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH), + gc.get(gc.DAY_OF_MONTH), + gc.get(gc.DAY_OF_WEEK), 0) + != -7*millisPerHour) + errln("FAIL: getOffset returned wrong value"); + } + + // Test getAvailableID API + public void TestGetAvailableIDs913() + { + StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { "); + String[] s = TimeZone.getAvailableIDs(); + for (int i=0; i 0) buf.append(", "); + buf.append(s[i]); + } + buf.append(" };"); + logln(buf.toString()); + + buf.setLength(0); + buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { "); + s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000); + for (int i=0; i 0) buf.append(", "); + buf.append(s[i]); + } + buf.append(" };"); + logln(buf.toString()); + + TimeZone tz = TimeZone.getTimeZone("PST"); + if (tz != null) + logln("getTimeZone(PST) = " + tz.getID()); + else + errln("FAIL: getTimeZone(PST) = null"); + + tz = TimeZone.getTimeZone("America/Los_Angeles"); + if (tz != null) + logln("getTimeZone(America/Los_Angeles) = " + tz.getID()); + else + errln("FAIL: getTimeZone(PST) = null"); + + // Bug 4096694 + tz = TimeZone.getTimeZone("NON_EXISTENT"); + if (tz == null) + errln("FAIL: getTimeZone(NON_EXISTENT) = null"); + else if (!tz.getID().equals("GMT")) + errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID()); + } + + /** + * Bug 4107276 + */ + public void TestDSTSavings() { + // It might be better to find a way to integrate this test into the main TimeZone + // tests above, but I don't have time to figure out how to do this (or if it's + // even really a good idea). Let's consider that a future. --rtg 1/27/98 + SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest", + Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0, + (int)(0.5 * millisPerHour)); + + if (tz.getRawOffset() != -5 * millisPerHour) + errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) + + " hours instead of -5 hours."); + if (!tz.useDaylightTime()) + errln("Test time zone should use DST but claims it doesn't."); + if (tz.getDSTSavings() != 0.5 * millisPerHour) + errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() / + millisPerHour) + " hours instead."); + + int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, + 10 * millisPerHour); + if (offset != -4.5 * millisPerHour) + errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + tz.setDSTSavings(millisPerHour); + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, + 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + } + + /** + * Bug 4107570 + */ + public void TestAlternateRules() { + // Like TestDSTSavings, this test should probably be integrated somehow with the main + // test at the top of this class, but I didn't have time to figure out how to do that. + // --rtg 1/28/98 + + SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest"); + + // test the day-of-month API + tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour); + tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour); + + int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15, + Calendar.SUNDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25, + Calendar.SUNDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + // test the day-of-week-after-day-in-month API + tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true); + tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11, + Calendar.WEDNESDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14, + Calendar.SATURDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17, + Calendar.SATURDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + } +} + +//eof diff --git a/icu4j/src/com/ibm/icu/text/DateFormat.java b/icu4j/src/com/ibm/icu/text/DateFormat.java index 99c46be454..44d545a58b 100755 --- a/icu4j/src/com/ibm/icu/text/DateFormat.java +++ b/icu4j/src/com/ibm/icu/text/DateFormat.java @@ -37,7 +37,7 @@ import java.text.NumberFormat; import java.util.Locale; import java.util.ResourceBundle; import java.util.MissingResourceException; -import java.util.TimeZone; +import com.ibm.util.TimeZone; import com.ibm.util.Calendar; import com.ibm.util.GregorianCalendar; import java.util.Date; @@ -118,9 +118,9 @@ import java.text.resources.*; * @see Format * @see NumberFormat * @see SimpleDateFormat - * @see java.util.Calendar - * @see java.util.GregorianCalendar - * @see java.util.TimeZone + * @see com.ibm.util.Calendar + * @see com.ibm.util.GregorianCalendar + * @see com.ibm.util.TimeZone * @version 1.37 11/02/99 * @author Mark Davis, Chen-Lieh Huang, Alan Liu */ @@ -582,7 +582,7 @@ public abstract class DateFormat extends Format { * do not precisely match this object's format. With strict parsing, * inputs must match this object's format. * @param lenient when true, parsing is lenient - * @see java.util.Calendar#setLenient + * @see com.ibm.util.Calendar#setLenient */ public void setLenient(boolean lenient) { diff --git a/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java b/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java index a1924f906a..6d7b2a3e6c 100755 --- a/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java +++ b/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java,v $ - * $Date: 2000/04/27 22:41:39 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:19:35 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -64,7 +64,7 @@ import com.ibm.util.Utility; * @see DateFormat * @see SimpleDateFormat - * @see java.util.SimpleTimeZone + * @see com.ibm.util.SimpleTimeZone * @version 1.31 09/21/99 * @author Chen-Lieh Huang */ @@ -169,7 +169,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { * are localized names. If a zone does not implement daylight savings * time, the daylight savings time names are ignored. * @see java.text.resources.DateFormatZoneData - * @see java.util.TimeZone + * @see com.ibm.util.TimeZone * @serial */ String zoneStrings[][] = null; @@ -505,7 +505,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { * @param ID the given time zone ID. * @return the index of the given time zone ID. Returns -1 if * the given time zone ID can't be located in the DateFormatSymbols object. - * @see java.util.SimpleTimeZone + * @see com.ibm.util.SimpleTimeZone */ final int getZoneIndex (String ID) { diff --git a/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java b/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java index 407fe44a12..84f2b33208 100755 --- a/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java +++ b/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java,v $ - * $Date: 2000/04/27 22:41:39 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:19:35 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -20,12 +20,12 @@ import java.text.NumberFormat; import java.text.FieldPosition; import java.text.ParsePosition; -import java.util.TimeZone; +import com.ibm.util.TimeZone; import com.ibm.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.ResourceBundle; -import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; import com.ibm.util.GregorianCalendar; import java.io.ObjectInputStream; import java.io.IOException; @@ -170,9 +170,9 @@ import java.lang.StringIndexOutOfBoundsException; * time zone. There is one common decimal format to handle all the numbers; * the digit count is handled programmatically according to the pattern. * - * @see java.util.Calendar - * @see java.util.GregorianCalendar - * @see java.util.TimeZone + * @see com.ibm.util.Calendar + * @see com.ibm.util.GregorianCalendar + * @see com.ibm.util.TimeZone * @see DateFormat * @see DateFormatSymbols * @see DecimalFormat diff --git a/icu4j/src/com/ibm/icu/util/BuddhistCalendar.java b/icu4j/src/com/ibm/icu/util/BuddhistCalendar.java index 21b0a7c002..45a25ded64 100755 --- a/icu4j/src/com/ibm/icu/util/BuddhistCalendar.java +++ b/icu4j/src/com/ibm/icu/util/BuddhistCalendar.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/BuddhistCalendar.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -16,7 +16,6 @@ package com.ibm.util; import java.util.Date; import com.ibm.util.GregorianCalendar; import java.util.Locale; -import java.util.TimeZone; /** * BuddhistCalendar is a subclass of GregorianCalendar @@ -33,7 +32,7 @@ import java.util.TimeZone; * calendar is not in lenient mode (see setLenient), dates before * 1/1/1 BE are rejected with an IllegalArgumentException. * - * @see java.util.GregorianCalendar + * @see com.ibm.util.GregorianCalendar * * @author Laura Werner */ @@ -49,7 +48,7 @@ public class BuddhistCalendar extends GregorianCalendar { * Constant for the Buddhist Era. This is the only allowable ERA * value for the Buddhist calendar. * - * @see java.util.Calendar#ERA + * @see com.ibm.util.Calendar#ERA */ public static final int BE = 0; diff --git a/icu4j/src/com/ibm/icu/util/Calendar.java b/icu4j/src/com/ibm/icu/util/Calendar.java index 2994d442b1..2cbe725516 100755 --- a/icu4j/src/com/ibm/icu/util/Calendar.java +++ b/icu4j/src/com/ibm/icu/util/Calendar.java @@ -33,7 +33,6 @@ import java.util.Date; import java.util.Hashtable; import java.util.Locale; import java.util.ResourceBundle; -import java.util.TimeZone; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; diff --git a/icu4j/src/com/ibm/icu/util/EasterHoliday.java b/icu4j/src/com/ibm/icu/util/EasterHoliday.java index 6d15021cff..bc37a82a92 100755 --- a/icu4j/src/com/ibm/icu/util/EasterHoliday.java +++ b/icu4j/src/com/ibm/icu/util/EasterHoliday.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/EasterHoliday.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -16,7 +16,7 @@ package com.ibm.util; import java.util.Date; import com.ibm.util.GregorianCalendar; import com.ibm.util.Calendar; -import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; /** * A Holiday subclass which represents holidays that occur diff --git a/icu4j/src/com/ibm/icu/util/GregorianCalendar.java b/icu4j/src/com/ibm/icu/util/GregorianCalendar.java index f1e00ea6f3..3cd09d5330 100755 --- a/icu4j/src/com/ibm/icu/util/GregorianCalendar.java +++ b/icu4j/src/com/ibm/icu/util/GregorianCalendar.java @@ -31,7 +31,6 @@ package com.ibm.util; import java.util.Date; import java.util.Locale; -import java.util.TimeZone; /** * GregorianCalendar is a concrete subclass of @@ -1184,8 +1183,9 @@ public class GregorianCalendar extends Calendar { // getOffset(..., monthLen). This makes some zones behave incorrectly. // Fix this later, if desired, by porting TimeZone and STZ to this pkg. // -Alan - int dstOffset = getTimeZone().getOffset(era,year,month,date,dayOfWeek,millisInDay /*, - monthLength(month), prevMonthLength(month)*/) + // [icu4j fixed after 'port' of tz&stz to com.ibm.util - liu] + int dstOffset = getTimeZone().getOffset(era,year,month,date,dayOfWeek,millisInDay, + monthLength(month), prevMonthLength(month)) - rawOffset; // Adjust our millisInDay for DST, if necessary. @@ -1525,14 +1525,15 @@ public class GregorianCalendar extends Calendar { // getOffset(..., millis). This makes some zones behave incorrectly. // Fix this later, if desired, by porting TimeZone and STZ to this pkg. // -Alan + // [icu4j fixed after 'port' of tz&stz to com.ibm.util - liu] dstOffset = zone.getOffset(era, internalGet(YEAR), internalGet(MONTH), internalGet(DATE), dow, - normalizedMillisInDay[0] /*, + normalizedMillisInDay[0], monthLength(internalGet(MONTH)), - prevMonthLength(internalGet(MONTH)) */) - + prevMonthLength(internalGet(MONTH))) - zoneOffset; // Note: Because we pass in wall millisInDay, rather than // standard millisInDay, we interpret "1:00 am" on the day diff --git a/icu4j/src/com/ibm/icu/util/HebrewCalendar.java b/icu4j/src/com/ibm/icu/util/HebrewCalendar.java index 6cd4c57464..86e9528766 100755 --- a/icu4j/src/com/ibm/icu/util/HebrewCalendar.java +++ b/icu4j/src/com/ibm/icu/util/HebrewCalendar.java @@ -5,17 +5,15 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/HebrewCalendar.java,v $ - * $Date: 2000/03/10 04:17:58 $ - * $Revision: 1.2 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.3 $ * ***************************************************************************************** */ package com.ibm.util; import java.util.Date; -import java.util.GregorianCalendar; import java.util.Locale; -import java.util.TimeZone; /** * HebrewCalendar is a subclass of Calendar @@ -63,7 +61,7 @@ import java.util.TimeZone; * http://www.pip.dknet.dk/~pip10160/calendar.html * *

- * @see java.util.GregorianCalendar + * @see com.ibm.util.GregorianCalendar * * @author Laura Werner */ @@ -352,7 +350,7 @@ public class HebrewCalendar extends IBMCalendar { * * @param field The field whose minimum value is desired. * - * @see java.util.Calendar#getMinimum + * @see com.ibm.util.Calendar#getMinimum */ public int getMinimum(int field) { @@ -570,7 +568,7 @@ public class HebrewCalendar extends IBMCalendar { //------------------------------------------------------------------------- // Functions for converting from field values to milliseconds and back... // - // These are overrides of abstract methods on java.util.Calendar + // These are overrides of abstract methods on com.ibm.util.Calendar //------------------------------------------------------------------------- /** @@ -1099,4 +1097,4 @@ public class HebrewCalendar extends IBMCalendar { System.out.println(str); } } -}; \ No newline at end of file +}; diff --git a/icu4j/src/com/ibm/icu/util/IslamicCalendar.java b/icu4j/src/com/ibm/icu/util/IslamicCalendar.java index 24dcc9a79f..039216dd22 100755 --- a/icu4j/src/com/ibm/icu/util/IslamicCalendar.java +++ b/icu4j/src/com/ibm/icu/util/IslamicCalendar.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/IslamicCalendar.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -16,7 +16,6 @@ import com.ibm.util.Calendar; import java.util.Date; import com.ibm.util.GregorianCalendar; import java.util.Locale; -import java.util.TimeZone; import com.ibm.util.CalendarAstronomer; /** @@ -69,7 +68,7 @@ import com.ibm.util.CalendarAstronomer; * fixed-cycle civil calendar is used. However, if setCivil(false) * is called, an approximation of the true lunar calendar will be used. * - * @see java.util.GregorianCalendar + * @see com.ibm.util.GregorianCalendar * * @author Laura Werner * @version 1.0 @@ -297,7 +296,7 @@ public class IslamicCalendar extends IBMCalendar { * * @param field The field whose minimum value is desired. * - * @see java.util.Calendar#getMinimum + * @see com.ibm.util.Calendar#getMinimum */ public int getMinimum(int field) { diff --git a/icu4j/src/com/ibm/icu/util/JapaneseCalendar.java b/icu4j/src/com/ibm/icu/util/JapaneseCalendar.java index 54ca8f1883..7746543254 100755 --- a/icu4j/src/com/ibm/icu/util/JapaneseCalendar.java +++ b/icu4j/src/com/ibm/icu/util/JapaneseCalendar.java @@ -5,18 +5,15 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/JapaneseCalendar.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ package com.ibm.util; import java.util.Date; -import com.ibm.util.GregorianCalendar; import java.util.Locale; -import java.util.SimpleTimeZone; -import java.util.TimeZone; /** * JapaneseCalendar is a subclass of GregorianCalendar @@ -43,7 +40,7 @@ import java.util.TimeZone; * constants rather than using actual, absolute numbers. *

* - * @see java.util.GregorianCalendar + * @see com.ibm.util.GregorianCalendar * * @author Laura Werner */ diff --git a/icu4j/src/com/ibm/icu/util/SimpleDateRule.java b/icu4j/src/com/ibm/icu/util/SimpleDateRule.java index 7daf738545..a34cb28f6e 100755 --- a/icu4j/src/com/ibm/icu/util/SimpleDateRule.java +++ b/icu4j/src/com/ibm/icu/util/SimpleDateRule.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/SimpleDateRule.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:20:11 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -16,7 +16,7 @@ package com.ibm.util; import java.util.Date; import com.ibm.util.Calendar; import com.ibm.util.GregorianCalendar; -import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; public class SimpleDateRule implements DateRule { diff --git a/icu4j/src/com/ibm/icu/util/SimpleTimeZone.java b/icu4j/src/com/ibm/icu/util/SimpleTimeZone.java new file mode 100755 index 0000000000..ef07b2e3b1 --- /dev/null +++ b/icu4j/src/com/ibm/icu/util/SimpleTimeZone.java @@ -0,0 +1,1461 @@ +/* + * @(#)SimpleTimeZone.java 1.38 00/01/19 + * + * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved. + * + * This software is the proprietary information of Sun Microsystems, Inc. + * Use is subject to license terms. + * + */ + +/* + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - All Rights Reserved + * + * The original version of this source code and documentation is copyrighted + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These + * materials are provided under terms of a License Agreement between Taligent + * and Sun. This technology is protected by multiple US and International + * patents. This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + */ + +package com.ibm.util; + +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.IOException; +import java.util.Date; + +/** + * SimpleTimeZone is a concrete subclass of TimeZone + * that represents a time zone for use with a Gregorian calendar. This + * class does not handle historical changes. + * + *

+ * Use a negative value for dayOfWeekInMonth to indicate that + * SimpleTimeZone should count from the end of the month backwards. + * For example, Daylight Savings Time ends at the last + * (dayOfWeekInMonth = -1) Sunday in October, at 2 AM in standard time. + * + * @see Calendar + * @see GregorianCalendar + * @see TimeZone + * @version 1.38 01/19/00 + * @author David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu + */ +public class SimpleTimeZone extends TimeZone { + /** + * Constructs a SimpleTimeZone with the given base time zone offset from GMT + * and time zone ID. Timezone IDs can be obtained from + * TimeZone.getAvailableIDs. Normally you should use TimeZone.getDefault to + * construct a TimeZone. + * + * @param rawOffset The given base time zone offset to GMT. + * @param ID The time zone ID which is obtained from + * TimeZone.getAvailableIDs. + */ + public SimpleTimeZone(int rawOffset, String ID) + { + this.rawOffset = rawOffset; + setID (ID); + dstSavings = millisPerHour; // In case user sets rules later + } + + /** + * Construct a SimpleTimeZone with the given base time zone offset from + * GMT, time zone ID, time to start and end the daylight time. Timezone IDs + * can be obtained from TimeZone.getAvailableIDs. Normally you should use + * TimeZone.getDefault to create a TimeZone. For a time zone that does not + * use daylight saving time, do not use this constructor; instead you should + * use SimpleTimeZone(rawOffset, ID). + * + * By default, this constructor specifies day-of-week-in-month rules. That + * is, if the startDay is 1, and the startDayOfWeek is SUNDAY, then this + * indicates the first Sunday in the startMonth. A startDay of -1 likewise + * indicates the last Sunday. However, by using negative or zero values for + * certain parameters, other types of rules can be specified. + * + * Day of month. To specify an exact day of the month, such as March 1, set + * startDayOfWeek to zero. + * + * Day of week after day of month. To specify the first day of the week + * occurring on or after an exact day of the month, make the day of the week + * negative. For example, if startDay is 5 and startDayOfWeek is -MONDAY, + * this indicates the first Monday on or after the 5th day of the + * startMonth. + * + * Day of week before day of month. To specify the last day of the week + * occurring on or before an exact day of the month, make the day of the + * week and the day of the month negative. For example, if startDay is -21 + * and startDayOfWeek is -WEDNESDAY, this indicates the last Wednesday on or + * before the 21st of the startMonth. + * + * The above examples refer to the startMonth, startDay, and startDayOfWeek; + * the same applies for the endMonth, endDay, and endDayOfWeek. + * + * @param rawOffset The given base time zone offset to GMT. + * @param ID The time zone ID which is obtained from + * TimeZone.getAvailableIDs. + * @param startMonth The daylight savings starting month. Month is + * 0-based. eg, 0 for January. + * @param startDay The daylight savings starting + * day-of-week-in-month. Please see the member + * description for an example. + * @param startDayOfWeek The daylight savings starting day-of-week. Please + * see the member description for an example. + * @param startTime The daylight savings starting time in local wall + * time, which is standard time in this case. Please see the + * member description for an example. + * @param endMonth The daylight savings ending month. Month is + * 0-based. eg, 0 for January. + * @param endDay The daylight savings ending day-of-week-in-month. + * Please see the member description for an example. + * @param endDayOfWeek The daylight savings ending day-of-week. Please + * see the member description for an example. + * @param endTime The daylight savings ending time in local wall time, + * which is daylight time in this case. Please see the + * member description for an example. + * @exception IllegalArgumentException the month, day, dayOfWeek, or time + * parameters are out of range for the start or end rule + * @since JDK1.1 + */ + public SimpleTimeZone(int rawOffset, String ID, + int startMonth, int startDay, int startDayOfWeek, int startTime, + int endMonth, int endDay, int endDayOfWeek, int endTime) + { + this(rawOffset, ID, + startMonth, startDay, startDayOfWeek, startTime, WALL_TIME, + endMonth, endDay, endDayOfWeek, endTime, WALL_TIME, + millisPerHour); + } + + /** + * Constructor. This constructor is identical to the 10-argument + * constructor, but also takes a dstSavings parameter. + * @param dstSavings The amount of time in ms saved during DST. + * @exception IllegalArgumentException the month, day, dayOfWeek, or time + * parameters are out of range for the start or end rule + * @since 1.2 + */ + public SimpleTimeZone(int rawOffset, String ID, + int startMonth, int startDay, int startDayOfWeek, int startTime, + int endMonth, int endDay, int endDayOfWeek, int endTime, + int dstSavings) + { + this(rawOffset, ID, + startMonth, startDay, startDayOfWeek, startTime, WALL_TIME, + endMonth, endDay, endDayOfWeek, endTime, WALL_TIME, + dstSavings); + } + + /** + * Constructor. + */ + SimpleTimeZone(int rawOffset, String ID, + int startMonth, int startDay, int startDayOfWeek, + int startTime, int startTimeMode, + int endMonth, int endDay, int endDayOfWeek, + int endTime, int endTimeMode, + int dstSavings) { + setID(ID); + this.rawOffset = rawOffset; + this.startMonth = startMonth; + this.startDay = startDay; + this.startDayOfWeek = startDayOfWeek; + this.startTime = startTime; + this.startTimeMode = startTimeMode; + this.endMonth = endMonth; + this.endDay = endDay; + this.endDayOfWeek = endDayOfWeek; + this.endTime = endTime; + this.endTimeMode = endTimeMode; + this.dstSavings = dstSavings; + // this.useDaylight = true; // Set by decodeRules + decodeRules(); + if (dstSavings <= 0) { + throw new IllegalArgumentException("Illegal DST savings"); + } + } + + /** + * Sets the daylight savings starting year. + * + * @param year The daylight savings starting year. + */ + public void setStartYear(int year) + { + startYear = year; + } + + /** + * Sets the daylight savings starting rule. For example, Daylight Savings + * Time starts at the first Sunday in April, at 2 AM in standard time. + * Therefore, you can set the start rule by calling: + * setStartRule(TimeFields.APRIL, 1, TimeFields.SUNDAY, 2*60*60*1000); + * + * @param month The daylight savings starting month. Month is + * 0-based. eg, 0 for January. + * @param dayOfWeekInMonth The daylight savings starting + * day-of-week-in-month. Please see the member + * description for an example. + * @param dayOfWeek The daylight savings starting day-of-week. + * Please see the member description for an + * example. + * @param time The daylight savings starting time in local wall + * time, which is standard time in this case. Please see + * the member description for an example. + * @exception IllegalArgumentException the month, dayOfWeekInMonth, + * dayOfWeek, or time parameters are out of range + */ + public void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, + int time) + { + startMonth = month; + startDay = dayOfWeekInMonth; + startDayOfWeek = dayOfWeek; + startTime = time; + startTimeMode = WALL_TIME; + // useDaylight = true; // Set by decodeRules + decodeStartRule(); + } + + /** + * Sets the DST start rule to a fixed date within a month. + * + * @param month The month in which this rule occurs (0-based). + * @param dayOfMonth The date in that month (1-based). + * @param time The time of that day (number of millis after midnight) + * when DST takes effect in local wall time, which is + * standard time in this case. + * @exception IllegalArgumentException the month, + * dayOfMonth, or time parameters are out of range + * @since 1.2 + */ + public void setStartRule(int month, int dayOfMonth, int time) { + setStartRule(month, dayOfMonth, 0, time); + } + + /** + * Sets the DST start rule to a weekday before or after a give date within + * a month, e.g., the first Monday on or after the 8th. + * + * @param month The month in which this rule occurs (0-based). + * @param dayOfMonth A date within that month (1-based). + * @param dayOfWeek The day of the week on which this rule occurs. + * @param time The time of that day (number of millis after midnight) + * when DST takes effect in local wall time, which is + * standard time in this case. + * @param after If true, this rule selects the first dayOfWeek on + * or after dayOfMonth. If false, this rule selects + * the last dayOfWeek on or before dayOfMonth. + * @exception IllegalArgumentException the month, dayOfMonth, + * dayOfWeek, or time parameters are out of range + * @since 1.2 + */ + public void setStartRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) + { + if (after) + setStartRule(month, dayOfMonth, -dayOfWeek, time); + else + setStartRule(month, -dayOfMonth, -dayOfWeek, time); + } + + /** + * Sets the daylight savings ending rule. For example, Daylight Savings Time + * ends at the last (-1) Sunday in October, at 2 AM in standard time. + * Therefore, you can set the end rule by calling: + * setEndRule(TimeFields.OCTOBER, -1, TimeFields.SUNDAY, 2*60*60*1000); + * + * @param month The daylight savings ending month. Month is + * 0-based. eg, 0 for January. + * @param dayOfWeekInMonth The daylight savings ending + * day-of-week-in-month. Please see the member + * description for an example. + * @param dayOfWeek The daylight savings ending day-of-week. Please + * see the member description for an example. + * @param time The daylight savings ending time in local wall time, + * which is daylight time in this case. Please see the + * member description for an example. + * @exception IllegalArgumentException the month, dayOfWeekInMonth, + * dayOfWeek, or time parameters are out of range + */ + public void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, + int time) + { + endMonth = month; + endDay = dayOfWeekInMonth; + endDayOfWeek = dayOfWeek; + endTime = time; + endTimeMode = WALL_TIME; + // useDaylight = true; // Set by decodeRules + decodeEndRule(); + } + + /** + * Sets the DST end rule to a fixed date within a month. + * + * @param month The month in which this rule occurs (0-based). + * @param dayOfMonth The date in that month (1-based). + * @param time The time of that day (number of millis after midnight) + * when DST ends in local wall time, which is daylight + * time in this case. + * @exception IllegalArgumentException the month, + * dayOfMonth, or time parameters are out of range + * @since 1.2 + */ + public void setEndRule(int month, int dayOfMonth, int time) + { + setEndRule(month, dayOfMonth, 0, time); + } + + /** + * Sets the DST end rule to a weekday before or after a give date within + * a month, e.g., the first Monday on or after the 8th. + * + * @param month The month in which this rule occurs (0-based). + * @param dayOfMonth A date within that month (1-based). + * @param dayOfWeek The day of the week on which this rule occurs. + * @param time The time of that day (number of millis after midnight) + * when DST ends in local wall time, which is daylight + * time in this case. + * @param after If true, this rule selects the first dayOfWeek on + * or after dayOfMonth. If false, this rule selects + * the last dayOfWeek on or before dayOfMonth. + * @exception IllegalArgumentException the month, dayOfMonth, + * dayOfWeek, or time parameters are out of range + * @since 1.2 + */ + public void setEndRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) + { + if (after) + setEndRule(month, dayOfMonth, -dayOfWeek, time); + else + setEndRule(month, -dayOfMonth, -dayOfWeek, time); + } + + /** + * Returns the difference in milliseconds between local time and + * UTC, taking into account both the raw offset and the effect of + * daylight savings, for the specified date and time. This method + * assumes that the start and end month are distinct. It also + * uses a default {@link GregorianCalendar} object as its + * underlying calendar, such as for determining leap years. Do + * not use the result of this method with a calendar other than a + * default GregorianCalendar. + * + *

Note: In general, clients should use + * Calendar.get(ZONE_OFFSET) + Calendar.get(DST_OFFSET) + * instead of calling this method. + * + * @param era The era of the given date. + * @param year The year in the given date. + * @param month The month in the given date. Month is 0-based. e.g., + * 0 for January. + * @param day The day-in-month of the given date. + * @param dayOfWeek The day-of-week of the given date. + * @param millis The milliseconds in day in standard local time. + * @return The milliseconds to add to UTC to get local time. + * @exception IllegalArgumentException the era, month, day, + * dayOfWeek, or millis parameters are out of range + */ + public int getOffset(int era, int year, int month, int day, int dayOfWeek, + int millis) + { + // Check the month before indexing into staticMonthLength. This + // duplicates the test that occurs in the 7-argument getOffset(), + // however, this is unavoidable. We don't mind because this method, in + // fact, should not be called; internal code should always call the + // 7-argument getOffset(), and outside code should use Calendar.get(int + // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of + // this method because it's public API. - liu 8/10/98 + if (month < Calendar.JANUARY + || month > Calendar.DECEMBER) { + throw new IllegalArgumentException("Illegal month " + month); + } + int monthLength, prevMonthLength; + if ((era == GregorianCalendar.AD) && internalCal.isLeapYear(year)) { + monthLength = staticLeapMonthLength[month]; + prevMonthLength = (month > 1) ? staticLeapMonthLength[month - 1] : 31; + } else { + monthLength = staticMonthLength[month]; + prevMonthLength = (month > 1) ? staticMonthLength[month - 1] : 31; + } + + return getOffset(era, year, month, day, dayOfWeek, millis, + monthLength, prevMonthLength); + } + + /** + * Gets offset, for current date, modified in case of + * daylight savings. This is the offset to add to UTC to get local time. + * Gets the time zone offset, for current date, modified in case of daylight + * savings. This is the offset to add *to* UTC to get local time. Assume + * that the start and end month are distinct. + * @param era The era of the given date. + * @param year The year in the given date. + * @param month The month in the given date. Month is 0-based. e.g., + * 0 for January. + * @param day The day-in-month of the given date. + * @param dayOfWeek The day-of-week of the given date. + * @param millis The milliseconds in day in standard local time. + * @param monthLength The length of the given month in days. + * @param prevMonthLength The length of the previous month in days. + * @return The offset to add *to* GMT to get local time. + * @exception IllegalArgumentException the era, month, day, + * dayOfWeek, millis, or monthLength parameters are out of range + */ + int getOffset(int era, int year, int month, int day, int dayOfWeek, + int millis, int monthLength, int prevMonthLength) { + if (false) { + /* Use this parameter checking code for normal operation. Only one + * of these two blocks should actually get compiled into the class + * file. */ + if ((era != GregorianCalendar.AD && era != GregorianCalendar.BC) + || month < Calendar.JANUARY + || month > Calendar.DECEMBER + || day < 1 + || day > monthLength + || dayOfWeek < Calendar.SUNDAY + || dayOfWeek > Calendar.SATURDAY + || millis < 0 + || millis >= millisPerDay + || monthLength < 28 + || monthLength > 31 + || prevMonthLength < 28 + || prevMonthLength > 31) { + throw new IllegalArgumentException(); + } + } else { + /* This parameter checking code is better for debugging, but + * overkill for normal operation. Only one of these two blocks + * should actually get compiled into the class file. */ + if (era != GregorianCalendar.AD && era != GregorianCalendar.BC) { + throw new IllegalArgumentException("Illegal era " + era); + } + if (month < Calendar.JANUARY + || month > Calendar.DECEMBER) { + throw new IllegalArgumentException("Illegal month " + month); + } + if (day < 1 + || day > monthLength) { + throw new IllegalArgumentException("Illegal day " + day); + } + if (dayOfWeek < Calendar.SUNDAY + || dayOfWeek > Calendar.SATURDAY) { + throw new IllegalArgumentException("Illegal day of week " + dayOfWeek); + } + if (millis < 0 + || millis >= millisPerDay) { + throw new IllegalArgumentException("Illegal millis " + millis); + } + if (monthLength < 28 + || monthLength > 31) { + throw new IllegalArgumentException("Illegal month length " + monthLength); + } + if (prevMonthLength < 28 + || prevMonthLength > 31) { + throw new IllegalArgumentException("Illegal previous month length " + prevMonthLength); + } + } + + int result = rawOffset; + + // Bail out if we are before the onset of daylight savings time + if (!useDaylight || year < startYear || era != GregorianCalendar.AD) return result; + + // Check for southern hemisphere. We assume that the start and end + // month are different. + boolean southern = (startMonth > endMonth); + + // Compare the date to the starting and ending rules.+1 = date>rule, -1 + // = date= 0)) { + /* For the ending rule comparison, we add the dstSavings to the millis + * passed in to convert them from standard to wall time. We then must + * normalize the millis to the range 0..millisPerDay-1. */ + endCompare = compareToRule(month, monthLength, prevMonthLength, + day, dayOfWeek, millis, + endTimeMode == WALL_TIME ? dstSavings : + (endTimeMode == UTC_TIME ? -rawOffset : 0), + endMode, endMonth, endDayOfWeek, + endDay, endTime); + } + + // Check for both the northern and southern hemisphere cases. We + // assume that in the northern hemisphere, the start rule is before the + // end rule within the calendar year, and vice versa for the southern + // hemisphere. + if ((!southern && (startCompare >= 0 && endCompare < 0)) || + (southern && (startCompare >= 0 || endCompare < 0))) + result += dstSavings; + + return result; + } + + /** + * Compare a given date in the year to a rule. Return 1, 0, or -1, depending + * on whether the date is after, equal to, or before the rule date. The + * millis are compared directly against the ruleMillis, so any + * standard-daylight adjustments must be handled by the caller. + * + * @return 1 if the date is after the rule date, -1 if the date is before + * the rule date, or 0 if the date is equal to the rule date. + */ + private static int compareToRule(int month, int monthLen, int prevMonthLen, + int dayOfMonth, + int dayOfWeek, int millis, int millisDelta, + int ruleMode, int ruleMonth, int ruleDayOfWeek, + int ruleDay, int ruleMillis) + { + // Make adjustments for startTimeMode and endTimeMode + millis += millisDelta; + while (millis >= millisPerDay) { + millis -= millisPerDay; + ++dayOfMonth; + dayOfWeek = 1 + (dayOfWeek % 7); // dayOfWeek is one-based + if (dayOfMonth > monthLen) { + dayOfMonth = 1; + /* When incrementing the month, it is desirible to overflow + * from DECEMBER to DECEMBER+1, since we use the result to + * compare against a real month. Wraparound of the value + * leads to bug 4173604. */ + ++month; + } + } + while (millis < 0) { + millis += millisPerDay; + --dayOfMonth; + dayOfWeek = 1 + ((dayOfWeek+5) % 7); // dayOfWeek is one-based + if (dayOfMonth < 1) { + dayOfMonth = prevMonthLen; + --month; + } + } + + if (month < ruleMonth) return -1; + else if (month > ruleMonth) return 1; + + int ruleDayOfMonth = 0; + switch (ruleMode) + { + case DOM_MODE: + ruleDayOfMonth = ruleDay; + break; + case DOW_IN_MONTH_MODE: + // In this case ruleDay is the day-of-week-in-month + if (ruleDay > 0) + ruleDayOfMonth = 1 + (ruleDay - 1) * 7 + + (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7; + else // Assume ruleDay < 0 here + { + ruleDayOfMonth = monthLen + (ruleDay + 1) * 7 - + (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7; + } + break; + case DOW_GE_DOM_MODE: + ruleDayOfMonth = ruleDay + + (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth) % 7; + break; + case DOW_LE_DOM_MODE: + ruleDayOfMonth = ruleDay - + (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth) % 7; + // Note at this point ruleDayOfMonth may be <1, although it will + // be >=1 for well-formed rules. + break; + } + + if (dayOfMonth < ruleDayOfMonth) return -1; + else if (dayOfMonth > ruleDayOfMonth) return 1; + + if (millis < ruleMillis) return -1; + else if (millis > ruleMillis) return 1; + else return 0; + } + + /** + * Overrides TimeZone + * Gets the GMT offset for this time zone. + */ + public int getRawOffset() + { + // The given date will be taken into account while + // we have the historical time zone data in place. + return rawOffset; + } + + /** + * Overrides TimeZone + * Sets the base time zone offset to GMT. + * This is the offset to add *to* UTC to get local time. + * Please see TimeZone.setRawOffset for descriptions on the parameter. + */ + public void setRawOffset(int offsetMillis) + { + this.rawOffset = offsetMillis; + } + + /** + * Sets the amount of time in ms that the clock is advanced during DST. + * @param millisSavedDuringDST the number of milliseconds the time is + * advanced with respect to standard time when the daylight savings rules + * are in effect. A positive number, typically one hour (3600000). + * @since 1.2 + */ + public void setDSTSavings(int millisSavedDuringDST) { + if (millisSavedDuringDST <= 0) { + throw new IllegalArgumentException("Illegal DST savings"); + } + dstSavings = millisSavedDuringDST; + } + + /** + * Returns the amount of time in ms that the clock is advanced during DST. + * @return the number of milliseconds the time is + * advanced with respect to standard time when the daylight savings rules + * are in effect. A positive number, typically one hour (3600000). + * @since 1.2 + */ + public int getDSTSavings() { + return dstSavings; + } + + /** + * Overrides TimeZone + * Queries if this time zone uses Daylight Savings Time. + */ + public boolean useDaylightTime() + { + return useDaylight; + } + + /** + * Overrides TimeZone + * Queries if the given date is in Daylight Savings Time. + */ + public boolean inDaylightTime(Date date) + { + GregorianCalendar gc = new GregorianCalendar(this); + gc.setTime(date); + return gc.inDaylightTime(); + } + + /** + * Overrides Cloneable + */ + public Object clone() + { + return super.clone(); + // other fields are bit-copied + } + + /** + * Override hashCode. + * Generates the hash code for the SimpleDateFormat object + */ + public synchronized int hashCode() + { + return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^ + endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset; + } + + /** + * Compares the equality of two SimpleTimeZone objects. + * + * @param obj The SimpleTimeZone object to be compared with. + * @return True if the given obj is the same as this SimpleTimeZone + * object; false otherwise. + */ + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (!(obj instanceof SimpleTimeZone)) + return false; + + SimpleTimeZone that = (SimpleTimeZone) obj; + + return getID().equals(that.getID()) && + hasSameRules(that); + } + + /** + * Return true if this zone has the same rules and offset as another zone. + * @param other the TimeZone object to be compared with + * @return true if the given zone has the same rules and offset as this one + * @since 1.2 + */ + public boolean hasSameRules(TimeZone other) { + if (this == other) return true; + if (!(other instanceof SimpleTimeZone)) return false; + SimpleTimeZone that = (SimpleTimeZone) other; + return rawOffset == that.rawOffset && + useDaylight == that.useDaylight && + (!useDaylight + // Only check rules if using DST + || (dstSavings == that.dstSavings && + startMode == that.startMode && + startMonth == that.startMonth && + startDay == that.startDay && + startDayOfWeek == that.startDayOfWeek && + startTime == that.startTime && + startTimeMode == that.startTimeMode && + endMode == that.endMode && + endMonth == that.endMonth && + endDay == that.endDay && + endDayOfWeek == that.endDayOfWeek && + endTime == that.endTime && + endTimeMode == that.endTimeMode && + startYear == that.startYear)); + } + + /** + * Return a string representation of this time zone. + * @return a string representation of this time zone. + */ + public String toString() { + return getClass().getName() + + "[id=" + getID() + + ",offset=" + rawOffset + + ",dstSavings=" + dstSavings + + ",useDaylight=" + useDaylight + + ",startYear=" + startYear + + ",startMode=" + startMode + + ",startMonth=" + startMonth + + ",startDay=" + startDay + + ",startDayOfWeek=" + startDayOfWeek + + ",startTime=" + startTime + + ",startTimeMode=" + startTimeMode + + ",endMode=" + endMode + + ",endMonth=" + endMonth + + ",endDay=" + endDay + + ",endDayOfWeek=" + endDayOfWeek + + ",endTime=" + endTime + + ",endTimeMode=" + endTimeMode + ']'; + } + + // =======================privates=============================== + + /** + * The month in which daylight savings time starts. This value must be + * between Calendar.JANUARY and + * Calendar.DECEMBER inclusive. This value must not equal + * endMonth. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int startMonth; + + /** + * This field has two possible interpretations: + *

+ *
startMode == DOW_IN_MONTH
+ *
+ * startDay indicates the day of the month of + * startMonth on which daylight + * savings time starts, from 1 to 28, 30, or 31, depending on the + * startMonth. + *
+ *
startMode != DOW_IN_MONTH
+ *
+ * startDay indicates which startDayOfWeek in th + * month startMonth daylight + * savings time starts on. For example, a value of +1 and a + * startDayOfWeek of Calendar.SUNDAY indicates the + * first Sunday of startMonth. Likewise, +2 would indicate the + * second Sunday, and -1 the last Sunday. A value of 0 is illegal. + *
+ * + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int startDay; + + /** + * The day of the week on which daylight savings time starts. This value + * must be between Calendar.SUNDAY and + * Calendar.SATURDAY inclusive. + *

If useDaylight is false or + * startMode == DAY_OF_MONTH, this value is ignored. + * @serial + */ + private int startDayOfWeek; + + /** + * The time in milliseconds after midnight at which daylight savings + * time starts. This value is expressed as wall time, standard time, + * or UTC time, depending on the setting of startTimeMode. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int startTime; + + /** + * The format of startTime, either WALL_TIME, STANDARD_TIME, or UTC_TIME. + * @serial + * @since JDK 1.3 + */ + private int startTimeMode; + + /** + * The month in which daylight savings time ends. This value must be + * between Calendar.JANUARY and + * Calendar.UNDECIMBER. This value must not equal + * startMonth. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int endMonth; + + /** + * This field has two possible interpretations: + *

+ *
endMode == DOW_IN_MONTH
+ *
+ * endDay indicates the day of the month of + * endMonth on which daylight + * savings time ends, from 1 to 28, 30, or 31, depending on the + * endMonth. + *
+ *
endMode != DOW_IN_MONTH
+ *
+ * endDay indicates which endDayOfWeek in th + * month endMonth daylight + * savings time ends on. For example, a value of +1 and a + * endDayOfWeek of Calendar.SUNDAY indicates the + * first Sunday of endMonth. Likewise, +2 would indicate the + * second Sunday, and -1 the last Sunday. A value of 0 is illegal. + *
+ * + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int endDay; + + /** + * The day of the week on which daylight savings time ends. This value + * must be between Calendar.SUNDAY and + * Calendar.SATURDAY inclusive. + *

If useDaylight is false or + * endMode == DAY_OF_MONTH, this value is ignored. + * @serial + */ + private int endDayOfWeek; + + /** + * The time in milliseconds after midnight at which daylight savings + * time ends. This value is expressed as wall time, standard time, + * or UTC time, depending on the setting of endTimeMode. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int endTime; + + /** + * The format of endTime, either WALL_TIME, STANDARD_TIME, or UTC_TIME. + * @serial + * @since JDK 1.3 + */ + private int endTimeMode; + + /** + * The year in which daylight savings time is first observed. This is an AD + * value. If this value is less than 1 then daylight savings is observed + * for all AD years. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int startYear; + + /** + * The offset in milliseconds between this zone and GMT. Negative offsets + * are to the west of Greenwich. To obtain local standard time, + * add the offset to GMT time. To obtain local wall time it may also be + * necessary to add dstSavings. + * @serial + */ + private int rawOffset; + + /** + * A boolean value which is true if and only if this zone uses daylight + * savings time. If this value is false, several other fields are ignored. + * @serial + */ + private boolean useDaylight=false; // indicate if this time zone uses DST + + private static final int millisPerHour = 60*60*1000; + private static final int millisPerDay = 24*millisPerHour; + + /** + * This field was serialized in JDK 1.1, so we have to keep it that way + * to maintain serialization compatibility. However, there's no need to + * recreate the array each time we create a new time zone. + * @serial An array of bytes containing the values {31, 28, 31, 30, 31, 30, + * 31, 31, 30, 31, 30, 31}. This is ignored as of the Java 2 platform v1.2, however, it must + * be streamed out for compatibility with JDK 1.1. + */ + private final byte monthLength[] = staticMonthLength; + private final static byte staticMonthLength[] = {31,28,31,30,31,30,31,31,30,31,30,31}; + private final static byte staticLeapMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31}; + // Hack: Use the y/m/d constructor in the following line. + // This prevents the infinite recursion that results when + // the GC wants to call STZ.getOffset. - liu + private static GregorianCalendar internalCal = new GregorianCalendar(0, 0, 0); + + /** + * Variables specifying the mode of the start rule. Takes the following + * values: + *

+ *
DOM_MODE
+ *
+ * Exact day of week; e.g., March 1. + *
+ *
DOW_IN_MONTH_MODE
+ *
+ * Day of week in month; e.g., last Sunday in March. + *
+ *
DOW_GE_DOM_MODE
+ *
+ * Day of week after day of month; e.g., Sunday on or after March 15. + *
+ *
DOW_LE_DOM_MODE
+ *
+ * Day of week before day of month; e.g., Sunday on or before March 15. + *
+ *
+ * The setting of this field affects the interpretation of the + * startDay field. + *

If useDaylight is false, this value is ignored. + * @serial + * @since JDK1.1.4 + */ + private int startMode; + + /** + * Variables specifying the mode of the end rule. Takes the following + * values: + *

+ *
DOM_MODE
+ *
+ * Exact day of week; e.g., March 1. + *
+ *
DOW_IN_MONTH_MODE
+ *
+ * Day of week in month; e.g., last Sunday in March. + *
+ *
DOW_GE_DOM_MODE
+ *
+ * Day of week after day of month; e.g., Sunday on or after March 15. + *
+ *
DOW_LE_DOM_MODE
+ *
+ * Day of week before day of month; e.g., Sunday on or before March 15. + *
+ *
+ * The setting of this field affects the interpretation of the + * endDay field. + *

If useDaylight is false, this value is ignored. + * @serial + * @since JDK1.1.4 + */ + private int endMode; + + /** + * A positive value indicating the amount of time saved during DST in + * milliseconds. + * Typically one hour (3600000); sometimes 30 minutes (1800000). + *

If useDaylight is false, this value is ignored. + * @serial + * @since JDK1.1.4 + */ + private int dstSavings; + + /** + * Constants specifying values of startMode and endMode. + */ + private static final int DOM_MODE = 1; // Exact day of month, "Mar 1" + private static final int DOW_IN_MONTH_MODE = 2; // Day of week in month, "lastSun" + private static final int DOW_GE_DOM_MODE = 3; // Day of week after day of month, "Sun>=15" + private static final int DOW_LE_DOM_MODE = 4; // Day of week before day of month, "Sun<=21" + + /** + * Constant for a rule specified as wall time. Wall time is standard time + * for the onset rule, and daylight time for the end rule. Most rules + * are specified as wall time. + */ + static final int WALL_TIME = 0; // Zero for backward compatibility + + /** + * Constant for a rule specified as standard time. + */ + static final int STANDARD_TIME = 1; + + /** + * Constant for a rule specified as UTC. EU rules are specified as UTC + * time. + */ + static final int UTC_TIME = 2; + + // Proclaim compatibility with 1.1 + static final long serialVersionUID = -403250971215465050L; + + // the internal serial version which says which version was written + // - 0 (default) for version up to JDK 1.1.3 + // - 1 for version from JDK 1.1.4, which includes 3 new fields + // - 2 for JDK 1.3, which includes 2 new files + static final int currentSerialVersion = 2; + + /** + * The version of the serialized data on the stream. Possible values: + *

+ *
0 or not present on stream
+ *
+ * JDK 1.1.3 or earlier. + *
+ *
1
+ *
+ * JDK 1.1.4 or later. Includes three new fields: startMode, + * endMode, and dstSavings. + *
+ *
2
+ *
+ * JDK 1.3 or later. Includes two new fields: startTimeMode + * and endTimeMode. + *
+ *
+ * When streaming out this class, the most recent format + * and the highest allowable serialVersionOnStream + * is written. + * @serial + * @since JDK1.1.4 + */ + private int serialVersionOnStream = currentSerialVersion; + + //---------------------------------------------------------------------- + // Rule representation + // + // We represent the following flavors of rules: + // 5 the fifth of the month + // lastSun the last Sunday in the month + // lastMon the last Monday in the month + // Sun>=8 first Sunday on or after the eighth + // Sun<=25 last Sunday on or before the 25th + // This is further complicated by the fact that we need to remain + // backward compatible with the 1.1 FCS. Finally, we need to minimize + // API changes. In order to satisfy these requirements, we support + // three representation systems, and we translate between them. + // + // INTERNAL REPRESENTATION + // This is the format SimpleTimeZone objects take after construction or + // streaming in is complete. Rules are represented directly, using an + // unencoded format. We will discuss the start rule only below; the end + // rule is analogous. + // startMode Takes on enumerated values DAY_OF_MONTH, + // DOW_IN_MONTH, DOW_AFTER_DOM, or DOW_BEFORE_DOM. + // startDay The day of the month, or for DOW_IN_MONTH mode, a + // value indicating which DOW, such as +1 for first, + // +2 for second, -1 for last, etc. + // startDayOfWeek The day of the week. Ignored for DAY_OF_MONTH. + // + // ENCODED REPRESENTATION + // This is the format accepted by the constructor and by setStartRule() + // and setEndRule(). It uses various combinations of positive, negative, + // and zero values to encode the different rules. This representation + // allows us to specify all the different rule flavors without altering + // the API. + // MODE startMonth startDay startDayOfWeek + // DOW_IN_MONTH_MODE >=0 !=0 >0 + // DOM_MODE >=0 >0 ==0 + // DOW_GE_DOM_MODE >=0 >0 <0 + // DOW_LE_DOM_MODE >=0 <0 <0 + // (no DST) don't care ==0 don't care + // + // STREAMED REPRESENTATION + // We must retain binary compatibility with the 1.1 FCS. The 1.1 code only + // handles DOW_IN_MONTH_MODE and non-DST mode, the latter indicated by the + // flag useDaylight. When we stream an object out, we translate into an + // approximate DOW_IN_MONTH_MODE representation so the object can be parsed + // and used by 1.1 code. Following that, we write out the full + // representation separately so that contemporary code can recognize and + // parse it. The full representation is written in a "packed" format, + // consisting of a version number, a length, and an array of bytes. Future + // versions of this class may specify different versions. If they wish to + // include additional data, they should do so by storing them after the + // packed representation below. + //---------------------------------------------------------------------- + + /** + * Given a set of encoded rules in startDay and startDayOfMonth, decode + * them and set the startMode appropriately. Do the same for endDay and + * endDayOfMonth. Upon entry, the day of week variables may be zero or + * negative, in order to indicate special modes. The day of month + * variables may also be negative. Upon exit, the mode variables will be + * set, and the day of week and day of month variables will be positive. + * This method also recognizes a startDay or endDay of zero as indicating + * no DST. + */ + private void decodeRules() + { + decodeStartRule(); + decodeEndRule(); + } + + /** + * Decode the start rule and validate the parameters. The parameters are + * expected to be in encoded form, which represents the various rule modes + * by negating or zeroing certain values. Representation formats are: + *

+ *

+     *            DOW_IN_MONTH  DOM    DOW>=DOM  DOW<=DOM  no DST
+     *            ------------  -----  --------  --------  ----------
+     * month       0..11        same    same      same     don't care
+     * day        -5..5         1..31   1..31    -1..-31   0
+     * dayOfWeek   1..7         0      -1..-7    -1..-7    don't care
+     * time        0..ONEDAY    same    same      same     don't care
+     * 
+ * The range for month does not include UNDECIMBER since this class is + * really specific to GregorianCalendar, which does not use that month. + * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the + * end rule is an exclusive limit point. That is, the range of times that + * are in DST include those >= the start and < the end. For this reason, + * it should be possible to specify an end of ONEDAY in order to include the + * entire day. Although this is equivalent to time 0 of the following day, + * it's not always possible to specify that, for example, on December 31. + * While arguably the start range should still be 0..ONEDAY-1, we keep + * the start and end ranges the same for consistency. + */ + private void decodeStartRule() { + useDaylight = (startDay != 0) && (endDay != 0); + if (startDay != 0) { + if (startMonth < Calendar.JANUARY || startMonth > Calendar.DECEMBER) { + throw new IllegalArgumentException( + "Illegal start month " + startMonth); + } + if (startTime < 0 || startTime >= millisPerDay) { + throw new IllegalArgumentException( + "Illegal start time " + startTime); + } + if (startDayOfWeek == 0) { + startMode = DOM_MODE; + } else { + if (startDayOfWeek > 0) { + startMode = DOW_IN_MONTH_MODE; + } else { + startDayOfWeek = -startDayOfWeek; + if (startDay > 0) { + startMode = DOW_GE_DOM_MODE; + } else { + startDay = -startDay; + startMode = DOW_LE_DOM_MODE; + } + } + if (startDayOfWeek > Calendar.SATURDAY) { + throw new IllegalArgumentException( + "Illegal start day of week " + startDayOfWeek); + } + } + if (startMode == DOW_IN_MONTH_MODE) { + if (startDay < -5 || startDay > 5) { + throw new IllegalArgumentException( + "Illegal start day of week in month " + startDay); + } + } else if (startDay < 1 || startDay > staticMonthLength[startMonth]) { + throw new IllegalArgumentException( + "Illegal start day " + startDay); + } + } + } + + /** + * Decode the end rule and validate the parameters. This method is exactly + * analogous to decodeStartRule(). + * @see decodeStartRule + */ + private void decodeEndRule() { + useDaylight = (startDay != 0) && (endDay != 0); + if (endDay != 0) { + if (endMonth < Calendar.JANUARY || endMonth > Calendar.DECEMBER) { + throw new IllegalArgumentException( + "Illegal end month " + endMonth); + } + if (endTime < 0 || endTime >= millisPerDay) { + throw new IllegalArgumentException( + "Illegal end time " + endTime); + } + if (endDayOfWeek == 0) { + endMode = DOM_MODE; + } else { + if (endDayOfWeek > 0) { + endMode = DOW_IN_MONTH_MODE; + } else { + endDayOfWeek = -endDayOfWeek; + if (endDay > 0) { + endMode = DOW_GE_DOM_MODE; + } else { + endDay = -endDay; + endMode = DOW_LE_DOM_MODE; + } + } + if (endDayOfWeek > Calendar.SATURDAY) { + throw new IllegalArgumentException( + "Illegal end day of week " + endDayOfWeek); + } + } + if (endMode == DOW_IN_MONTH_MODE) { + if (endDay < -5 || endDay > 5) { + throw new IllegalArgumentException( + "Illegal end day of week in month " + endDay); + } + } else if (endDay < 1 || endDay > staticMonthLength[endMonth]) { + throw new IllegalArgumentException( + "Illegal end day " + endDay); + } + } + } + + /** + * Make rules compatible to 1.1 FCS code. Since 1.1 FCS code only understands + * day-of-week-in-month rules, we must modify other modes of rules to their + * approximate equivalent in 1.1 FCS terms. This method is used when streaming + * out objects of this class. After it is called, the rules will be modified, + * with a possible loss of information. startMode and endMode will NOT be + * altered, even though semantically they should be set to DOW_IN_MONTH_MODE, + * since the rule modification is only intended to be temporary. + */ + private void makeRulesCompatible() + { + switch (startMode) + { + case DOM_MODE: + startDay = 1 + (startDay / 7); + startDayOfWeek = Calendar.SUNDAY; + break; + case DOW_GE_DOM_MODE: + // A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE + // that is, Sun>=1 == firstSun. + if (startDay != 1) + startDay = 1 + (startDay / 7); + break; + case DOW_LE_DOM_MODE: + if (startDay >= 30) + startDay = -1; + else + startDay = 1 + (startDay / 7); + break; + } + + switch (endMode) + { + case DOM_MODE: + endDay = 1 + (endDay / 7); + endDayOfWeek = Calendar.SUNDAY; + break; + case DOW_GE_DOM_MODE: + // A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE + // that is, Sun>=1 == firstSun. + if (endDay != 1) + endDay = 1 + (endDay / 7); + break; + case DOW_LE_DOM_MODE: + if (endDay >= 30) + endDay = -1; + else + endDay = 1 + (endDay / 7); + break; + } + + /* Adjust the start and end times to wall time. This works perfectly + * well unless it pushes into the next or previous day. If that + * happens, we attempt to adjust the day rule somewhat crudely. The day + * rules have been forced into DOW_IN_MONTH mode already, so we change + * the day of week to move forward or back by a day. It's possible to + * make a more refined adjustment of the original rules first, but in + * most cases this extra effort will go to waste once we adjust the day + * rules anyway. */ + switch (startTimeMode) { + case UTC_TIME: + startTime += rawOffset; + break; + } + while (startTime < 0) { + startTime += millisPerDay; + startDayOfWeek = 1 + ((startDayOfWeek+5) % 7); // Back 1 day + } + while (startTime >= millisPerDay) { + startTime -= millisPerDay; + startDayOfWeek = 1 + (startDayOfWeek % 7); // Forward 1 day + } + + switch (endTimeMode) { + case UTC_TIME: + endTime += rawOffset + dstSavings; + break; + case STANDARD_TIME: + endTime += dstSavings; + } + while (endTime < 0) { + endTime += millisPerDay; + endDayOfWeek = 1 + ((endDayOfWeek+5) % 7); // Back 1 day + } + while (endTime >= millisPerDay) { + endTime -= millisPerDay; + endDayOfWeek = 1 + (endDayOfWeek % 7); // Forward 1 day + } + } + + /** + * Pack the start and end rules into an array of bytes. Only pack + * data which is not preserved by makeRulesCompatible. + */ + private byte[] packRules() + { + byte[] rules = new byte[6]; + rules[0] = (byte)startDay; + rules[1] = (byte)startDayOfWeek; + rules[2] = (byte)endDay; + rules[3] = (byte)endDayOfWeek; + + // As of serial version 2, include time modes + rules[4] = (byte)startTimeMode; + rules[5] = (byte)endTimeMode; + + return rules; + } + + /** + * Given an array of bytes produced by packRules, interpret them + * as the start and end rules. + */ + private void unpackRules(byte[] rules) + { + startDay = rules[0]; + startDayOfWeek = rules[1]; + endDay = rules[2]; + endDayOfWeek = rules[3]; + + // As of serial version 2, include time modes + if (rules.length >= 6) { + startTimeMode = rules[4]; + endTimeMode = rules[5]; + } + } + + /** + * Pack the start and end times into an array of bytes. This is required + * as of serial version 2. + */ + private int[] packTimes() { + int[] times = new int[2]; + times[0] = startTime; + times[1] = endTime; + return times; + } + + /** + * Unpack the start and end times from an array of bytes. This is required + * as of serial version 2. + */ + private void unpackTimes(int[] times) { + startTime = times[0]; + endTime = times[1]; + } + + /** + * Save the state of this object to a stream (i.e., serialize it). + * + * @serialData We write out two formats, a JDK 1.1 compatible format, using + * DOW_IN_MONTH_MODE rules, in the required section, followed + * by the full rules, in packed format, in the optional section. The + * optional section will be ignored by JDK 1.1 code upon stream in. + *

Contents of the optional section: The length of a byte array is + * emitted (int); this is 4 as of this release. The byte array of the given + * length is emitted. The contents of the byte array are the true values of + * the fields startDay, startDayOfWeek, + * endDay, and endDayOfWeek. The values of these + * fields in the required section are approximate values suited to the rule + * mode DOW_IN_MONTH_MODE, which is the only mode recognized by + * JDK 1.1. + */ + private void writeObject(ObjectOutputStream stream) + throws IOException + { + // Construct a binary rule + byte[] rules = packRules(); + int[] times = packTimes(); + + // Convert to 1.1 FCS rules. This step may cause us to lose information. + makeRulesCompatible(); + + // Write out the 1.1 FCS rules + stream.defaultWriteObject(); + + // Write out the binary rules in the optional data area of the stream. + stream.writeInt(rules.length); + stream.write(rules); + stream.writeObject(times); + + // Recover the original rules. This recovers the information lost + // by makeRulesCompatible. + unpackRules(rules); + unpackTimes(times); + } + + /** + * Reconstitute this object from a stream (i.e., deserialize it). + * + * We handle both JDK 1.1 + * binary formats and full formats with a packed byte array. + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + + if (serialVersionOnStream < 1) + { + // Fix a bug in the 1.1 SimpleTimeZone code -- namely, + // startDayOfWeek and endDayOfWeek were usually uninitialized. We can't do + // too much, so we assume SUNDAY, which actually works most of the time. + if (startDayOfWeek == 0) startDayOfWeek = Calendar.SUNDAY; + if (endDayOfWeek == 0) endDayOfWeek = Calendar.SUNDAY; + + // The variables dstSavings, startMode, and endMode are post-1.1, so they + // won't be present if we're reading from a 1.1 stream. Fix them up. + startMode = endMode = DOW_IN_MONTH_MODE; + dstSavings = millisPerHour; + } + else + { + // For 1.1.4, in addition to the 3 new instance variables, we also + // store the actual rules (which have not be made compatible with 1.1) + // in the optional area. Read them in here and parse them. + int length = stream.readInt(); + byte[] rules = new byte[length]; + stream.readFully(rules); + unpackRules(rules); + } + + if (serialVersionOnStream >= 2) { + int[] times = (int[]) stream.readObject(); + unpackTimes(times); + } + + serialVersionOnStream = currentSerialVersion; + } +} + +//eof diff --git a/icu4j/src/com/ibm/icu/util/SimpleTimeZoneAdapter.java b/icu4j/src/com/ibm/icu/util/SimpleTimeZoneAdapter.java new file mode 100755 index 0000000000..0f6dc0ee02 --- /dev/null +++ b/icu4j/src/com/ibm/icu/util/SimpleTimeZoneAdapter.java @@ -0,0 +1,157 @@ +/* Copyright (c) 2000 International Business Machines Corporation and + * others. All Rights Reserved. + * + * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/Attic/SimpleTimeZoneAdapter.java,v $ + * $Date: 2000/05/12 23:20:11 $ + * $Revision: 1.1 $ + */ +package com.ibm.util; +import java.util.Date; + +/** + * SimpleTimeZoneAdapter wraps a + * com.ibm.util.SimpleTimeZone and inherits from java.util.TimeZone. + * Without this class, we would need to 'port' java.util.Date to + * com.ibm.util as well, so that Date could interoperate properly with + * the com.ibm.util TimeZone and Calendar classes. With this class, + * we can (mostly) use java.util.Date together with com.ibm.util + * classes. + * + *

This solution is imperfect because of the faulty design of + * java.util.TimeZone. Specifically, TZ contains a package private + * method, getOffset(), that should really be public. Because it is + * package private, it cannot be overridden from where we are, and we + * cannot properly delegate its operation to our contained + * com.ibm.util.STZ object. + * + *

For the moment we live with this problem. It appear not to + * cause too much trouble since most real computations happen using + * the com.ibm.util classes. However, if this becomes a problem in + * the future, we will have to stop using this adapter, and 'port' + * java.util.Date into com.ibm.util. + * + * @see com.ibm.util.TimeZone#setDefault + * @author Alan Liu + */ +public class SimpleTimeZoneAdapter extends java.util.TimeZone { + + /** + * The contained com.ibm.util.SimpleTimeZone object. + * We delegate all methods to this object. + */ + private SimpleTimeZone zone; + + public SimpleTimeZoneAdapter(SimpleTimeZone zone) { + this.zone = zone; + } + + /** + * Override TimeZone + */ + public String getID() { + return zone.getID(); + } + + /** + * Override TimeZone + */ + public void setID(String ID) { + zone.setID(ID); + } + + /** + * Override TimeZone + */ + public boolean hasSameRules(java.util.TimeZone other) { + return other instanceof SimpleTimeZoneAdapter && + zone.hasSameRules(((SimpleTimeZoneAdapter)other).zone); + } + + /** + * Override TimeZone + */ + public int getOffset(int era, int year, int month, int day, int dayOfWeek, + int millis) { + return zone.getOffset(era, year, month, day, dayOfWeek, millis); + } + + // This doesn't work! Because this is a package-private method, + // it cannot override the corresponding method in java.util.TZ. + // This reflects a fundamental bug in the architecture of + // java.util.TZ. If not for this, this adapter class would + // work flawlessly. - liu +//! /** +//! * Override TimeZone +//! */ +//! int getOffset(int era, int year, int month, int day, int dayOfWeek, +//! int millis, int monthLength, int prevMonthLength) { +//! return zone.getOffset(era, year, month, day, dayOfWeek, +//! millis, monthLength, prevMonthLength); +//! } + + /** + * Overrides TimeZone + * Gets the GMT offset for this time zone. + */ + public int getRawOffset() { + return zone.getRawOffset(); + } + + /** + * Overrides TimeZone + */ + public void setRawOffset(int offsetMillis) { + zone.setRawOffset(offsetMillis); + } + + /** + * Overrides TimeZone + */ + public boolean useDaylightTime() { + return zone.useDaylightTime(); + } + + /** + * Overrides TimeZone + */ + public boolean inDaylightTime(Date date) { + return zone.inDaylightTime(date); + } + + /** + * Overrides Cloneable + */ + public Object clone() { + return new SimpleTimeZoneAdapter((SimpleTimeZone)zone.clone()); + } + + /** + * Override hashCode. + */ + public synchronized int hashCode() { + return zone.hashCode(); + } + + /** + * Compares the equality of two SimpleTimeZone objects. + * + * @param obj The SimpleTimeZone object to be compared with. + * @return True if the given obj is the same as this SimpleTimeZone + * object; false otherwise. + */ + public boolean equals(Object obj) { + if (obj instanceof SimpleTimeZoneAdapter) { + obj = ((SimpleTimeZoneAdapter)obj).zone; + } + return zone.equals(obj); + } + + /** + * Return a string representation of this time zone. + * @return a string representation of this time zone. + */ + public String toString() { + // Should probably show our class name here...fix later. + return zone.toString(); + } +} diff --git a/icu4j/src/com/ibm/icu/util/TimeZone.java b/icu4j/src/com/ibm/icu/util/TimeZone.java new file mode 100755 index 0000000000..98810f3962 --- /dev/null +++ b/icu4j/src/com/ibm/icu/util/TimeZone.java @@ -0,0 +1,2036 @@ +/* + * @(#)TimeZone.java 1.51 00/01/19 + * + * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved. + * + * This software is the proprietary information of Sun Microsystems, Inc. + * Use is subject to license terms. + * + */ + +/* + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - All Rights Reserved + * + * The original version of this source code and documentation is copyrighted + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These + * materials are provided under terms of a License Agreement between Taligent + * and Sun. This technology is protected by multiple US and International + * patents. This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + */ + +package com.ibm.util; +import java.io.Serializable; +import java.lang.ref.SoftReference; +import java.security.AccessController; +import java.security.PrivilegedAction; +import com.ibm.text.SimpleDateFormat; +import com.ibm.text.NumberFormat; +import java.text.ParsePosition; +import sun.security.action.GetPropertyAction; +import java.util.Date; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +/** + * TimeZone represents a time zone offset, and also figures out daylight + * savings. + * + *

+ * Typically, you get a TimeZone using getDefault + * which creates a TimeZone based on the time zone where the program + * is running. For example, for a program running in Japan, getDefault + * creates a TimeZone object based on Japanese Standard Time. + * + *

+ * You can also get a TimeZone using getTimeZone + * along with a time zone ID. For instance, the time zone ID for the + * U.S. Pacific Time zone is "America/Los_Angeles". So, you can get a + * U.S. Pacific Time TimeZone object with: + *

+ *
+ * TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
+ * 
+ *
+ * You can use getAvailableIDs method to iterate through + * all the supported time zone IDs. You can then choose a + * supported ID to get a TimeZone. + * If the time zone you want is not represented by one of the + * supported IDs, then you can create a custom time zone ID with + * the following syntax: + * + *
+ *
+ * GMT[+|-]hh[[:]mm]
+ * 
+ *
+ * + * For example, you might specify GMT+14:00 as a custom + * time zone ID. The TimeZone that is returned + * when you specify a custom time zone ID does not include + * daylight savings time. + *

+ * For compatibility with JDK 1.1.x, some other three-letter time zone IDs + * (such as "PST", "CTT", "AST") are also supported. However, their + * use is deprecated because the same abbreviation is often used + * for multiple time zones (for example, "CST" could be U.S. "Central Standard + * Time" and "China Standard Time"), and the Java platform can then only + * recognize one of them. + * + * + * @see Calendar + * @see GregorianCalendar + * @see SimpleTimeZone + * @version 1.51 01/19/00 + * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu + * @since JDK1.1 + */ +abstract public class TimeZone implements Serializable, Cloneable { + /** + * Sole constructor. (For invocation by subclass constructors, typically + * implicit.) + */ + public TimeZone() { + } + + /** + * A style specifier for getDisplayName() indicating + * a short name, such as "PST." + * @see #LONG + * @since 1.2 + */ + public static final int SHORT = 0; + + /** + * A style specifier for getDisplayName() indicating + * a long name, such as "Pacific Standard Time." + * @see #SHORT + * @since 1.2 + */ + public static final int LONG = 1; + + // Constants used internally; unit is milliseconds + private static final int ONE_MINUTE = 60*1000; + private static final int ONE_HOUR = 60*ONE_MINUTE; + private static final int ONE_DAY = 24*ONE_HOUR; + + /** + * Cache to hold the SimpleDateFormat objects for a Locale. + */ + private static Hashtable cachedLocaleData = new Hashtable(3); + + // Proclaim serialization compatibility with JDK 1.1 + static final long serialVersionUID = 3581463369166924961L; + + /** + * Gets the time zone offset, for current date, modified in case of + * daylight savings. This is the offset to add *to* UTC to get local time. + * @param era the era of the given date. + * @param year the year in the given date. + * @param month the month in the given date. + * Month is 0-based. e.g., 0 for January. + * @param day the day-in-month of the given date. + * @param dayOfWeek the day-of-week of the given date. + * @param milliseconds the millis in day in standard local time. + * @return the offset to add *to* GMT to get local time. + */ + abstract public int getOffset(int era, int year, int month, int day, + int dayOfWeek, int milliseconds); + + /** + * Gets the time zone offset, for current date, modified in case of + * daylight savings. This is the offset to add *to* UTC to get local time. + * @param era the era of the given date. + * @param year the year in the given date. + * @param month the month in the given date. + * Month is 0-based. e.g., 0 for January. + * @param day the day-in-month of the given date. + * @param dayOfWeek the day-of-week of the given date. + * @param milliseconds the millis in day in standard local time. + * @param monthLength the length of the given month in days. + * @param prevMonthLength the length of the previous month in days. + * @return the offset to add *to* GMT to get local time. + */ + int getOffset(int era, int year, int month, int day, + int dayOfWeek, int milliseconds, int monthLength, int prevMonthLength) { + // Default implementation which ignores the monthLength. + // SimpleTimeZone overrides this and actually uses monthLength. + return getOffset(era, year, month, day, dayOfWeek, milliseconds); + } + + + /** + * Sets the base time zone offset to GMT. + * This is the offset to add *to* UTC to get local time. + * @param offsetMillis the given base time zone offset to GMT. + */ + abstract public void setRawOffset(int offsetMillis); + + /** + * Gets unmodified offset, NOT modified in case of daylight savings. + * This is the offset to add *to* UTC to get local time. + * @return the unmodified offset to add *to* UTC to get local time. + */ + abstract public int getRawOffset(); + + /** + * Gets the ID of this time zone. + * @return the ID of this time zone. + */ + public String getID() + { + return ID; + } + + /** + * Sets the time zone ID. This does not change any other data in + * the time zone object. + * @param ID the new time zone ID. + */ + public void setID(String ID) + { + if (ID == null) { + throw new NullPointerException(); + } + this.ID = ID; + } + + /** + * Returns a name of this time zone suitable for presentation to the user + * in the default locale. + * This method returns the long name, not including daylight savings. + * If the display name is not available for the locale, + * then this method returns a string in the format + * GMT[+-]hh:mm. + * @return the human-readable name of this time zone in the default locale. + * @since 1.2 + */ + public final String getDisplayName() { + return getDisplayName(false, LONG, Locale.getDefault()); + } + + /** + * Returns a name of this time zone suitable for presentation to the user + * in the specified locale. + * This method returns the long name, not including daylight savings. + * If the display name is not available for the locale, + * then this method returns a string in the format + * GMT[+-]hh:mm. + * @param locale the locale in which to supply the display name. + * @return the human-readable name of this time zone in the given locale + * or in the default locale if the given locale is not recognized. + * @since 1.2 + */ + public final String getDisplayName(Locale locale) { + return getDisplayName(false, LONG, locale); + } + + /** + * Returns a name of this time zone suitable for presentation to the user + * in the default locale. + * If the display name is not available for the locale, + * then this method returns a string in the format + * GMT[+-]hh:mm. + * @param daylight if true, return the daylight savings name. + * @param style either LONG or SHORT + * @return the human-readable name of this time zone in the default locale. + * @since 1.2 + */ + public final String getDisplayName(boolean daylight, int style) { + return getDisplayName(daylight, style, Locale.getDefault()); + } + + /** + * Returns a name of this time zone suitable for presentation to the user + * in the specified locale. + * If the display name is not available for the locale, + * then this method returns a string in the format + * GMT[+-]hh:mm. + * @param daylight if true, return the daylight savings name. + * @param style either LONG or SHORT + * @param locale the locale in which to supply the display name. + * @return the human-readable name of this time zone in the given locale + * or in the default locale if the given locale is not recognized. + * @exception IllegalArgumentException style is invalid. + * @since 1.2 + */ + public String getDisplayName(boolean daylight, int style, Locale locale) { + /* NOTES: + * (1) We use SimpleDateFormat for simplicity; we could do this + * more efficiently but it would duplicate the SimpleDateFormat code + * here, which is undesirable. + * (2) Attempts to move the code from SimpleDateFormat to here also run + * aground because this requires SimpleDateFormat to keep a Locale + * object around, which it currently doesn't; to synthesize such a + * locale upon resurrection; and to somehow handle the special case of + * construction from a DateFormatSymbols object. + */ + if (style != SHORT && style != LONG) { + throw new IllegalArgumentException("Illegal style: " + style); + } + // We keep a cache, indexed by locale. The cache contains a + // SimpleDateFormat object, which we create on demand. + SoftReference data = (SoftReference)cachedLocaleData.get(locale); + SimpleDateFormat format; + if (data == null || + (format = (SimpleDateFormat)data.get()) == null) { + format = new SimpleDateFormat(null, locale); + cachedLocaleData.put(locale, new SoftReference(format)); + } + // Create a new SimpleTimeZone as a stand-in for this zone; the stand-in + // will have no DST, or DST during January, but the same ID and offset, + // and hence the same display name. We don't cache these because + // they're small and cheap to create. + SimpleTimeZone tz; + if (daylight && useDaylightTime()) { + int savings = ONE_HOUR; + try { + savings = ((SimpleTimeZone) this).getDSTSavings(); + } catch (ClassCastException e) {} + tz = new SimpleTimeZone(getRawOffset(), getID(), + Calendar.JANUARY, 1, 0, 0, + Calendar.FEBRUARY, 1, 0, 0, + savings); + } else { + tz = new SimpleTimeZone(getRawOffset(), getID()); + } + format.applyPattern(style == LONG ? "zzzz" : "z"); + format.setTimeZone(tz); + // Format a date in January. We use the value 10*ONE_DAY == Jan 11 1970 + // 0:00 GMT. + return format.format(new Date(864000000L)); + } + + /** + * Queries if this time zone uses daylight savings time. + * @return true if this time zone uses daylight savings time, + * false, otherwise. + */ + abstract public boolean useDaylightTime(); + + /** + * Queries if the given date is in daylight savings time in + * this time zone. + * @param date the given Date. + * @return true if the given date is in daylight savings time, + * false, otherwise. + */ + abstract public boolean inDaylightTime(Date date); + + /** + * Gets the TimeZone for the given ID. + * + * @param ID the ID for a TimeZone, either an abbreviation + * such as "PST", a full name such as "America/Los_Angeles", or a custom + * ID such as "GMT-8:00". Note that the support of abbreviations is + * for JDK 1.1.x compatibility only and full names should be used. + * + * @return the specified TimeZone, or the GMT zone if the given ID + * cannot be understood. + */ + public static synchronized TimeZone getTimeZone(String ID) { + /* We first try to lookup the zone ID in our hashtable. If this fails, + * we try to parse it as a custom string GMT[+-]hh:mm. This allows us + * to recognize zones in user.timezone that otherwise cannot be + * identified. We do the recognition here, rather than in getDefault(), + * so that the default zone is always the result of calling + * getTimeZone() with the property user.timezone. + * + * If all else fails, we return GMT, which is probably not what the user + * wants, but at least is a functioning TimeZone object. */ + TimeZone zone = TimeZoneData.get(ID); + if (zone == null) zone = parseCustomTimeZone(ID); + if (zone == null) zone = (TimeZone)GMT.clone(); + return zone; + } + + /** + * Gets the available IDs according to the given time zone offset. + * @param rawOffset the given time zone GMT offset. + * @return an array of IDs, where the time zone for that ID has + * the specified GMT offset. For example, "America/Phoenix" and "America/Denver" + * both have GMT-07:00, but differ in daylight savings behavior. + */ + public static synchronized String[] getAvailableIDs(int rawOffset) { + String[] result; + Vector matched = new Vector(); + + /* The array TimeZoneData.zones is no longer sorted by raw offset. + * Now scanning through all zone data to match offset. + */ + for (int i = 0; i < TimeZoneData.zones.length; ++i) { + if (TimeZoneData.zones[i].getRawOffset() == rawOffset) + matched.add(TimeZoneData.zones[i].getID()); + } + result = new String[matched.size()]; + matched.toArray(result); + + return result; + } + + /** + * Gets all the available IDs supported. + * @return an array of IDs. + */ + public static synchronized String[] getAvailableIDs() { + String[] resultArray = new String[TimeZoneData.zones.length]; + int count = 0; + for (int i = 0; i < TimeZoneData.zones.length; ++i) + resultArray[count++] = TimeZoneData.zones[i].getID(); + + // copy into array of the right size and return + String[] finalResult = new String[count]; + System.arraycopy(resultArray, 0, finalResult, 0, count); + + return finalResult; + } + + /** + * Gets the platform defined TimeZone ID. + **/ + private static native String getSystemTimeZoneID(String javaHome, + String region); + + /** + * Gets the default TimeZone for this host. + * The source of the default TimeZone + * may vary with implementation. + * @return a default TimeZone. + */ + public static synchronized TimeZone getDefault() { + if (defaultZone == null) { + // get the time zone ID from the system properties + String zoneID = (String) AccessController.doPrivileged( + new GetPropertyAction("user.timezone")); + + // if the time zone ID is not set (yet), perform the + // platform to Java time zone ID mapping. + if (zoneID == null || zoneID.equals("")) { + //String region = (String) AccessController.doPrivileged( + // new GetPropertyAction("user.region")); + //String javaHome = (String) AccessController.doPrivileged( + // new GetPropertyAction("java.home")); + //zoneID = getSystemTimeZoneID(javaHome, region); + + // [icu4j We get the default zone by querying java.util.TimeZone, + // and then attempting to map the ID. - liu ] + java.util.TimeZone _default = java.util.TimeZone.getDefault(); + if (false) System.out.println("java.util.TZ.default " + _default); + zoneID = _default.getID(); + defaultZone = TimeZoneData.get(zoneID); + if (defaultZone == null) { + // [icu4j This means that the zone returned by the JDK does + // not exist in our table. We will, for the moment, map to + // a std zone that has the same raw offset. In the future + // we might find it worthwhile to extract the rules from the + // system default zone, but this is too much trouble for + // now. It will be easier to extend our mapping table to + // match the JDKs we want to support. - liu ] + try { + java.util.SimpleTimeZone s = (java.util.SimpleTimeZone) _default; + defaultZone = new SimpleTimeZone(s.getRawOffset(), s.getID()); + } catch (ClassCastException e) {} + } else { + if (zoneID == null) { + zoneID = GMT_ID; + } + final String id = zoneID; + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + System.setProperty("user.timezone", id); + return null; + } + }); + } + } + if (defaultZone == null) { + defaultZone = getTimeZone(zoneID); + } + if (false) System.out.println("com.ibm.util.TZ.default " + defaultZone); + } + return (TimeZone)defaultZone.clone(); + } + + /** + * Sets the TimeZone that is + * returned by the getDefault method. If zone + * is null, reset the default to the value it had originally when the + * VM first started. + * @param zone the new default time zone + */ + public static synchronized void setDefault(TimeZone zone) + { + defaultZone = zone; + // [icu4j Keep java.util.TimeZone default in sync so java.util.Date + // can interoperate with com.ibm.util classes. This solution + // is _imperfect_; see SimpleTimeZoneAdapter. - liu] + try { + java.util.TimeZone.setDefault( + new SimpleTimeZoneAdapter((SimpleTimeZone) zone)); + } catch (ClassCastException e) {} + } + + /** + * Returns true if this zone has the same rule and offset as another zone. + * That is, if this zone differs only in ID, if at all. Returns false + * if the other zone is null. + * @param other the TimeZone object to be compared with + * @return true if the other zone is not null and is the same as this one, + * with the possible exception of the ID + * @since 1.2 + */ + public boolean hasSameRules(TimeZone other) { + return other != null && getRawOffset() == other.getRawOffset() && + useDaylightTime() == other.useDaylightTime(); + } + + /** + * Overrides Cloneable + */ + public Object clone() + { + try { + TimeZone other = (TimeZone) super.clone(); + other.ID = ID; + return other; + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } + + // =======================privates=============================== + + /** + * The string identifier of this TimeZone. This is a + * programmatic identifier used internally to look up TimeZone + * objects from the system table and also to map them to their localized + * display names. ID values are unique in the system + * table but may not be for dynamically created zones. + * @serial + */ + private String ID; + private static TimeZone defaultZone = null; + + static final String GMT_ID = "GMT"; + private static final int GMT_ID_LENGTH = 3; + private static final String CUSTOM_ID = "Custom"; + + private static NumberFormat numberFormat = null; + + private static final TimeZone GMT = new SimpleTimeZone(0, GMT_ID); + + /** + * Parse a custom time zone identifier and return a corresponding zone. + * @param id a string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or + * GMT[+-]hh. + * @return a newly created SimpleTimeZone with the given offset and + * no daylight savings time, or null if the id cannot be parsed. + */ + private static final SimpleTimeZone parseCustomTimeZone(String id) { + if (id.length() > GMT_ID_LENGTH && + id.regionMatches(true, 0, GMT_ID, 0, GMT_ID_LENGTH)) { + ParsePosition pos = new ParsePosition(GMT_ID_LENGTH); + boolean negative = false; + int offset; + + if (id.charAt(pos.getIndex()) == '-') + negative = true; + else if (id.charAt(pos.getIndex()) != '+') + return null; + pos.setIndex(pos.getIndex() + 1); + + // Create NumberFormat if necessary + synchronized (TimeZoneData.class) { + if (numberFormat == null) { + numberFormat = NumberFormat.getInstance(); + numberFormat.setParseIntegerOnly(true); + } + } + + synchronized (numberFormat) { + // Look for either hh:mm, hhmm, or hh + int start = pos.getIndex(); + Number n = numberFormat.parse(id, pos); + if (n == null) return null; + offset = n.intValue(); + + if (pos.getIndex() < id.length() && + id.charAt(pos.getIndex()) == ':') { + // hh:mm + offset *= 60; + pos.setIndex(pos.getIndex() + 1); + n = numberFormat.parse(id, pos); + if (n == null) return null; + offset += n.intValue(); + } + else { + // hhmm or hh + + // Be strict about interpreting something as hh; it must be + // an offset < 30, and it must be one or two digits. Thus + // 0010 is interpreted as 00:10, but 10 is interpreted as + // 10:00. + if (offset < 30 && (pos.getIndex() - start) <= 2) + offset *= 60; // hh, from 00 to 29; 30 is 00:30 + else + offset = offset % 100 + offset / 100 * 60; // hhmm + } + + if (negative) offset = -offset; + return new SimpleTimeZone(offset * 60000, CUSTOM_ID); + } + } + + return null; + } + + // Internal Implementation Notes [LIU] + // + // TimeZone data is stored in two parts. The first is an encoding of the + // rules for each TimeZone. A TimeZone rule includes the offset of a zone + // in milliseconds from GMT, the starting month and day for daylight savings + // time, if there is any, and the ending month and day for daylight savings + // time. The starting and ending days are specified in terms of the n-th + // day of the week, for instance, the first Sunday or the last ("-1"-th) + // Sunday of the month. The rules are stored as statically-constructed + // SimpleTimeZone objects in the TimeZone class. + // + // Each rule has a unique internal identifier string which is used to + // specify it. This identifier string is arbitrary, and is not to be shown + // to the user -- it is for programmatic use only. In order to instantiate + // a TimeZone object, you pass its identifier string to + // TimeZone.getTimeZone(). (This identifier is also used to index the + // localized string data.) + // + // The second part of the data consists of localized string names used by + // DateFormat to describe various TimeZones. A TimeZone may have up to four + // names: The abbreviated and long name for standard time in that zone, and + // the abbreviated and long name for daylight savings time in that zone. + // The data also includes a representative city. For example, [ "PST", + // "Pacific Standard Time", "PDT", "Pacific Daylight Time", "Los Angeles" ] + // might be one such set of string names in the en_US locale. These strings + // are intended to be shown to the user. The string data is indexed in the + // system by a pair (String id, Locale locale). The id is the unique string + // identifier for the rule for the given TimeZone (as passed to + // TimeZone.getTimeZone()). String names are stored as localized resource + // data of the class java.text.resources.DateFormatZoneData??? where ??? is + // the Locale specifier (e.g., DateFormatZoneData_en_US). This data is a + // two-dimensional array of strings with N rows and 6 columns. The columns + // are id, short standard name, long standard name, short daylight name, + // long daylight name, representative city name. + // + // The mapping between rules (SimpleTimeZone objects) and localized string + // names (DateFormatZoneData objects) is one-to-many. That is, there will + // sometimes be more than one localized string name sets associated with + // each rule. + // + // Each locale can potentially have localized name data for all time zones. + // Since we support approximately 90 time zones and approximately 50 + // locales, there can be over 4500 sets of localized names. In practice, + // only a fraction of these names are provided. If a time zone needs to be + // displayed to the user in a given locale, and there is no string data in + // that locale for that time zone, then the default representation will be + // shown. This is a string of the form GMT+HHMM or GMT-HHMM, where HHMM + // represents the offset in hours and minutes with respect to GMT. This + // format is used because it is recognized in all locales. In order to make + // this mechanism to work, the root resource data (in the class + // DateFormatZoneData) is left empty. + // + // The current default TimeZone is determined via the system property + // user.timezone. This is set by the platform-dependent native code to + // a three-letter abbreviation. We interpret these into our own internal + // IDs using a lookup table. +} + +/** + * Encapsulates data for international timezones. This package-private class is for + * internal use only by TimeZone. It encapsulates the list of recognized international + * timezones. By implementing this as a separate class, the loading and initialization + * cost for this array is delayed until a TimeZone object is actually created from its ID. + * This class contains only static variables and static methods; it cannot be instantiated. + */ +class TimeZoneData +{ + static final TimeZone get(String ID) { + Object o = lookup.get(ID); + return o == null ? null : (TimeZone)((TimeZone)o).clone(); // [sic] + } + + // ---------------- BEGIN GENERATED DATA ---------------- + private static final int ONE_HOUR = 60*60*1000; + + static SimpleTimeZone zones[] = { + // The following data is current as of 1998. + // Total Unix zones: 343 + // Total Java zones: 289 + // Not all Unix zones become Java zones due to duplication and overlap. + //---------------------------------------------------------- + new SimpleTimeZone(-11*ONE_HOUR, "Pacific/Niue" /*NUT*/), + // Pacific/Niue Niue(NU) -11:00 - NUT + //---------------------------------------------------------- + new SimpleTimeZone(-11*ONE_HOUR, "Pacific/Apia" /*WST*/), + // Pacific/Apia W Samoa(WS) -11:00 - WST # W Samoa Time + new SimpleTimeZone(-11*ONE_HOUR, "MIT" /*alias for Pacific/Apia*/), + //---------------------------------------------------------- + new SimpleTimeZone(-11*ONE_HOUR, "Pacific/Pago_Pago" /*SST*/), + // Pacific/Pago_Pago American Samoa(US) -11:00 - SST # S=Samoa + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "Pacific/Tahiti" /*TAHT*/), + // Pacific/Tahiti French Polynesia(PF) -10:00 - TAHT # Tahiti Time + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "Pacific/Fakaofo" /*TKT*/), + // Pacific/Fakaofo Tokelau Is(TK) -10:00 - TKT # Tokelau Time + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "Pacific/Honolulu" /*HST*/), + // Pacific/Honolulu Hawaii(US) -10:00 - HST + new SimpleTimeZone(-10*ONE_HOUR, "HST" /*alias for Pacific/Honolulu*/), + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "America/Adak" /*HA%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Adak Alaska(US) -10:00 US HA%sT + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "Pacific/Rarotonga"), + // Zone Pacific/Rarotonga Cook Is(CK) -10:00 Cook CK%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(-9.5*ONE_HOUR), "Pacific/Marquesas" /*MART*/), + // Pacific/Marquesas French Polynesia(PF) -9:30 - MART # Marquesas Time + //---------------------------------------------------------- + new SimpleTimeZone(-9*ONE_HOUR, "Pacific/Gambier" /*GAMT*/), + // Pacific/Gambier French Polynesia(PF) -9:00 - GAMT # Gambier Time + //---------------------------------------------------------- + new SimpleTimeZone(-9*ONE_HOUR, "America/Anchorage" /*AK%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Anchorage Alaska(US) -9:00 US AK%sT + new SimpleTimeZone(-9*ONE_HOUR, "AST" /*alias for America/Anchorage*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone((int)(-8.5*ONE_HOUR), "Pacific/Pitcairn" /*PNT*/), + // Pacific/Pitcairn Pitcairn(PN) -8:30 - PNT # Pitcairn Time + //---------------------------------------------------------- + new SimpleTimeZone(-8*ONE_HOUR, "America/Vancouver" /*P%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Vanc 1962 max - Oct lastSun 2:00 0 S + // Rule Vanc 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Vancouver British Columbia(CA) -8:00 Vanc P%sT + //---------------------------------------------------------- + new SimpleTimeZone(-8*ONE_HOUR, "America/Tijuana" /*P%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mexico 1996 max - Apr Sun>=1 2:00 1:00 D + // Rule Mexico 1996 max - Oct lastSun 2:00 0 S + // America/Tijuana Mexico(MX) -8:00 Mexico P%sT + //---------------------------------------------------------- + new SimpleTimeZone(-8*ONE_HOUR, "America/Los_Angeles" /*P%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Los_Angeles US Pacific time, represented by Los Angeles(US) -8:00 US P%sT + new SimpleTimeZone(-8*ONE_HOUR, "PST" /*alias for America/Los_Angeles*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Dawson_Creek" /*MST*/), + // America/Dawson_Creek British Columbia(CA) -7:00 - MST + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Phoenix" /*MST*/), + // America/Phoenix ?(US) -7:00 - MST + new SimpleTimeZone(-7*ONE_HOUR, "PNT" /*alias for America/Phoenix*/), + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Edmonton" /*M%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Edm 1972 max - Oct lastSun 2:00 0 S + // Rule Edm 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Edmonton Alberta(CA) -7:00 Edm M%sT + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Mazatlan" /*M%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mexico 1996 max - Apr Sun>=1 2:00 1:00 D + // Rule Mexico 1996 max - Oct lastSun 2:00 0 S + // America/Mazatlan Mexico(MX) -7:00 Mexico M%sT + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Denver" /*M%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Denver US Mountain time, represented by Denver(US) -7:00 US M%sT + new SimpleTimeZone(-7*ONE_HOUR, "MST" /*alias for America/Denver*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Belize" /*C%sT*/), + // America/Belize Belize(BZ) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Regina" /*CST*/), + // America/Regina Saskatchewan(CA) -6:00 - CST + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "Pacific/Galapagos" /*GALT*/), + // Pacific/Galapagos Ecuador(EC) -6:00 - GALT # Galapagos Time + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Guatemala" /*C%sT*/), + // America/Guatemala Guatemala(GT) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Tegucigalpa" /*C%sT*/), + // America/Tegucigalpa Honduras(HN) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/El_Salvador" /*C%sT*/), + // America/El_Salvador El Salvador(SV) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Costa_Rica" /*C%sT*/), + // America/Costa_Rica Costa Rica(CR) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg" /*C%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Winn 1966 max - Oct lastSun 2:00 0 S + // Rule Winn 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Winnipeg Manitoba(CA) -6:00 Winn C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "Pacific/Easter" /*EAS%sT*/, + Calendar.OCTOBER, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.MARCH, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Chile 1969 max - Oct Sun>=9 0:00 1:00 S + // Rule Chile 1970 max - Mar Sun>=9 0:00 0 - + // Pacific/Easter Chile(CL) -6:00 Chile EAS%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Mexico_City" /*C%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mexico 1996 max - Apr Sun>=1 2:00 1:00 D + // Rule Mexico 1996 max - Oct lastSun 2:00 0 S + // America/Mexico_City Mexico(MX) -6:00 Mexico C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Chicago" /*C%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Chicago US Central time, represented by Chicago(US) -6:00 US C%sT + new SimpleTimeZone(-6*ONE_HOUR, "CST" /*alias for America/Chicago*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Porto_Acre" /*AST*/), + // America/Porto_Acre Brazil(BR) -5:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Bogota" /*CO%sT*/), + // America/Bogota Colombia(CO) -5:00 - CO%sT # Colombia Time + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Guayaquil" /*ECT*/), + // America/Guayaquil Ecuador(EC) -5:00 - ECT # Ecuador Time + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Jamaica" /*EST*/), + // America/Jamaica Jamaica(JM) -5:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Cayman" /*EST*/), + // America/Cayman Cayman Is(KY) -5:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Managua" /*EST*/), + // America/Managua Nicaragua(NI) -5:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Panama" /*EST*/), + // America/Panama Panama(PA) -5:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Lima" /*PE%sT*/), + // America/Lima Peru(PE) -5:00 - PE%sT # Peru Time + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Indianapolis" /*EST*/), + // America/Indianapolis Indiana(US) -5:00 - EST + new SimpleTimeZone(-5*ONE_HOUR, "IET" /*alias for America/Indianapolis*/), + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Nassau" /*E%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Bahamas 1964 max - Oct lastSun 2:00 0 S + // Rule Bahamas 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Nassau Bahamas(BS) -5:00 Bahamas E%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Montreal" /*E%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mont 1957 max - Oct lastSun 2:00 0 S + // Rule Mont 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Montreal Ontario, Quebec(CA) -5:00 Mont E%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Havana", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule Cuba 1998 max - Mar lastSun 0:00s 1:00 D + // Rule Cuba 1998 max - Oct lastSun 0:00s 0 S + // Zone America/Havana Cuba(CU) -5:00 Cuba C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Port-au-Prince"), + // Zone America/Port-au-Prince Haiti(HT) -5:00 Haiti E%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Grand_Turk" /*E%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule TC 1979 max - Oct lastSun 0:00 0 S + // Rule TC 1987 max - Apr Sun>=1 0:00 1:00 D + // America/Grand_Turk Turks and Caicos(TC) -5:00 TC E%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/New_York" /*E%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/New_York US Eastern time, represented by New York(US) -5:00 US E%sT + new SimpleTimeZone(-5*ONE_HOUR, "EST" /*alias for America/New_York*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Antigua" /*AST*/), + // America/Antigua Antigua and Barbuda(AG) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Anguilla" /*AST*/), + // America/Anguilla Anguilla(AI) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Curacao" /*AST*/), + // America/Curacao Curacao(AN) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Aruba" /*AST*/), + // America/Aruba Aruba(AW) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Barbados" /*A%sT*/), + // America/Barbados Barbados(BB) -4:00 - A%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/La_Paz" /*BOT*/), + // America/La_Paz Bolivia(BO) -4:00 - BOT # Bolivia Time + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Manaus" /*WST*/), + // America/Manaus Brazil(BR) -4:00 - WST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Dominica" /*AST*/), + // America/Dominica Dominica(DM) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Santo_Domingo" /*AST*/), + // America/Santo_Domingo Dominican Republic(DO) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Grenada" /*AST*/), + // America/Grenada Grenada(GD) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Guadeloupe" /*AST*/), + // America/Guadeloupe Guadeloupe(GP) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Guyana" /*GYT*/), + // America/Guyana Guyana(GY) -4:00 - GYT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/St_Kitts" /*AST*/), + // America/St_Kitts St Kitts-Nevis(KN) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/St_Lucia" /*AST*/), + // America/St_Lucia St Lucia(LC) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Martinique" /*AST*/), + // America/Martinique Martinique(MQ) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Montserrat" /*AST*/), + // America/Montserrat Montserrat(MS) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Puerto_Rico" /*AST*/), + // America/Puerto_Rico Puerto Rico(PR) -4:00 - AST + new SimpleTimeZone(-4*ONE_HOUR, "PRT" /*alias for America/Puerto_Rico*/), + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Port_of_Spain" /*AST*/), + // America/Port_of_Spain Trinidad and Tobago(TT) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/St_Vincent" /*AST*/), + // America/St_Vincent St Vincent and the Grenadines(VC) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Tortola" /*AST*/), + // America/Tortola British Virgin Is(VG) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/St_Thomas" /*AST*/), + // America/St_Thomas Virgin Is(VI) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Caracas" /*VET*/), + // America/Caracas Venezuela(VE) -4:00 - VET + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "Antarctica/Palmer" /*CL%sT*/, + Calendar.OCTOBER, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.MARCH, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule ChileAQ 1969 max - Oct Sun>=9 0:00 1:00 S + // Rule ChileAQ 1970 max - Mar Sun>=9 0:00 0 - + // Antarctica/Palmer USA - year-round bases(AQ) -4:00 ChileAQ CL%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "Atlantic/Bermuda" /*A%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Bahamas 1964 max - Oct lastSun 2:00 0 S + // Rule Bahamas 1987 max - Apr Sun>=1 2:00 1:00 D + // Atlantic/Bermuda Bermuda(BM) -4:00 Bahamas A%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Cuiaba"), + // Zone America/Cuiaba Brazil(BR) -4:00 - WST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Halifax" /*A%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Halifax 1962 max - Oct lastSun 2:00 0 S + // Rule Halifax 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Halifax ?(CA) -4:00 Halifax A%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "Atlantic/Stanley" /*FK%sT*/, + Calendar.SEPTEMBER, 8, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.APRIL, 16, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Falk 1986 max - Apr Sun>=16 0:00 0 - + // Rule Falk 1996 max - Sep Sun>=8 0:00 1:00 S + // Atlantic/Stanley Falklands(FK) -4:00 Falk FK%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Thule" /*A%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Thule 1993 max - Apr Sun>=1 2:00 1:00 D + // Rule Thule 1993 max - Oct lastSun 2:00 0 S + // America/Thule ?(GL) -4:00 Thule A%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion", + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.FEBRUARY, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Para 1996 max - Oct Sun>=1 0:00 1:00 S + // Rule Para 1999 max - Feb lastSun 0:00 0 - + // Zone America/Asuncion Paraguay(PY) -4:00 Para PY%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Santiago" /*CL%sT*/, + Calendar.OCTOBER, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.MARCH, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Chile 1969 max - Oct Sun>=9 0:00 1:00 S + // Rule Chile 1970 max - Mar Sun>=9 0:00 0 - + // America/Santiago Chile(CL) -4:00 Chile CL%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(-3.5*ONE_HOUR), "America/St_Johns" /*N%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule StJohns 1960 max - Oct lastSun 2:00 0 S + // Rule StJohns 1989 max - Apr Sun>=1 2:00 1:00 D + // America/St_Johns Canada(CA) -3:30 StJohns N%sT + new SimpleTimeZone((int)(-3.5*ONE_HOUR), "CNT" /*alias for America/St_Johns*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Fortaleza" /*EST*/), + // America/Fortaleza Brazil(BR) -3:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Cayenne" /*GFT*/), + // America/Cayenne French Guiana(GF) -3:00 - GFT + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Paramaribo" /*SRT*/), + // America/Paramaribo Suriname(SR) -3:00 - SRT + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Montevideo" /*UY%sT*/), + // America/Montevideo Uruguay(UY) -3:00 - UY%sT + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Buenos_Aires" /*AR%sT*/), + // America/Buenos_Aires Argentina(AR) -3:00 - AR%sT + new SimpleTimeZone(-3*ONE_HOUR, "AGT" /*alias for America/Buenos_Aires*/), + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Godthab", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone America/Godthab ?(GL) -3:00 EU WG%sT + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Miquelon" /*PM%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mont 1957 max - Oct lastSun 2:00 0 S + // Rule Mont 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Miquelon St Pierre and Miquelon(PM) -3:00 Mont PM%sT # Pierre & Miquelon Time + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Sao_Paulo", + Calendar.OCTOBER, 8, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.FEBRUARY, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Brazil 1998 max - Oct Sun>=8 0:00 1:00 D + // Rule Brazil 1999 max - Feb Sun>=15 0:00 0 S + // Zone America/Sao_Paulo Brazil(BR) -3:00 Brazil E%sT + new SimpleTimeZone(-3*ONE_HOUR, "BET" /*alias for America/Sao_Paulo*/, + Calendar.OCTOBER, 8, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.FEBRUARY, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-2*ONE_HOUR, "America/Noronha" /*FST*/), + // America/Noronha Brazil(BR) -2:00 - FST + //---------------------------------------------------------- + new SimpleTimeZone(-2*ONE_HOUR, "Atlantic/South_Georgia" /*GST*/), + // Atlantic/South_Georgia South Georgia(GS) -2:00 - GST # South Georgia Time + //---------------------------------------------------------- + new SimpleTimeZone(-1*ONE_HOUR, "Atlantic/Jan_Mayen" /*EGT*/), + // Atlantic/Jan_Mayen ?(NO) -1:00 - EGT + //---------------------------------------------------------- + new SimpleTimeZone(-1*ONE_HOUR, "Atlantic/Cape_Verde" /*CVT*/), + // Atlantic/Cape_Verde Cape Verde(CV) -1:00 - CVT + //---------------------------------------------------------- + new SimpleTimeZone(-1*ONE_HOUR, "America/Scoresbysund", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone America/Scoresbysund ?(GL) -1:00 EU EG%sT + //---------------------------------------------------------- + new SimpleTimeZone(-1*ONE_HOUR, "Atlantic/Azores", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Atlantic/Azores Portugal(PT) -1:00 EU AZO%sT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Ouagadougou" /*GMT*/), + // Africa/Ouagadougou Burkina Faso(BF) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Abidjan" /*GMT*/), + // Africa/Abidjan Cote D'Ivoire(CI) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Accra" /*%s*/), + // Africa/Accra Ghana(GH) 0:00 - %s + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Banjul" /*GMT*/), + // Africa/Banjul Gambia(GM) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Conakry" /*GMT*/), + // Africa/Conakry Guinea(GN) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Bissau" /*GMT*/), + // Africa/Bissau Guinea-Bissau(GW) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Atlantic/Reykjavik" /*GMT*/), + // Atlantic/Reykjavik Iceland(IS) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Monrovia" /*GMT*/), + // Africa/Monrovia Liberia(LR) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Casablanca" /*WET*/), + // Africa/Casablanca Morocco(MA) 0:00 - WET + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Timbuktu" /*GMT*/), + // Africa/Timbuktu Mali(ML) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Nouakchott" /*GMT*/), + // Africa/Nouakchott Mauritania(MR) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Atlantic/St_Helena" /*GMT*/), + // Atlantic/St_Helena St Helena(SH) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Freetown" /*%s*/), + // Africa/Freetown Sierra Leone(SL) 0:00 - %s + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Dakar" /*GMT*/), + // Africa/Dakar Senegal(SN) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Sao_Tome" /*GMT*/), + // Africa/Sao_Tome Sao Tome and Principe(ST) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Lome" /*GMT*/), + // Africa/Lome Togo(TG) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "GMT" /*GMT*/), + // GMT -(-) 0:00 - GMT + new SimpleTimeZone(0*ONE_HOUR, "UTC" /*alias for GMT*/), + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Atlantic/Faeroe", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Atlantic/Faeroe Denmark, Faeroe Islands, and Greenland(DK) 0:00 EU WE%sT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Atlantic/Canary", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Atlantic/Canary Spain(ES) 0:00 EU WE%sT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Europe/Dublin", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Dublin ---(IE) 0:00 EU GMT/IST + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Europe/Lisbon", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Lisbon Portugal(PT) 0:00 EU WE%sT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Europe/London", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/London ---(GB) 0:00 EU GMT/BST + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Luanda" /*WAT*/), + // Africa/Luanda Angola(AO) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Porto-Novo" /*WAT*/), + // Africa/Porto-Novo Benin(BJ) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Bangui" /*WAT*/), + // Africa/Bangui Central African Republic(CF) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Kinshasa" /*WAT*/), + // Africa/Kinshasa Democratic Republic of Congo(CG) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Douala" /*WAT*/), + // Africa/Douala Cameroon(CM) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Libreville" /*WAT*/), + // Africa/Libreville Gabon(GA) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Malabo" /*WAT*/), + // Africa/Malabo Equatorial Guinea(GQ) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Niamey" /*WAT*/), + // Africa/Niamey Niger(NE) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Lagos" /*WAT*/), + // Africa/Lagos Nigeria(NG) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Ndjamena" /*WAT*/), + // Africa/Ndjamena Chad(TD) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Tunis" /*CE%sT*/), + // Africa/Tunis Tunisia(TN) 1:00 - CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Algiers" /*CET*/), + // Africa/Algiers Algeria(DZ) 1:00 - CET + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Andorra", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Andorra Andorra(AD) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Tirane", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Tirane Albania(AL) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Vienna", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Vienna Austria(AT) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Brussels", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Brussels Belgium(BE) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Zurich", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Zurich Switzerland(CH) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Prague", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Prague Czech Republic(CZ) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Berlin", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Berlin Germany(DE) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Copenhagen", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Copenhagen Denmark, Faeroe Islands, and Greenland(DK) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Madrid", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Madrid Spain(ES) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Gibraltar", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Gibraltar Gibraltar(GI) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Budapest", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Budapest Hungary(HU) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Rome", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Rome Italy(IT) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Vaduz", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Vaduz Liechtenstein(LI) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Luxembourg", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Luxembourg Luxembourg(LU) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Tripoli"), + // Zone Africa/Tripoli Libya(LY) 2:00 - EET + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Monaco", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Monaco Monaco(MC) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Malta", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Malta Malta(MT) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Windhoek" /*WA%sT*/, + Calendar.SEPTEMBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Namibia 1994 max - Sep Sun>=1 2:00 1:00 S + // Rule Namibia 1995 max - Apr Sun>=1 2:00 0 - + // Africa/Windhoek Namibia(NA) 1:00 Namibia WA%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Amsterdam", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Amsterdam Netherlands(NL) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Oslo", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Oslo Norway(NO) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Warsaw", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Warsaw 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Stockholm", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Stockholm Sweden(SE) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Belgrade", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Belgrade Yugoslavia(YU) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Paris", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Paris France(FR) 1:00 EU CE%sT + new SimpleTimeZone(1*ONE_HOUR, "ECT" /*alias for Europe/Paris*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Bujumbura" /*CAT*/), + // Africa/Bujumbura Burundi(BI) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Gaborone" /*CAT*/), + // Africa/Gaborone Botswana(BW) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Lubumbashi" /*CAT*/), + // Africa/Lubumbashi Democratic Republic of Congo(CG) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Maseru" /*SAST*/), + // Africa/Maseru Lesotho(LS) 2:00 - SAST + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Blantyre" /*CAT*/), + // Africa/Blantyre Malawi(ML) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Maputo" /*CAT*/), + // Africa/Maputo Mozambique(MZ) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Kigali" /*CAT*/), + // Africa/Kigali Rwanda(RW) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Khartoum" /*CA%sT*/), + // Africa/Khartoum Sudan(SD) 2:00 - CA%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Mbabane" /*SAST*/), + // Africa/Mbabane Swaziland(SZ) 2:00 - SAST + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Lusaka" /*CAT*/), + // Africa/Lusaka Zambia(ZM) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Harare" /*CAT*/), + // Africa/Harare Zimbabwe(ZW) 2:00 - CAT + new SimpleTimeZone(2*ONE_HOUR, "CAT" /*alias for Africa/Harare*/), + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Johannesburg" /*SAST*/), + // Africa/Johannesburg South Africa(ZA) 2:00 - SAST + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Sofia" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-Eur 1996 max - Oct lastSun 0:00 0 - + // Europe/Sofia Bulgaria(BG) 2:00 E-Eur EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Minsk" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Europe/Minsk Belarus(BY) 2:00 Russia EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Nicosia", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EUAsia 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EUAsia 1996 max - Oct lastSun 1:00u 0 - + // Zone Asia/Nicosia Cyprus(CY) 2:00 EUAsia EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Tallinn", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Tallinn Estonia(EE) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Cairo", + Calendar.APRIL, 22, -Calendar.FRIDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.SEPTEMBER, -1, Calendar.THURSDAY /*DOW_IN_MON*/, 23*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule Egypt 1995 max - Apr Fri>=22 0:00s 1:00 S + // Rule Egypt 1995 max - Sep lastThu 23:00s 0 - + // Zone Africa/Cairo Egypt(EG) 2:00 Egypt EE%sT + new SimpleTimeZone(2*ONE_HOUR, "ART" /*alias for Africa/Cairo*/, + Calendar.APRIL, 22, -Calendar.FRIDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.SEPTEMBER, -1, Calendar.THURSDAY /*DOW_IN_MON*/, 23*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Helsinki", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Helsinki Finland(FI) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Athens", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Athens Greece(GR) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Jerusalem", + Calendar.APRIL, 1, -Calendar.FRIDAY /*DOW>=DOM*/, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.SEPTEMBER, 1, -Calendar.FRIDAY /*DOW>=DOM*/, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Zion 2000 max - Apr Fri>=1 2:00 1:00 D + // Rule Zion 2000 max - Sep Fri>=1 2:00 0 S + // Zone Asia/Jerusalem Israel(IL) 2:00 Zion I%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Amman"), + // Zone Asia/Amman 2:00 Jordan EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Beirut" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.SEPTEMBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Lebanon 1993 max - Mar lastSun 0:00 1:00 S + // Rule Lebanon 1993 max - Sep lastSun 0:00 0 - + // Asia/Beirut Lebanon(LB) 2:00 Lebanon EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Vilnius", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Vilnius Lithuania(LT) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Riga", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Riga Latvia(LV) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Chisinau" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-Eur 1996 max - Oct lastSun 0:00 0 - + // Europe/Chisinau Moldova(MD) 2:00 E-Eur EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Bucharest" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-Eur 1996 max - Oct lastSun 0:00 0 - + // Europe/Bucharest Romania(RO) 2:00 E-Eur EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Kaliningrad" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Europe/Kaliningrad Russia(RU) 2:00 Russia EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/, + Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Syria 1994 max - Apr 1 0:00 1:00 S + // Rule Syria 1994 max - Oct 1 0:00 0 - + // Asia/Damascus Syria(SY) 2:00 Syria EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Kiev", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Kiev Ukraine(UA) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Istanbul", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Istanbul Turkey(TR) 2:00 EU EE%sT + new SimpleTimeZone(2*ONE_HOUR, "EET" /*alias for Europe/Istanbul*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Bahrain" /*AST*/), + // Asia/Bahrain Bahrain(BH) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Djibouti" /*EAT*/), + // Africa/Djibouti Djibouti(DJ) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Asmera" /*EAT*/), + // Africa/Asmera Eritrea(ER) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Addis_Ababa" /*EAT*/), + // Africa/Addis_Ababa Ethiopia(ET) 3:00 - EAT + new SimpleTimeZone(3*ONE_HOUR, "EAT" /*alias for Africa/Addis_Ababa*/), + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Nairobi" /*EAT*/), + // Africa/Nairobi Kenya(KE) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Indian/Comoro" /*EAT*/), + // Indian/Comoro Comoros(KM) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Kuwait" /*AST*/), + // Asia/Kuwait Kuwait(KW) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Indian/Antananarivo" /*EAT*/), + // Indian/Antananarivo Madagascar(MK) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Qatar" /*AST*/), + // Asia/Qatar Qatar(QA) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Mogadishu" /*EAT*/), + // Africa/Mogadishu Somalia(SO) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Dar_es_Salaam" /*EAT*/), + // Africa/Dar_es_Salaam Tanzania(TZ) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Kampala" /*EAT*/), + // Africa/Kampala Uganda(UG) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Aden" /*AST*/), + // Asia/Aden Yemen(YE) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Indian/Mayotte" /*EAT*/), + // Indian/Mayotte Mayotte(YT) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Riyadh" /*AST*/), + // Asia/Riyadh Saudi Arabia(SA) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Baghdad" /*A%sT*/, + Calendar.APRIL, 1, 0 /*DOM*/, 3*ONE_HOUR, + Calendar.OCTOBER, 1, 0 /*DOM*/, 4*ONE_HOUR, 1*ONE_HOUR), + // Rule Iraq 1991 max - Apr 1 3:00s 1:00 D + // Rule Iraq 1991 max - Oct 1 3:00s 0 D + // Asia/Baghdad Iraq(IQ) 3:00 Iraq A%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Simferopol", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Simferopol Ukraine(UA) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Europe/Moscow" /*MSK/MSD*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Europe/Moscow Russia(RU) 3:00 Russia MSK/MSD + //---------------------------------------------------------- + new SimpleTimeZone((int)(3.5*ONE_HOUR), "Asia/Tehran", + Calendar.MARCH, 20, 0 /*DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.SEPTEMBER, 22, 0 /*DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Iran 2000 only - Mar 20 0:00 1:00 S + // Rule Iran 2000 only - Sep 22 0:00 0 - + // Zone Asia/Tehran Iran(IR) 3:30 Iran IR%sT + new SimpleTimeZone((int)(3.5*ONE_HOUR), "MET" /*alias for Asia/Tehran*/, + Calendar.MARCH, 20, 0 /*DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.SEPTEMBER, 22, 0 /*DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Dubai" /*GST*/), + // Asia/Dubai United Arab Emirates(AE) 4:00 - GST + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Indian/Mauritius" /*MUT*/), + // Indian/Mauritius Mauritius(MU) 4:00 - MUT # Mauritius Time + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Muscat" /*GST*/), + // Asia/Muscat Oman(OM) 4:00 - GST + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Indian/Reunion" /*RET*/), + // Indian/Reunion Reunion(RE) 4:00 - RET # Reunion Time + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Indian/Mahe" /*SCT*/), + // Indian/Mahe Seychelles(SC) 4:00 - SCT # Seychelles Time + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Yerevan", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule RussiaAsia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule RussiaAsia 1996 max - Oct lastSun 2:00s 0 - + // Zone Asia/Yerevan Armenia(AM) 4:00 RussiaAsia AM%sT + new SimpleTimeZone(4*ONE_HOUR, "NET" /*alias for Asia/Yerevan*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Baku", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Azer 1997 max - Mar lastSun 1:00 1:00 S + // Rule Azer 1997 max - Oct lastSun 1:00 0 - + // Zone Asia/Baku Azerbaijan(AZ) 4:00 Azer AZ%sT + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Aqtau" /*AQT%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 - + // Asia/Aqtau Kazakhstan(KZ) 4:00 E-EurAsia AQT%sT + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Europe/Samara" /*SAM%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Europe/Samara Russia(RU) 4:00 Russia SAM%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(4.5*ONE_HOUR), "Asia/Kabul" /*AFT*/), + // Asia/Kabul Afghanistan(AF) 4:30 - AFT + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Indian/Kerguelen" /*TFT*/), + // Indian/Kerguelen France - year-round bases(FR) 5:00 - TFT # ISO code TF Time + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Tbilisi", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 - + // Zone Asia/Tbilisi Georgia(GE) 4:00 E-EurAsia GE%sT + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Indian/Chagos" /*IOT*/), + // Indian/Chagos British Indian Ocean Territory(IO) 5:00 - IOT # BIOT Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Indian/Maldives" /*MVT*/), + // Indian/Maldives Maldives(MV) 5:00 - MVT # Maldives Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Dushanbe" /*TJT*/), + // Asia/Dushanbe Tajikistan(TJ) 5:00 - TJT # Tajikistan Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Ashkhabad" /*TMT*/), + // Asia/Ashkhabad Turkmenistan(TM) 5:00 - TMT # Turkmenistan Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Tashkent" /*UZT*/), + // Asia/Tashkent Uzbekistan(UZ) 5:00 - UZT # Uzbekistan Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Karachi" /*PKT*/), + // Asia/Karachi Pakistan(PK) 5:00 - PKT # Pakistan Time + new SimpleTimeZone(5*ONE_HOUR, "PLT" /*alias for Asia/Karachi*/), + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Bishkek", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, (int)(2.5*ONE_HOUR), SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, (int)(2.5*ONE_HOUR), SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Kirgiz 1997 max - Mar lastSun 2:30 1:00 S + // Rule Kirgiz 1997 max - Oct lastSun 2:30 0 - + // Zone Asia/Bishkek Kirgizstan(KG) 5:00 Kirgiz KG%sT + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Aqtobe" /*AQT%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 - + // Asia/Aqtobe Kazakhstan(KZ) 5:00 E-EurAsia AQT%sT + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Yekaterinburg" /*YEK%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Yekaterinburg Russia(RU) 5:00 Russia YEK%sT # Yekaterinburg Time + //---------------------------------------------------------- + new SimpleTimeZone((int)(5.5*ONE_HOUR), "Asia/Calcutta" /*IST*/), + // Asia/Calcutta India(IN) 5:30 - IST + new SimpleTimeZone((int)(5.5*ONE_HOUR), "IST" /*alias for Asia/Calcutta*/), + //---------------------------------------------------------- + new SimpleTimeZone((int)(5.75*ONE_HOUR), "Asia/Katmandu" /*NPT*/), + // Asia/Katmandu Nepal(NP) 5:45 - NPT # Nepal Time + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Antarctica/Mawson" /*MAWT*/), + // Antarctica/Mawson Australia - territories(AQ) 6:00 - MAWT # Mawson Time + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Thimbu" /*BTT*/), + // Asia/Thimbu Bhutan(BT) 6:00 - BTT # Bhutan Time + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Colombo" /*LKT*/), + // Asia/Colombo Sri Lanka(LK) 6:00 - LKT + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Dacca" /*BDT*/), + // Asia/Dacca Bangladesh(BD) 6:00 - BDT # Bangladesh Time + new SimpleTimeZone(6*ONE_HOUR, "BST" /*alias for Asia/Dacca*/), + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Almaty", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 - + // Zone Asia/Almaty 6:00 E-EurAsia ALM%sT + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Novosibirsk" /*NOV%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Novosibirsk Russia(RU) 6:00 Russia NOV%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(6.5*ONE_HOUR), "Indian/Cocos" /*CCT*/), + // Indian/Cocos Cocos(CC) 6:30 - CCT # Cocos Islands Time + //---------------------------------------------------------- + new SimpleTimeZone((int)(6.5*ONE_HOUR), "Asia/Rangoon" /*MMT*/), + // Asia/Rangoon Burma / Myanmar(MM) 6:30 - MMT # Myanmar Time + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Indian/Christmas" /*CXT*/), + // Indian/Christmas Australian miscellany(AU) 7:00 - CXT # Christmas Island Time + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Jakarta" /*JAVT*/), + // Asia/Jakarta Indonesia(ID) 7:00 - JAVT + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Phnom_Penh" /*ICT*/), + // Asia/Phnom_Penh Cambodia(KH) 7:00 - ICT + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Vientiane" /*ICT*/), + // Asia/Vientiane Laos(LA) 7:00 - ICT + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Saigon" /*ICT*/), + // Asia/Saigon Vietnam(VN) 7:00 - ICT + new SimpleTimeZone(7*ONE_HOUR, "VST" /*alias for Asia/Saigon*/), + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Bangkok" /*ICT*/), + // Asia/Bangkok Thailand(TH) 7:00 - ICT + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Krasnoyarsk" /*KRA%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Krasnoyarsk Russia(RU) 7:00 Russia KRA%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Antarctica/Casey" /*WST*/), + // Antarctica/Casey Australia - territories(AQ) 8:00 - WST # Western (Aus) Standard Time + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Australia/Perth" /*WST*/), + // Australia/Perth Australia(AU) 8:00 - WST + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Brunei" /*BNT*/), + // Asia/Brunei Brunei(BN) 8:00 - BNT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Hong_Kong" /*C%sT*/), + // Asia/Hong_Kong China(HK) 8:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Ujung_Pandang" /*BORT*/), + // Asia/Ujung_Pandang Indonesia(ID) 8:00 - BORT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Macao" /*C%sT*/), + // Asia/Macao Macao(MO) 8:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Kuala_Lumpur" /*MYT*/), + // Asia/Kuala_Lumpur Malaysia(MY) 8:00 - MYT # Malaysia Time + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Manila" /*PH%sT*/), + // Asia/Manila Philippines(PH) 8:00 - PH%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Singapore" /*SGT*/), + // Asia/Singapore Singapore(SG) 8:00 - SGT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Taipei" /*C%sT*/), + // Asia/Taipei Taiwan(TW) 8:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Shanghai" /*C%sT*/), + // Asia/Shanghai China(CN) 8:00 - C%sT + new SimpleTimeZone(8*ONE_HOUR, "CTT" /*alias for Asia/Shanghai*/), + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Ulan_Bator" /*ULA%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.SEPTEMBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Mongol 1991 max - Mar lastSun 0:00 1:00 S + // Rule Mongol 1997 max - Sep lastSun 0:00 0 - + // Asia/Ulan_Bator Mongolia(MN) 8:00 Mongol ULA%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Irkutsk" /*IRK%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Irkutsk Russia(RU) 8:00 Russia IRK%sT + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Jayapura" /*JAYT*/), + // Asia/Jayapura Indonesia(ID) 9:00 - JAYT + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Pyongyang" /*KST*/), + // Asia/Pyongyang ?(KP) 9:00 - KST + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Seoul" /*K%sT*/), + // Asia/Seoul ?(KR) 9:00 - K%sT + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Pacific/Palau" /*PWT*/), + // Pacific/Palau Palau(PW) 9:00 - PWT # Palau Time + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Tokyo" /*JST*/), + // Asia/Tokyo Japan(JP) 9:00 - JST + new SimpleTimeZone(9*ONE_HOUR, "JST" /*alias for Asia/Tokyo*/), + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Yakutsk" /*YAK%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Yakutsk Russia(RU) 9:00 Russia YAK%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(9.5*ONE_HOUR), "Australia/Darwin" /*CST*/), + // Australia/Darwin Australia(AU) 9:30 - CST + new SimpleTimeZone((int)(9.5*ONE_HOUR), "ACT" /*alias for Australia/Darwin*/), + //---------------------------------------------------------- + new SimpleTimeZone((int)(9.5*ONE_HOUR), "Australia/Adelaide", + Calendar.AUGUST, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule AS 2000 only - Aug lastSun 2:00s 1:00 - + // Rule AS 1995 max - Mar lastSun 2:00s 0 - + // Zone Australia/Adelaide 9:30 AS CST + //---------------------------------------------------------- + new SimpleTimeZone((int)(9.5*ONE_HOUR), "Australia/Broken_Hill", + Calendar.AUGUST, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule AN 2000 only - Aug lastSun 2:00s 1:00 - + // Rule AN 1996 max - Mar lastSun 2:00s 0 - + // Zone Australia/Broken_Hill 9:30 AN CST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Australia/Hobart", + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule AT 1991 max - Oct Sun>=1 2:00s 1:00 - + // Rule AT 1991 max - Mar lastSun 2:00s 0 - + // Australia/Hobart 10:00 AT EST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Antarctica/DumontDUrville" /*DDUT*/), + // Antarctica/DumontDUrville France - year-round bases(AQ) 10:00 - DDUT # Dumont-d'Urville Time + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Pacific/Truk" /*TRUT*/), + // Pacific/Truk Micronesia(FM) 10:00 - TRUT # Truk Time + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Pacific/Guam" /*GST*/), + // Pacific/Guam Guam(GU) 10:00 - GST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Pacific/Saipan" /*MPT*/), + // Pacific/Saipan N Mariana Is(MP) 10:00 - MPT + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Pacific/Port_Moresby" /*PGT*/), + // Pacific/Port_Moresby Papua New Guinea(PG) 10:00 - PGT # Papua New Guinea Time + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Australia/Brisbane" /*EST*/), + // Australia/Brisbane Australia(AU) 10:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Asia/Vladivostok" /*VLA%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Vladivostok Russia(RU) 10:00 Russia VLA%sT + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Australia/Sydney", + Calendar.AUGUST, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule AN 2000 only - Aug lastSun 2:00s 1:00 - + // Rule AN 1996 max - Mar lastSun 2:00s 0 - + // Zone Australia/Sydney 10:00 AN EST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "AET" /*alias for Australia/Sydney*/, + Calendar.AUGUST, 26, 0 /*DOM*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone((int)(10.5*ONE_HOUR), "Australia/Lord_Howe", + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, (int)(0.5*ONE_HOUR)), + // Rule LH 1987 max - Oct lastSun 2:00s 0:30 - + // Rule LH 1996 max - Mar lastSun 2:00s 0 - + // Zone Australia/Lord_Howe Lord Howe Island(AU) 10:30 LH LHST + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Pacific/Ponape" /*PONT*/), + // Pacific/Ponape Micronesia(FM) 11:00 - PONT # Ponape Time + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Pacific/Efate" /*VU%sT*/), + // Pacific/Efate Vanuatu(VU) 11:00 - VU%sT # Vanuatu Time + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Pacific/Guadalcanal" /*SBT*/), + // Pacific/Guadalcanal Solomon Is(SB) 11:00 - SBT # Solomon Is Time + new SimpleTimeZone(11*ONE_HOUR, "SST" /*alias for Pacific/Guadalcanal*/), + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Pacific/Noumea"), + // Zone Pacific/Noumea New Caledonia(NC) 11:00 NC NC%sT + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Asia/Magadan" /*MAG%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Magadan Russia(RU) 11:00 Russia MAG%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(11.5*ONE_HOUR), "Pacific/Norfolk" /*NFT*/), + // Pacific/Norfolk Norfolk(NF) 11:30 - NFT # Norfolk Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Kosrae" /*KOST*/), + // Pacific/Kosrae Micronesia(FM) 12:00 - KOST # Kosrae Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Tarawa" /*GILT*/), + // Pacific/Tarawa Kiribati(KI) 12:00 - GILT # Gilbert Is Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Majuro" /*MHT*/), + // Pacific/Majuro Marshall Is(MH) 12:00 - MHT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Nauru" /*NRT*/), + // Pacific/Nauru Nauru(NR) 12:00 - NRT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Funafuti" /*TVT*/), + // Pacific/Funafuti Tuvalu(TV) 12:00 - TVT # Tuvalu Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Wake" /*WAKT*/), + // Pacific/Wake Wake(US) 12:00 - WAKT # Wake Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Wallis" /*WFT*/), + // Pacific/Wallis Wallis and Futuna(WF) 12:00 - WFT # Wallis & Futuna Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Fiji", + Calendar.NOVEMBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.FEBRUARY, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 3*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Fiji 1998 max - Nov Sun>=1 2:00 1:00 S + // Rule Fiji 1999 max - Feb lastSun 3:00 0 - + // Zone Pacific/Fiji Fiji(FJ) 12:00 Fiji FJ%sT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Antarctica/McMurdo" /*NZ%sT*/, + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.MARCH, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule NZAQ 1990 max - Oct Sun>=1 2:00s 1:00 D + // Rule NZAQ 1990 max - Mar Sun>=15 2:00s 0 S + // Antarctica/McMurdo USA - year-round bases(AQ) 12:00 NZAQ NZ%sT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Asia/Kamchatka" /*PET%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Kamchatka Russia(RU) 12:00 Russia PET%sT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Auckland" /*NZ%sT*/, + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.MARCH, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule NZ 1990 max - Oct Sun>=1 2:00s 1:00 D + // Rule NZ 1990 max - Mar Sun>=15 2:00s 0 S + // Pacific/Auckland New Zealand(NZ) 12:00 NZ NZ%sT + new SimpleTimeZone(12*ONE_HOUR, "NST" /*alias for Pacific/Auckland*/, + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.MARCH, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone((int)(12.75*ONE_HOUR), "Pacific/Chatham" /*CHA%sT*/, + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, (int)(2.75*ONE_HOUR), + Calendar.MARCH, 15, -Calendar.SUNDAY /*DOW>=DOM*/, (int)(3.75*ONE_HOUR), 1*ONE_HOUR), + // Rule Chatham 1990 max - Oct Sun>=1 2:45s 1:00 D + // Rule Chatham 1991 max - Mar Sun>=15 2:45s 0 S + // Pacific/Chatham New Zealand(NZ) 12:45 Chatham CHA%sT + //---------------------------------------------------------- + new SimpleTimeZone(13*ONE_HOUR, "Pacific/Enderbury" /*PHOT*/), + // Pacific/Enderbury Kiribati(KI) 13:00 - PHOT + //---------------------------------------------------------- + new SimpleTimeZone(13*ONE_HOUR, "Pacific/Tongatapu" /*TOT*/), + // Pacific/Tongatapu Tonga(TO) 13:00 - TOT + //---------------------------------------------------------- + new SimpleTimeZone(13*ONE_HOUR, "Asia/Anadyr" /*ANA%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Anadyr Russia(RU) 13:00 Russia ANA%sT + //---------------------------------------------------------- + new SimpleTimeZone(14*ONE_HOUR, "Pacific/Kiritimati" /*LINT*/), + // Pacific/Kiritimati Kiribati(KI) 14:00 - LINT + }; + // ---------------- END GENERATED DATA ---------------- + + private static Hashtable lookup = new Hashtable(zones.length); + + static { + for (int i=0; i < zones.length; ++i) + lookup.put(zones[i].getID(), zones[i]); + TimeZone.getDefault(); // to cache default system time zone + } +} + +//eof diff --git a/icu4j/src/com/ibm/test/calendar/AstroTest.java b/icu4j/src/com/ibm/test/calendar/AstroTest.java index 023ae6f479..d7ca4b983f 100755 --- a/icu4j/src/com/ibm/test/calendar/AstroTest.java +++ b/icu4j/src/com/ibm/test/calendar/AstroTest.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/test/calendar/Attic/AstroTest.java,v $ - * $Date: 2000/03/21 02:20:08 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:19:12 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -15,7 +15,6 @@ package com.ibm.test.calendar; // AstroTest import com.ibm.test.*; -import java.util.SimpleTimeZone; import com.ibm.util.*; import com.ibm.util.CalendarAstronomer.*; diff --git a/icu4j/src/com/ibm/test/calendar/CalendarRegression.java b/icu4j/src/com/ibm/test/calendar/CalendarRegression.java index b15d2e699c..7e82722d96 100755 --- a/icu4j/src/com/ibm/test/calendar/CalendarRegression.java +++ b/icu4j/src/com/ibm/test/calendar/CalendarRegression.java @@ -1,8 +1,6 @@ package com.ibm.test.calendar; import com.ibm.util.*; import java.util.Date; -import java.util.TimeZone; -import java.util.SimpleTimeZone; import java.util.Locale; import com.ibm.text.*; @@ -771,23 +769,25 @@ public class CalendarRegression extends com.ibm.test.TestFmwk { // I am disabling this test -- it is currently failing because of a bug // in Sun's latest change to STZ.getOffset(). I have filed a Sun bug // against this problem. -//! /** -//! * Prove that GregorianCalendar is proleptic (it used to cut off -//! * at 45 BC, and not have leap years before then). -//! */ -//! public void Test4125892() { -//! GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance(); -//! DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G"); -//! cal.clear(); -//! cal.set(Calendar.ERA, GregorianCalendar.BC); -//! cal.set(Calendar.YEAR, 81); // 81 BC is a leap year (proleptically) -//! cal.set(Calendar.MONTH, Calendar.FEBRUARY); -//! cal.set(Calendar.DATE, 28); -//! cal.add(Calendar.DATE, 1); -//! if (cal.get(Calendar.DATE) != 29 || -//! !cal.isLeapYear(-80)) // -80 == 81 BC -//! errln("Calendar not proleptic"); -//! } + + // Re-enabled after 'porting' TZ and STZ from java.util to com.ibm.util. + /** + * Prove that GregorianCalendar is proleptic (it used to cut off + * at 45 BC, and not have leap years before then). + */ + public void Test4125892() { + GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance(); + DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G"); + cal.clear(); + cal.set(Calendar.ERA, GregorianCalendar.BC); + cal.set(Calendar.YEAR, 81); // 81 BC is a leap year (proleptically) + cal.set(Calendar.MONTH, Calendar.FEBRUARY); + cal.set(Calendar.DATE, 28); + cal.add(Calendar.DATE, 1); + if (cal.get(Calendar.DATE) != 29 || + !cal.isLeapYear(-80)) // -80 == 81 BC + errln("Calendar not proleptic"); + } /** * Calendar and GregorianCalendar hashCode() methods need improvement. diff --git a/icu4j/src/com/ibm/test/calendar/CalendarTest.java b/icu4j/src/com/ibm/test/calendar/CalendarTest.java index 35954ce3e1..d2f976efbc 100755 --- a/icu4j/src/com/ibm/test/calendar/CalendarTest.java +++ b/icu4j/src/com/ibm/test/calendar/CalendarTest.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/test/calendar/Attic/CalendarTest.java,v $ - * $Date: 2000/03/21 02:20:08 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:19:12 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -18,7 +18,6 @@ import com.ibm.text.DateFormat; import com.ibm.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -import java.util.SimpleTimeZone; import com.ibm.util.*; /** diff --git a/icu4j/src/com/ibm/test/calendar/CompatibilityTest.java b/icu4j/src/com/ibm/test/calendar/CompatibilityTest.java index 15e7bf4be8..4bbce5cffd 100755 --- a/icu4j/src/com/ibm/test/calendar/CompatibilityTest.java +++ b/icu4j/src/com/ibm/test/calendar/CompatibilityTest.java @@ -7,8 +7,6 @@ package com.ibm.test.calendar; import com.ibm.util.*; import java.util.Date; -import java.util.TimeZone; -import java.util.SimpleTimeZone; import java.util.Locale; import java.text.*; import java.io.*; diff --git a/icu4j/src/com/ibm/test/calendar/TestCase.java b/icu4j/src/com/ibm/test/calendar/TestCase.java index 04b8251c52..a451645175 100755 --- a/icu4j/src/com/ibm/test/calendar/TestCase.java +++ b/icu4j/src/com/ibm/test/calendar/TestCase.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/test/calendar/Attic/TestCase.java,v $ - * $Date: 2000/03/21 02:20:08 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:19:12 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -16,7 +16,7 @@ import com.ibm.test.*; import com.ibm.util.Calendar; import com.ibm.util.GregorianCalendar; import java.util.Date; -import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; import java.util.Locale; /** diff --git a/icu4j/src/com/ibm/test/timezone/TimeZoneBoundaryTest.java b/icu4j/src/com/ibm/test/timezone/TimeZoneBoundaryTest.java new file mode 100755 index 0000000000..ca63f6ec16 --- /dev/null +++ b/icu4j/src/com/ibm/test/timezone/TimeZoneBoundaryTest.java @@ -0,0 +1,674 @@ +/* + @test 1.9 99/06/15 + @summary test Time Zone Boundary +*/ + +package com.ibm.test.timezone; +import com.ibm.text.*; +import com.ibm.util.*; +import com.ibm.test.*; +import java.util.Date; + +/** + * A test which discovers the boundaries of DST programmatically and verifies + * that they are correct. + */ +public class TimeZoneBoundaryTest extends TestFmwk +{ + static final int ONE_SECOND = 1000; + static final int ONE_MINUTE = 60*ONE_SECOND; + static final int ONE_HOUR = 60*ONE_MINUTE; + static final long ONE_DAY = 24*ONE_HOUR; + static final long ONE_YEAR = (long)(365.25 * ONE_DAY); + static final long SIX_MONTHS = ONE_YEAR / 2; + + static final int MONTH_LENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31}; + + // These values are empirically determined to be correct + static final long PST_1997_BEG = 860320800000L; + static final long PST_1997_END = 877856400000L; + + // Minimum interval for binary searches in ms; should be no larger + // than 1000. + static final long INTERVAL = 10; // Milliseconds + + // When long zone names are supported again, switch this to the + // long zone name. + static final String AUSTRALIA = "AET"; // Australia/Adelaide + static final long AUSTRALIA_1997_BEG = 872524800000L; // 877797000000L + static final long AUSTRALIA_1997_END = 859651200000L; // 859653000000L + + public static void main(String[] args) throws Exception { + new TimeZoneBoundaryTest().run(args); + } + + /** + * Date.toString().substring() Boundary Test + * Look for a DST changeover to occur within 6 months of the given Date. + * The initial Date.toString() should yield a string containing the + * startMode as a SUBSTRING. The boundary will be tested to be + * at the expectedBoundary value. + */ + void findDaylightBoundaryUsingDate(Date d, String startMode, long expectedBoundary) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + if (d.toString().indexOf(startMode) == -1) + { + logln("Error: " + startMode + " not present in " + d); + } + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + SIX_MONTHS; + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + String s = new Date(mid).toString(); + // logln(s); + if (s.indexOf(startMode) != -1) + { + min = mid; + } + else + { + max = mid; + } + } + + logln("Date Before: " + showDate(min)); + logln("Date After: " + showDate(max)); + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + // This test cannot be compiled until the inDaylightTime() method of GregorianCalendar + // becomes public. + // static void findDaylightBoundaryUsingCalendar(Date d, boolean startsInDST) + // { + // // Given a date with a year start, find the Daylight onset + // // and end. The given date should be 1/1/xx in some year. + // + // GregorianCalendar cal = new GregorianCalendar(); + // cal.setTime(d); + // if (cal.inDaylightTime() != startsInDST) + // { + // logln("Error: inDaylightTime(" + d + ") != " + startsInDST); + // } + // + // // Use a binary search, assuming that we have a Standard + // // time at the midpoint. + // long min = d.getTime(); + // long max = min + (long)(365.25 / 2 * 24*60*60*1000); + // + // while ((max - min) > INTERVAL) + // { + // long mid = (min + max) >> 1; + // cal.setTime(new Date(mid)); + // if (cal.inDaylightTime() == startsInDST) + // { + // min = mid; + // } + // else + // { + // max = mid; + // } + // } + // + // logln("Calendar Before: " + showDate(min)); + // logln("Calendar After: " + showDate(max)); + // } + + void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, long expectedBoundary) + { + findDaylightBoundaryUsingTimeZone(d, startsInDST, expectedBoundary, + TimeZone.getDefault()); + } + + void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, + long expectedBoundary, TimeZone tz) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + SIX_MONTHS; + + if (tz.inDaylightTime(d) != startsInDST) + { + errln("FAIL: " + tz.getID() + " inDaylightTime(" + + d + ") != " + startsInDST); + startsInDST = !startsInDST; // Flip over; find the apparent value + } + + if (tz.inDaylightTime(new Date(max)) == startsInDST) + { + errln("FAIL: " + tz.getID() + " inDaylightTime(" + + (new Date(max)) + ") != " + (!startsInDST)); + return; + } + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + boolean isIn = tz.inDaylightTime(new Date(mid)); + if (isIn == startsInDST) + { + min = mid; + } + else + { + max = mid; + } + } + + logln(tz.getID() + " Before: " + showDate(min, tz)); + logln(tz.getID() + " After: " + showDate(max, tz)); + + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + private static String showDate(long l) + { + return showDate(new Date(l)); + } + + private static String showDate(Date d) + { + return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) + + " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) + + " \"" + d + "\" = " + + d.getTime(); + } + + private static String showDate(long l, TimeZone z) + { + return showDate(new Date(l), z); + } + + private static String showDate(Date d, TimeZone zone) + { + DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + fmt.setTimeZone(zone); + return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) + + " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) + + " \"" + d + "\" = " + + fmt.format(d); + } + + private static String showNN(int n) + { + return ((n < 10) ? "0" : "") + n; + } + + /** + * Given a date, a TimeZone, and expected values for inDaylightTime, + * useDaylightTime, zone and DST offset, verify that this is the case. + */ + void verifyDST(Date d, TimeZone time_zone, + boolean expUseDaylightTime, boolean expInDaylightTime, + int expZoneOffset, int expDSTOffset) + { + logln("-- Verifying time " + d + + " in zone " + time_zone.getID()); + + if (time_zone.inDaylightTime(d) == expInDaylightTime) + logln("PASS: inDaylightTime = " + time_zone.inDaylightTime(d)); + else + errln("FAIL: inDaylightTime = " + time_zone.inDaylightTime(d)); + + if (time_zone.useDaylightTime() == expUseDaylightTime) + logln("PASS: useDaylightTime = " + time_zone.useDaylightTime()); + else + errln("FAIL: useDaylightTime = " + time_zone.useDaylightTime()); + + if (time_zone.getRawOffset() == expZoneOffset) + logln("PASS: getRawOffset() = " + expZoneOffset/(double)ONE_HOUR); + else + errln("FAIL: getRawOffset() = " + time_zone.getRawOffset()/(double)ONE_HOUR + + "; expected " + expZoneOffset/(double)ONE_HOUR); + + GregorianCalendar gc = new GregorianCalendar(time_zone); + gc.setTime(d); + int offset = time_zone.getOffset(gc.get(gc.ERA), gc.get(gc.YEAR), gc.get(gc.MONTH), + gc.get(gc.DAY_OF_MONTH), gc.get(gc.DAY_OF_WEEK), + ((gc.get(gc.HOUR_OF_DAY) * 60 + + gc.get(gc.MINUTE)) * 60 + + gc.get(gc.SECOND)) * 1000 + + gc.get(gc.MILLISECOND)); + if (offset == expDSTOffset) + logln("PASS: getOffset() = " + offset/(double)ONE_HOUR); + else + errln("FAIL: getOffset() = " + offset/(double)ONE_HOUR + + "; expected " + expDSTOffset/(double)ONE_HOUR); + } + + public void TestBoundaries() + { + TimeZone pst = TimeZone.getTimeZone("PST"); + TimeZone save = TimeZone.getDefault(); + try { + TimeZone.setDefault(pst); + + // DST changeover for PST is 4/6/1997 at 2 hours past midnight + Date d = new Date(97,Calendar.APRIL,6); + + // i is minutes past midnight standard time + for (int i=60; i<=180; i+=15) + { + boolean inDST = (i >= 120); + Date e = new Date(d.getTime() + i*60*1000); + verifyDST(e, pst, true, inDST, -8*ONE_HOUR, + inDST ? -7*ONE_HOUR : -8*ONE_HOUR); + } + } finally { + TimeZone.setDefault(save); + } + + if (true) + { + // This only works in PST/PDT + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + logln("========================================"); + findDaylightBoundaryUsingDate(new Date(97,0,1), "PST", PST_1997_BEG); + logln("========================================"); + findDaylightBoundaryUsingDate(new Date(97,6,1), "PDT", PST_1997_END); + } + + // if (true) + // { + // logln("========================================"); + // findDaylightBoundaryUsingCalendar(new Date(97,0,1), false); + // logln("========================================"); + // findDaylightBoundaryUsingCalendar(new Date(97,6,1), true); + // } + + if (true) + { + // Southern hemisphere test + logln("========================================"); + TimeZone z = TimeZone.getTimeZone(AUSTRALIA); + findDaylightBoundaryUsingTimeZone(new Date(97,0,1), true, AUSTRALIA_1997_END, z); + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,6,1), false, AUSTRALIA_1997_BEG, z); + } + + if (true) + { + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,0,1), false, PST_1997_BEG); + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true, PST_1997_END); + } + + // This just shows the offset for April 4-7 in 1997. This is redundant + // with a test above, so we disable it. + if (false) + { + TimeZone z = TimeZone.getDefault(); + logln(z.getOffset(1, 97, 3, 4, 6, 0) + " " + new Date(97, 3, 4)); + logln(z.getOffset(1, 97, 3, 5, 7, 0) + " " + new Date(97, 3, 5)); + logln(z.getOffset(1, 97, 3, 6, 1, 0) + " " + new Date(97, 3, 6)); + logln(z.getOffset(1, 97, 3, 7, 2, 0) + " " + new Date(97, 3, 7)); + } + } + + + //---------------------------------------------------------------------- + // Can't do any of these without a public inDaylightTime in GC + //---------------------------------------------------------------------- + + + // static GregorianCalendar cal = new GregorianCalendar(); + // + // static void _testUsingBinarySearch(Date d, boolean startsInDST) + // { + // // Given a date with a year start, find the Daylight onset + // // and end. The given date should be 1/1/xx in some year. + // + // // Use a binary search, assuming that we have a Standard + // // time at the midpoint. + // long min = d.getTime(); + // long max = min + (long)(365.25 / 2 * ONE_DAY); + // + // // First check the max + // cal.setTime(new Date(max)); + // if (cal.inDaylightTime() == startsInDST) + // { + // logln("Error: inDaylightTime(" + (new Date(max)) + ") != " + (!startsInDST)); + // } + // + // cal.setTime(d); + // if (cal.inDaylightTime() != startsInDST) + // { + // logln("Error: inDaylightTime(" + d + ") != " + startsInDST); + // } + // + // while ((max - min) > INTERVAL) + // { + // long mid = (min + max) >> 1; + // cal.setTime(new Date(mid)); + // if (cal.inDaylightTime() == startsInDST) + // { + // min = mid; + // } + // else + // { + // max = mid; + // } + // } + // + // logln("Binary Search Before: " + showDate(min)); + // logln("Binary Search After: " + showDate(max)); + // } + // + // static void _testUsingMillis(Date d, boolean startsInDST) + // { + // long millis = d.getTime(); + // long max = millis + (long)(370 * ONE_DAY); // A year plus extra + // + // boolean lastDST = startsInDST; + // while (millis < max) + // { + // cal.setTime(new Date(millis)); + // boolean inDaylight = cal.inDaylightTime(); + // + // if (inDaylight != lastDST) + // { + // logln("Switch " + (inDaylight ? "into" : "out of") + // + " DST at " + (new Date(millis))); + // lastDST = inDaylight; + // } + // + // millis += 15*ONE_MINUTE; + // } + // } + // + // static void _testUsingFields(int y, boolean startsInDST) + // { + // boolean lastDST = startsInDST; + // for (int m = 0; m < 12; ++m) + // { + // for (int d = 1; d <= MONTH_LENGTH[m]; ++d) + // { + // for (int h = 0; h < 24; ++h) + // { + // for (int min = 0; min < 60; min += 15) + // { + // cal.clear(); + // cal.set(y, m, d, h, min); + // boolean inDaylight = cal.inDaylightTime(); + // if (inDaylight != lastDST) + // { + // lastDST = inDaylight; + // log("Switch " + (lastDST ? "into" : "out of") + // + " DST at " + y + "/" + (m+1) + "/" + d + // + " " + showNN(h) + ":" + showNN(min)); + // logln(" " + cal.getTime()); + // + // cal.set(y, m, d, h-1, 45); + // log("Before = " + //+ y + "/" + (m+1) + "/" + d + //+ " " + showNN(h-1) + ":" + showNN(45)); + // logln(" " + cal.getTime()); + // } + // } + // } + // } + // } + // } + // + // public void Test1() + // { + // logln(Locale.getDefault().getDisplayName()); + // logln(TimeZone.getDefault().getID()); + // logln(new Date(0)); + // + // if (true) + // { + // logln("========================================"); + // _testUsingBinarySearch(new Date(97,0,1), false); + // logln("========================================"); + // _testUsingBinarySearch(new Date(97,6,1), true); + // } + // + // if (true) + // { + // logln("========================================"); + // logln("Stepping using millis"); + // _testUsingMillis(new Date(97,0,1), false); + // } + // + // if (true) + // { + // logln("========================================"); + // logln("Stepping using fields"); + // _testUsingFields(1997, false); + // } + // + // if (false) + // { + // cal.clear(); + // cal.set(1997, 3, 5, 10, 0); + // // cal.inDaylightTime(); + // logln("Date = " + cal.getTime()); + // logln("Millis = " + cal.getTime().getTime()/3600000); + // } + // } + + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + + void _testUsingBinarySearch(SimpleTimeZone tz, Date d, long expectedBoundary) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + (long)(365.25 / 2 * ONE_DAY); + + // First check the boundaries + boolean startsInDST = tz.inDaylightTime(d); + + if (tz.inDaylightTime(new Date(max)) == startsInDST) + { + logln("Error: inDaylightTime(" + (new Date(max)) + ") != " + (!startsInDST)); + } + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + if (tz.inDaylightTime(new Date(mid)) == startsInDST) + { + min = mid; + } + else + { + max = mid; + } + } + + logln("Binary Search Before: " + showDate(min)); + logln("Binary Search After: " + showDate(max)); + + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + /* + static void _testUsingMillis(Date d, boolean startsInDST) + { + long millis = d.getTime(); + long max = millis + (long)(370 * ONE_DAY); // A year plus extra + + boolean lastDST = startsInDST; + while (millis < max) + { + cal.setTime(new Date(millis)); + boolean inDaylight = cal.inDaylightTime(); + + if (inDaylight != lastDST) + { + logln("Switch " + (inDaylight ? "into" : "out of") + + " DST at " + (new Date(millis))); + lastDST = inDaylight; + } + + millis += 15*ONE_MINUTE; + } + } + */ + + /** + * Test new rule formats. + */ + public void TestNewRules() + { + //logln(Locale.getDefault().getDisplayName()); + //logln(TimeZone.getDefault().getID()); + //logln(new Date(0)); + + if (true) + { + // Doesn't matter what the default TimeZone is here, since we + // are creating our own TimeZone objects. + + SimpleTimeZone tz; + + logln("-----------------------------------------------------------------"); + logln("Aug 2ndTues .. Mar 15"); + tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_1", + Calendar.AUGUST, 2, Calendar.TUESDAY, 2*ONE_HOUR, + Calendar.MARCH, 15, 0, 2*ONE_HOUR); + //logln(tz.toString()); + logln("========================================"); + _testUsingBinarySearch(tz, new Date(97,0,1), 858416400000L); + logln("========================================"); + _testUsingBinarySearch(tz, new Date(97,6,1), 871380000000L); + + logln("-----------------------------------------------------------------"); + logln("Apr Wed>=14 .. Sep Sun<=20"); + tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_2", + Calendar.APRIL, 14, -Calendar.WEDNESDAY, 2*ONE_HOUR, + Calendar.SEPTEMBER, -20, -Calendar.SUNDAY, 2*ONE_HOUR); + //logln(tz.toString()); + logln("========================================"); + _testUsingBinarySearch(tz, new Date(97,0,1), 861184800000L); + logln("========================================"); + _testUsingBinarySearch(tz, new Date(97,6,1), 874227600000L); + } + + /* + if (true) + { + logln("========================================"); + logln("Stepping using millis"); + _testUsingMillis(new Date(97,0,1), false); + } + + if (true) + { + logln("========================================"); + logln("Stepping using fields"); + _testUsingFields(1997, false); + } + + if (false) + { + cal.clear(); + cal.set(1997, 3, 5, 10, 0); + // cal.inDaylightTime(); + logln("Date = " + cal.getTime()); + logln("Millis = " + cal.getTime().getTime()/3600000); + } + */ + } + + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + // Long Bug + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + + //public void Test3() + //{ + // findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true); + //} + + /** + * Find boundaries by stepping. + */ + void findBoundariesStepwise(int year, long interval, TimeZone z, int expectedChanges) + { + Date d = new Date(year - 1900, Calendar.JANUARY, 1); + long time = d.getTime(); // ms + long limit = time + ONE_YEAR + ONE_DAY; + boolean lastState = z.inDaylightTime(d); + int changes = 0; + logln("-- Zone " + z.getID() + " starts in " + year + " with DST = " + lastState); + logln("useDaylightTime = " + z.useDaylightTime()); + while (time < limit) + { + d.setTime(time); + boolean state = z.inDaylightTime(d); + if (state != lastState) + { + logln((state ? "Entry " : "Exit ") + + "at " + d); + lastState = state; + ++changes; + } + time += interval; + } + if (changes == 0) + { + if (!lastState && !z.useDaylightTime()) logln("No DST"); + else errln("FAIL: DST all year, or no DST with true useDaylightTime"); + } + else if (changes != 2) + { + errln("FAIL: " + changes + " changes seen; should see 0 or 2"); + } + else if (!z.useDaylightTime()) + { + errln("FAIL: useDaylightTime false but 2 changes seen"); + } + if (changes != expectedChanges) + { + errln("FAIL: " + changes + " changes seen; expected " + expectedChanges); + } + } + + public void TestStepwise() + { + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("EST"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("ACT"), 0); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone(AUSTRALIA), 2); + } +} diff --git a/icu4j/src/com/ibm/test/timezone/TimeZoneRegression.java b/icu4j/src/com/ibm/test/timezone/TimeZoneRegression.java new file mode 100755 index 0000000000..f962d7f994 --- /dev/null +++ b/icu4j/src/com/ibm/test/timezone/TimeZoneRegression.java @@ -0,0 +1,851 @@ +/** + * @test 1.18 99/09/21 + * @bug 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429 + * @bug 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960 + */ + +package com.ibm.test.timezone; +import com.ibm.util.*; +import java.io.*; +import com.ibm.text.*; +import com.ibm.test.*; +import java.util.Date; +import java.util.Locale; + +public class TimeZoneRegression extends TestFmwk { + + public static void main(String[] args) throws Exception { + new TimeZoneRegression().run(args); + } + + public void Test4052967() { + logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***"); + String id = TimeZone.getDefault().getID(); + logln("user.timezone: " + System.getProperty("user.timezone", "")); + logln("TimeZone.getDefault().getID(): " + id); + logln(new Date().toString()); + logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***"); + } + + public void Test4073209() { + TimeZone z1 = TimeZone.getTimeZone("PST"); + TimeZone z2 = TimeZone.getTimeZone("PST"); + if (z1 == z2) errln("Fail: TimeZone should return clones"); + } + + public void Test4073215() { + SimpleTimeZone z = (SimpleTimeZone) TimeZone.getTimeZone("GMT"); + if (z.useDaylightTime()) + errln("Fail: Fix test to start with non-DST zone"); + z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0); + z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0); + if (!z.useDaylightTime()) + errln("Fail: DST not active"); + if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) || + !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) || + z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) { + errln("Fail: DST not working as expected"); + } + } + + /** + * The expected behavior of TimeZone around the boundaries is: + * (Assume transition time of 2:00 AM) + * day of onset 1:59 AM STD = display name 1:59 AM ST + * 2:00 AM STD = display name 3:00 AM DT + * day of end 0:59 AM STD = display name 1:59 AM DT + * 1:00 AM STD = display name 1:00 AM ST + */ + public void Test4084933() { + TimeZone tz = TimeZone.getTimeZone("PST"); + + long offset1 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)); + long offset2 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1); + + long offset3 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)); + long offset4 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1); + + /* + * The following was added just for consistency. It shows that going *to* Daylight + * Savings Time (PDT) does work at 2am. + */ + + long offset5 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)); + long offset6 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1); + + long offset7 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)); + long offset8 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1); + + long SToffset = -8 * 60*60*1000L; + long DToffset = -7 * 60*60*1000L; + if (offset1 != SToffset || offset2 != SToffset || + offset3 != SToffset || offset4 != DToffset || + offset5 != DToffset || offset6 != SToffset || + offset7 != SToffset || offset8 != SToffset) + errln("Fail: TimeZone misbehaving"); + } + + public void Test4096952() { + String[] ZONES = { "GMT", "MET", "IST" }; + boolean pass = true; + try { + for (int i=0; i= ONE_DAY) { + millis -= ONE_DAY; + ++date; + dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7); + } + + tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA), + testCal.get(Calendar.YEAR), + testCal.get(Calendar.MONTH), + date, + dow, + millis); + tzRawOffset = testTZ.getRawOffset(); + tzOffsetFloat = new Float((float)tzOffset/(float)3600000); + tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000); + + Date testDate = testCal.getTime(); + + boolean inDaylightTime = testTZ.inDaylightTime(testDate); + SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm"); + sdf.setCalendar(testCal); + String inDaylightTimeString; + + boolean passed; + + if (inDaylightTime) + { + inDaylightTimeString = " DST "; + passed = (tzOffset == (tzRawOffset + 3600000)); + } + else + { + inDaylightTimeString = " "; + passed = (tzOffset == tzRawOffset); + } + + String output = testTZ.getID() + " " + sdf.format(testDate) + + " Offset(" + tzOffsetFloat + ")" + + " RawOffset(" + tzRawOffsetFloat + ")" + + " " + millis/(float)3600000 + " " + + inDaylightTimeString; + + if (passed) + output += " "; + else + output += "ERROR"; + + if (passed) logln(output); else errln(output); + return passed; + } + + /** + * CANNOT REPRODUDE + * + * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never + * should have been made public. It's simply too hard to use correctly. + * + * The original test code failed to do the following: + * (1) Call Calendar.setTime() before getting the fields! + * (2) Use the right millis (as usual) for getOffset(); they were passing + * in the MILLIS field, instead of the STANDARD MILLIS IN DAY. + * When you fix these two problems, the test passes, as expected. + */ + public void Test4126678() { + // Note: this test depends on the PST time zone. + TimeZone initialZone = TimeZone.getDefault(); + Calendar cal = Calendar.getInstance(); + TimeZone tz = TimeZone.getTimeZone("PST"); + TimeZone.setDefault(tz); + cal.setTimeZone(tz); + + Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0); + // the dt value is local time in PST. + if (!tz.inDaylightTime(dt)) + errln("We're not in Daylight Savings Time and we should be.\n"); + + cal.setTime(dt); + int era = cal.get(Calendar.ERA); + int year = cal.get(Calendar.YEAR); + int month = cal.get(Calendar.MONTH); + int day = cal.get(Calendar.DATE); + int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); + int millis = cal.get(Calendar.MILLISECOND) + + (cal.get(Calendar.SECOND) + + (cal.get(Calendar.MINUTE) + + (cal.get(Calendar.HOUR) * 60) * 60) * 1000) - + cal.get(Calendar.DST_OFFSET); + + long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis); + long raw_offset = tz.getRawOffset(); + if (offset == raw_offset) + errln("Offsets should not match when in DST"); + + // restore the initial time zone so that this test case + // doesn't affect the others. + TimeZone.setDefault(initialZone); + } + + /** + * TimeZone.getAvailableIDs(int) throws exception for certain values, + * due to a faulty constant in TimeZone.java. + */ + public void Test4151406() { + int max = 0; + for (int h=-28; h<=30; ++h) { + // h is in half-hours from GMT; rawoffset is in millis + int rawoffset = h * 1800000; + int hh = (h<0) ? -h : h; + String hname = ((h<0) ? "GMT-" : "GMT+") + + ((hh/2 < 10) ? "0" : "") + + (hh/2) + ':' + + ((hh%2==0) ? "00" : "30"); + try { + String[] ids = TimeZone.getAvailableIDs(rawoffset); + if (ids.length > max) max = ids.length; + logln(hname + ' ' + ids.length + + ((ids.length > 0) ? (" e.g. " + ids[0]) : "")); + } catch (Exception e) { + errln(hname + ' ' + "Fail: " + e); + } + } + logln("Maximum zones per offset = " + max); + } + + public void Test4151429() { + try { + TimeZone tz = TimeZone.getTimeZone("GMT"); + String name = tz.getDisplayName(true, Integer.MAX_VALUE, + Locale.getDefault()); + errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()"); + } catch(IllegalArgumentException e) {} + } + + /** + * SimpleTimeZone accepts illegal DST savings values. These values + * must be non-zero. There is no upper limit at this time. + */ + public void Test4154525() { + final int GOOD = 1, BAD = 0; + int[] DATA = { + 1, GOOD, + 0, BAD, + -1, BAD, + 60*60*1000, GOOD, + Integer.MIN_VALUE, BAD, + // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time + }; + for (int i=0; i) should work but throws " + ex) + : ", ) should fail but doesn't")); + } + + ex = null; + try { + SimpleTimeZone temp = new SimpleTimeZone(0, "Z", + GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME, + month, day, dayOfWeek, time); + } catch (IllegalArgumentException e) { + ex = e; + } + if ((ex == null) != shouldBeGood) { + errln("SimpleTimeZone(, month=" + month + ", day=" + day + + ", dayOfWeek=" + dayOfWeek + ", time=" + time + + (shouldBeGood ? (") should work but throws " + ex) + : ") should fail but doesn't")); + } + } + } + + /** + * SimpleTimeZone.getOffset accepts illegal arguments. + */ + public void Test4154650() { + final int GOOD=1, BAD=0; + final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST; + final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000; + int[] DATA = { + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0, + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000, + }; + + TimeZone tz = TimeZone.getDefault(); + for (int i=0; i " + zone[i]); + d = new Date(d.getTime() + ONE_HOUR); + } + if (zone[0].equals(zone[1]) && + (zone[1].equals(zone[2]) != transitionExpected) && + zone[2].equals(zone[3])) { + logln("Ok: transition " + transitionExpected); + } else { + errln("Fail: boundary transition incorrect"); + } + } + + // restore the initial time zone so that this test case + // doesn't affect the others. + TimeZone.setDefault(initialZone); + } + + /** + * TimeZone broken in last hour of year + */ + public void Test4173604() { + SimpleTimeZone pst = (SimpleTimeZone)TimeZone.getTimeZone("PST"); + int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000); + int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000); + int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0); + if (o22 != o23 || o22 != o00) { + errln("Offsets should be the same (for PST), but got: " + + "12/31 22:00 " + o22 + + ", 12/31 23:00 " + o23 + + ", 01/01 00:00 " + o00); + } + + GregorianCalendar cal = new GregorianCalendar(); + cal.setTimeZone(pst); + cal.clear(); + cal.set(1998, Calendar.JANUARY, 1); + int lastDST = cal.get(Calendar.DST_OFFSET); + int transitions = 0; + int delta = 5; + while (cal.get(Calendar.YEAR) < 2000) { + cal.add(Calendar.MINUTE, delta); + if (cal.get(Calendar.DST_OFFSET) != lastDST) { + ++transitions; + Calendar t = (Calendar)cal.clone(); + t.add(Calendar.MINUTE, -delta); + logln(t.getTime() + " " + t.get(Calendar.DST_OFFSET)); + logln(cal.getTime() + " " + (lastDST=cal.get(Calendar.DST_OFFSET))); + } + } + if (transitions != 4) { + errln("Saw " + transitions + " transitions; should have seen 4"); + } + } + + /** + * getDisplayName doesn't work with unusual savings/offsets. + */ + public void Test4176686() { + // Construct a zone that does not observe DST but + // that does have a DST savings (which should be ignored). + int offset = 90 * 60000; // 1:30 + SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_"); + z1.setDSTSavings(45 * 60000); // 0:45 + + // Construct a zone that observes DST for the first 6 months. + SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_"); + z2.setDSTSavings(45 * 60000); // 0:45 + z2.setStartRule(Calendar.JANUARY, 1, 0); + z2.setEndRule(Calendar.JULY, 1, 0); + + // Also check DateFormat + DateFormat fmt1 = new SimpleDateFormat("z"); + fmt1.setTimeZone(z1); // Format uses standard zone + DateFormat fmt2 = new SimpleDateFormat("z"); + fmt2.setTimeZone(z2); // Format uses DST zone + Date dst = new Date(1970-1900, Calendar.FEBRUARY, 1); // Time in DST + Date std = new Date(1970-1900, Calendar.AUGUST, 1); // Time in standard + + // Description, Result, Expected Result + String[] DATA = { + "getDisplayName(false, SHORT)/std zone", + z1.getDisplayName(false, TimeZone.SHORT), "GMT+01:30", + "getDisplayName(false, LONG)/std zone", + z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30", + "getDisplayName(true, SHORT)/std zone", + z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30", + "getDisplayName(true, LONG)/std zone", + z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30", + "getDisplayName(false, SHORT)/dst zone", + z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30", + "getDisplayName(false, LONG)/dst zone", + z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30", + "getDisplayName(true, SHORT)/dst zone", + z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15", + "getDisplayName(true, LONG)/dst zone", + z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15", + "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30", + "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30", + "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30", + "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15", + }; + + for (int i=0; i " + DATA[i+1] + ", exp " + DATA[i+2]); + } + } + } + + /** + * SimpleTimeZone allows invalid DOM values. + */ + public void Test4184229() { + SimpleTimeZone zone = null; + try { + zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 startDay"); + } catch(IllegalArgumentException e) { + logln("(a) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 endDay"); + } catch(IllegalArgumentException e) { + logln("(b) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000); + errln("Failed. No exception has been thrown for DOM -1 startDay +savings"); + } catch(IllegalArgumentException e) { + logln("(c) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000); + errln("Failed. No exception has been thrown for DOM -1 endDay +savings"); + } catch(IllegalArgumentException e) { + logln("(d) " + e.getMessage()); + } + // Make a valid constructor call for subsequent tests. + zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0); + try { + zone.setStartRule(0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings"); + } catch(IllegalArgumentException e) { + logln("(e) " + e.getMessage()); + } + try { + zone.setStartRule(0, -1, 0); + errln("Failed. No exception has been thrown for DOM -1 setStartRule"); + } catch(IllegalArgumentException e) { + logln("(f) " + e.getMessage()); + } + try { + zone.setEndRule(0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings"); + } catch(IllegalArgumentException e) { + logln("(g) " + e.getMessage()); + } + try { + zone.setEndRule(0, -1, 0); + errln("Failed. No exception has been thrown for DOM -1 setEndRule"); + } catch(IllegalArgumentException e) { + logln("(h) " + e.getMessage()); + } + } + + /** + * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get + * of 2/29/1996 (leap day). + */ + public void Test4208960 () { + SimpleTimeZone tz = (SimpleTimeZone)TimeZone.getTimeZone("PST"); + try { + int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29, + Calendar.THURSDAY, 0); + } catch (IllegalArgumentException e) { + errln("FAILED: to get TimeZone.getOffset(2/29/96)"); + } + try { + int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29, + Calendar.THURSDAY, 0); + errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception."); + } catch (IllegalArgumentException e) { + logln("got IllegalArgumentException"); + } + } +} + +//eof diff --git a/icu4j/src/com/ibm/test/timezone/TimeZoneTest.java b/icu4j/src/com/ibm/test/timezone/TimeZoneTest.java new file mode 100755 index 0000000000..ec8662b4fc --- /dev/null +++ b/icu4j/src/com/ibm/test/timezone/TimeZoneTest.java @@ -0,0 +1,701 @@ +/** + * @test 1.22 99/09/21 + * @bug 4028006 4044013 4096694 4107276 4107570 4112869 4130885 + * @summary test TimeZone + * @build TimeZoneTest + */ + +package com.ibm.test.timezone; +import com.ibm.text.*; +import com.ibm.util.*; +import com.ibm.test.*; +import java.util.Date; +import java.util.Locale; +import java.util.Hashtable; +import java.util.ResourceBundle; + +public class TimeZoneTest extends TestFmwk +{ + static final int millisPerHour = 3600000; + + public static void main(String[] args) throws Exception { + new TimeZoneTest().run(args); + } + + /** + * Bug 4130885 + * Certain short zone IDs, used since 1.1.x, are incorrect. + * + * The worst of these is: + * + * "CAT" (Central African Time) should be GMT+2:00, but instead returns a + * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST, + * or AZOST, depending on which zone is meant, but in no case is it CAT. + * + * Other wrong zone IDs: + * + * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time, + * GMT-5:00. European Central time is abbreviated CEST. + * + * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time, + * GMT-11:00. Solomon Island time is SBT. + * + * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for + * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST. + * + * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in + * another bug.] It should be "AKST". AST is Atlantic Standard Time, + * GMT-4:00. + * + * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time, + * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct + * from MST with daylight savings. + * + * In addition to these problems, a number of zones are FAKE. That is, they + * don't match what people use in the real world. + * + * FAKE zones: + * + * EET (should be EEST) + * ART (should be EEST) + * MET (should be IRST) + * NET (should be AMST) + * PLT (should be PKT) + * BST (should be BDT) + * VST (should be ICT) + * CTT (should be CST) + + * ACT (should be CST) + + * AET (should be EST) + + * MIT (should be WST) + + * IET (should be EST) + + * PRT (should be AST) + + * CNT (should be NST) + * AGT (should be ARST) + * BET (should be EST) + + * + * + A zone with the correct name already exists and means something + * else. E.g., EST usually indicates the US Eastern zone, so it cannot be + * used for Brazil (BET). + */ + public void TestShortZoneIDs() throws Exception { + + ZoneDescriptor[] JDK_116_REFERENCE_LIST = { + new ZoneDescriptor("MIT", -660, false), + new ZoneDescriptor("HST", -600, false), + new ZoneDescriptor("AST", -540, true), + new ZoneDescriptor("PST", -480, true), + new ZoneDescriptor("PNT", -420, false), + new ZoneDescriptor("MST", -420, true), + new ZoneDescriptor("CST", -360, true), + new ZoneDescriptor("IET", -300, false), + new ZoneDescriptor("EST", -300, true), + new ZoneDescriptor("PRT", -240, false), + new ZoneDescriptor("CNT", -210, true), + new ZoneDescriptor("AGT", -180, false), + new ZoneDescriptor("BET", -180, true), + // new ZoneDescriptor("CAT", -60, false), // Wrong: + // As of bug 4130885, fix CAT (Central Africa) + new ZoneDescriptor("CAT", 120, false), // Africa/Harare + new ZoneDescriptor("GMT", 0, false), + new ZoneDescriptor("UTC", 0, false), + new ZoneDescriptor("ECT", 60, true), + new ZoneDescriptor("ART", 120, true), + new ZoneDescriptor("EET", 120, true), + new ZoneDescriptor("EAT", 180, false), + new ZoneDescriptor("MET", 210, true), + // new ZoneDescriptor("NET", 240, false); + // As of bug 4191164, fix NET + new ZoneDescriptor("NET", 240, true), + new ZoneDescriptor("PLT", 300, false), + new ZoneDescriptor("IST", 330, false), + new ZoneDescriptor("BST", 360, false), + new ZoneDescriptor("VST", 420, false), + new ZoneDescriptor("CTT", 480, false), + new ZoneDescriptor("JST", 540, false), + new ZoneDescriptor("ACT", 570, false), + new ZoneDescriptor("AET", 600, true), + new ZoneDescriptor("SST", 660, false), + // new ZoneDescriptor("NST", 720, false), + // As of bug 4130885, fix NST (New Zealand) + new ZoneDescriptor("NST", 720, true), // Pacific/Auckland + }; + + Hashtable hash = new Hashtable(); + + String[] ids = TimeZone.getAvailableIDs(); + for (int i=0; i i2.offset) return 1; + if (i1.offset < i2.offset) return -1; + if (i1.daylight && !i2.daylight) return 1; + if (!i1.daylight && i2.daylight) return -1; + return i1.id.compareTo(i2.id); + } + } + + static final String EXPECTED_CUSTOM_ID = "Custom"; + static final String formatMinutes(int min) { + char sign = '+'; + if (min < 0) { sign = '-'; min = -min; } + int h = min/60; + min = min%60; + return "" + sign + h + ":" + ((min<10) ? "0" : "") + min; + } + /** + * As part of the VM fix (see CCC approved RFE 4028006, bug + * 4044013), TimeZone.getTimeZone() has been modified to recognize + * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and + * GMT[+-]hh. Test this behavior here. + * + * Bug 4044013 + */ + public void TestCustomParse() throws Exception { + Object[] DATA = { + // ID Expected offset in minutes + "GMT", null, + "GMT0", null, + "GMT+0", new Integer(0), + "GMT+1", new Integer(60), + "GMT-0030", new Integer(-30), + "GMT+15:99", new Integer(15*60+99), + "GMT+", null, + "GMT-", null, + "GMT+0:", null, + "GMT-:", null, + "GMT+0010", new Integer(10), // Interpret this as 00:10 + "GMT-10", new Integer(-10*60), + "GMT+30", new Integer(30), + "GMT-3:30", new Integer(-(3*60+30)), + "GMT-230", new Integer(-(2*60+30)), + }; + for (int i=0; i generic GMT"); + // When TimeZone.getTimeZone() can't parse the id, it + // returns GMT -- a dubious practice, but required for + // backward compatibility. + if (exp != null) { + throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + + " for " + id + ", got parse failure"); + } + } + else { + int ioffset = zone.getRawOffset()/60000; + String offset = formatMinutes(ioffset); + logln(id + " -> " + zone.getID() + " GMT" + offset); + if (exp == null) { + throw new Exception("Expected parse failure for " + id + + ", got offset of " + offset + + ", id " + zone.getID()); + } + else if (ioffset != exp.intValue() || + !zone.getID().equals(EXPECTED_CUSTOM_ID)) { + throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + + ", id Custom, for " + id + + ", got offset of " + offset + + ", id " + zone.getID()); + } + } + } + } + + /** + * Test the basic functionality of the getDisplayName() API. + * + * Bug 4112869 + * Bug 4028006 + * + * See also API change request A41. + * + * 4/21/98 - make smarter, so the test works if the ext resources + * are present or not. + */ + public void TestDisplayName() { + TimeZone zone = TimeZone.getTimeZone("PST"); + String name = zone.getDisplayName(Locale.ENGLISH); + logln("PST->" + name); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected \"Pacific Standard Time\""); + + //***************************************************************** + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + //***************************************************************** + Object[] DATA = { + new Boolean(false), new Integer(TimeZone.SHORT), "PST", + new Boolean(true), new Integer(TimeZone.SHORT), "PDT", + new Boolean(false), new Integer(TimeZone.LONG), "Pacific Standard Time", + new Boolean(true), new Integer(TimeZone.LONG), "Pacific Daylight Time", + }; + + for (int i=0; i" + zone2.inDaylightTime(new Date())); + name = zone2.getDisplayName(Locale.ENGLISH); + logln("Modified PST->" + name); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected \"Pacific Standard Time\""); + + // Make sure we get the default display format for Locales + // with no display name data. + Locale zh_CN = Locale.SIMPLIFIED_CHINESE; + name = zone.getDisplayName(zh_CN); + //***************************************************************** + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + //***************************************************************** + logln("PST(zh_CN)->" + name); + + // Now be smart -- check to see if zh resource is even present. + // If not, we expect the en fallback behavior. + ResourceBundle enRB = ResourceBundle.getBundle("java.text.resources.DateFormatZoneData", + Locale.ENGLISH); + ResourceBundle zhRB = ResourceBundle.getBundle("java.text.resources.DateFormatZoneData", + zh_CN); + boolean noZH = enRB == zhRB; + + if (noZH) { + logln("Warning: Not testing the zh_CN behavior because resource is absent"); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected Pacific Standard Time"); + } + else if (!name.equals("Pacific Standard Time") && + !name.equals("GMT-08:00") && + !name.equals("GMT-8:00") && + !name.equals("GMT-0800") && + !name.equals("GMT-800")) { + errln("Fail: Expected GMT-08:00 or something similar"); + errln("************************************************************"); + errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED"); + errln("************************************************************"); + } + + // Now try a non-existent zone + zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); + name = zone2.getDisplayName(Locale.ENGLISH); + logln("GMT+90min->" + name); + if (!name.equals("GMT+01:30") && + !name.equals("GMT+1:30") && + !name.equals("GMT+0130") && + !name.equals("GMT+130")) + errln("Fail: Expected GMT+01:30 or something similar"); + } + + public void TestGenericAPI() { + String id = "NewGMT"; + int offset = 12345; + + SimpleTimeZone zone = new SimpleTimeZone(offset, id); + if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); + + TimeZone zoneclone = (TimeZone)zone.clone(); + if (!zoneclone.equals(zone)) errln("FAIL: clone or operator== failed"); + zoneclone.setID("abc"); + if (zoneclone.equals(zone)) errln("FAIL: clone or operator!= failed"); + // delete zoneclone; + + zoneclone = (TimeZone)zone.clone(); + if (!zoneclone.equals(zone)) errln("FAIL: clone or operator== failed"); + zoneclone.setRawOffset(45678); + if (zoneclone.equals(zone)) errln("FAIL: clone or operator!= failed"); + + // C++ only + /* + SimpleTimeZone copy(*zone); + if (!(copy == *zone)) errln("FAIL: copy constructor or operator== failed"); + copy = *(SimpleTimeZone*)zoneclone; + if (!(copy == *zoneclone)) errln("FAIL: assignment operator or operator== failed"); + */ + + TimeZone saveDefault = TimeZone.getDefault(); + TimeZone.setDefault(zone); + TimeZone defaultzone = TimeZone.getDefault(); + if (defaultzone == zone) errln("FAIL: Default object is identical, not clone"); + if (!defaultzone.equals(zone)) errln("FAIL: Default object is not equal"); + TimeZone.setDefault(saveDefault); + // delete defaultzone; + // delete zoneclone; + } + + public void TestRuleAPI() + { + // ErrorCode status = ZERO_ERROR; + + int offset = (int)(60*60*1000*1.75); // Pick a weird offset + SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone"); + if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); + + // Establish our expected transition times. Do this with a non-DST + // calendar with the (above) declared local offset. + GregorianCalendar gc = new GregorianCalendar(zone); + gc.clear(); + gc.set(1990, Calendar.MARCH, 1); + long marchOneStd = gc.getTime().getTime(); // Local Std time midnight + gc.clear(); + gc.set(1990, Calendar.JULY, 1); + long julyOneStd = gc.getTime().getTime(); // Local Std time midnight + + // Starting and ending hours, WALL TIME + int startHour = (int)(2.25 * 3600000); + int endHour = (int)(3.5 * 3600000); + + zone.setStartRule(Calendar.MARCH, 1, 0, startHour); + zone.setEndRule (Calendar.JULY, 1, 0, endHour); + + gc = new GregorianCalendar(zone); + // if (failure(status, "new GregorianCalendar")) return; + + long marchOne = marchOneStd + startHour; + long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time + + long expMarchOne = 636251400000L; + if (marchOne != expMarchOne) + { + errln("FAIL: Expected start computed as " + marchOne + + " = " + new Date(marchOne)); + logln(" Should be " + expMarchOne + + " = " + new Date(expMarchOne)); + } + + long expJulyOne = 646793100000L; + if (julyOne != expJulyOne) + { + errln("FAIL: Expected start computed as " + julyOne + + " = " + new Date(julyOne)); + logln(" Should be " + expJulyOne + + " = " + new Date(expJulyOne)); + } + + _testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(), + new Date(90, Calendar.JUNE, 15).getTime(), marchOne); + _testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(), + new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne); + + if (zone.inDaylightTime(new Date(marchOne - 1000)) || + !zone.inDaylightTime(new Date(marchOne))) + errln("FAIL: Start rule broken"); + if (!zone.inDaylightTime(new Date(julyOne - 1000)) || + zone.inDaylightTime(new Date(julyOne))) + errln("FAIL: End rule broken"); + + zone.setStartYear(1991); + if (zone.inDaylightTime(new Date(marchOne)) || + zone.inDaylightTime(new Date(julyOne - 1000))) + errln("FAIL: Start year broken"); + + // failure(status, "TestRuleAPI"); + // delete gc; + // delete zone; + } + + void _testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary) + { + // ErrorCode status = ZERO_ERROR; + boolean startsInDST = tz.inDaylightTime(new Date(min)); + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + if (tz.inDaylightTime(new Date(max)) == startsInDST) { + logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST)); + return; + } + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + while ((max - min) > INTERVAL) { + long mid = (min + max) / 2; + if (tz.inDaylightTime(new Date(mid)) == startsInDST) { + min = mid; + } + else { + max = mid; + } + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + } + logln("Binary Search Before: " + min + " = " + new Date(min)); + logln("Binary Search After: " + max + " = " + new Date(max)); + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && + mindelta <= INTERVAL && + mindelta >= 0 && + mindelta <= INTERVAL) + logln("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); + else + errln("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); + } + + static final int INTERVAL = 100; + + // Bug 006; verify the offset for a specific zone. + public void TestPRTOffset() + { + TimeZone tz = TimeZone.getTimeZone( "PRT" ); + if( tz == null ) { + errln( "FAIL: TimeZone(PRT) is null" ); + } + else{ + if (tz.getRawOffset() != (-4*millisPerHour)) + errln("FAIL: Offset for PRT should be -4"); + } + + } + + // Test various calls + public void TestVariousAPI518() + { + TimeZone time_zone = TimeZone.getTimeZone("PST"); + Date d = new Date(97, Calendar.APRIL, 30); + + logln("The timezone is " + time_zone.getID()); + + if (time_zone.inDaylightTime(d) != true) + errln("FAIL: inDaylightTime returned false"); + + if (time_zone.useDaylightTime() != true) + errln("FAIL: useDaylightTime returned false"); + + if (time_zone.getRawOffset() != -8*millisPerHour) + errln( "FAIL: getRawOffset returned wrong value"); + + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(d); + if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH), + gc.get(gc.DAY_OF_MONTH), + gc.get(gc.DAY_OF_WEEK), 0) + != -7*millisPerHour) + errln("FAIL: getOffset returned wrong value"); + } + + // Test getAvailableID API + public void TestGetAvailableIDs913() + { + StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { "); + String[] s = TimeZone.getAvailableIDs(); + for (int i=0; i 0) buf.append(", "); + buf.append(s[i]); + } + buf.append(" };"); + logln(buf.toString()); + + buf.setLength(0); + buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { "); + s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000); + for (int i=0; i 0) buf.append(", "); + buf.append(s[i]); + } + buf.append(" };"); + logln(buf.toString()); + + TimeZone tz = TimeZone.getTimeZone("PST"); + if (tz != null) + logln("getTimeZone(PST) = " + tz.getID()); + else + errln("FAIL: getTimeZone(PST) = null"); + + tz = TimeZone.getTimeZone("America/Los_Angeles"); + if (tz != null) + logln("getTimeZone(America/Los_Angeles) = " + tz.getID()); + else + errln("FAIL: getTimeZone(PST) = null"); + + // Bug 4096694 + tz = TimeZone.getTimeZone("NON_EXISTENT"); + if (tz == null) + errln("FAIL: getTimeZone(NON_EXISTENT) = null"); + else if (!tz.getID().equals("GMT")) + errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID()); + } + + /** + * Bug 4107276 + */ + public void TestDSTSavings() { + // It might be better to find a way to integrate this test into the main TimeZone + // tests above, but I don't have time to figure out how to do this (or if it's + // even really a good idea). Let's consider that a future. --rtg 1/27/98 + SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest", + Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0, + (int)(0.5 * millisPerHour)); + + if (tz.getRawOffset() != -5 * millisPerHour) + errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) + + " hours instead of -5 hours."); + if (!tz.useDaylightTime()) + errln("Test time zone should use DST but claims it doesn't."); + if (tz.getDSTSavings() != 0.5 * millisPerHour) + errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() / + millisPerHour) + " hours instead."); + + int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, + 10 * millisPerHour); + if (offset != -4.5 * millisPerHour) + errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + tz.setDSTSavings(millisPerHour); + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, + 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + } + + /** + * Bug 4107570 + */ + public void TestAlternateRules() { + // Like TestDSTSavings, this test should probably be integrated somehow with the main + // test at the top of this class, but I didn't have time to figure out how to do that. + // --rtg 1/28/98 + + SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest"); + + // test the day-of-month API + tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour); + tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour); + + int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15, + Calendar.SUNDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25, + Calendar.SUNDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + // test the day-of-week-after-day-in-month API + tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true); + tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11, + Calendar.WEDNESDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14, + Calendar.SATURDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17, + Calendar.SATURDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + } +} + +//eof diff --git a/icu4j/src/com/ibm/text/DateFormat.java b/icu4j/src/com/ibm/text/DateFormat.java index 99c46be454..44d545a58b 100755 --- a/icu4j/src/com/ibm/text/DateFormat.java +++ b/icu4j/src/com/ibm/text/DateFormat.java @@ -37,7 +37,7 @@ import java.text.NumberFormat; import java.util.Locale; import java.util.ResourceBundle; import java.util.MissingResourceException; -import java.util.TimeZone; +import com.ibm.util.TimeZone; import com.ibm.util.Calendar; import com.ibm.util.GregorianCalendar; import java.util.Date; @@ -118,9 +118,9 @@ import java.text.resources.*; * @see Format * @see NumberFormat * @see SimpleDateFormat - * @see java.util.Calendar - * @see java.util.GregorianCalendar - * @see java.util.TimeZone + * @see com.ibm.util.Calendar + * @see com.ibm.util.GregorianCalendar + * @see com.ibm.util.TimeZone * @version 1.37 11/02/99 * @author Mark Davis, Chen-Lieh Huang, Alan Liu */ @@ -582,7 +582,7 @@ public abstract class DateFormat extends Format { * do not precisely match this object's format. With strict parsing, * inputs must match this object's format. * @param lenient when true, parsing is lenient - * @see java.util.Calendar#setLenient + * @see com.ibm.util.Calendar#setLenient */ public void setLenient(boolean lenient) { diff --git a/icu4j/src/com/ibm/text/DateFormatSymbols.java b/icu4j/src/com/ibm/text/DateFormatSymbols.java index bbb0a3016c..bf15ade60a 100755 --- a/icu4j/src/com/ibm/text/DateFormatSymbols.java +++ b/icu4j/src/com/ibm/text/DateFormatSymbols.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/text/Attic/DateFormatSymbols.java,v $ - * $Date: 2000/04/27 22:41:39 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:19:35 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -64,7 +64,7 @@ import com.ibm.util.Utility; * @see DateFormat * @see SimpleDateFormat - * @see java.util.SimpleTimeZone + * @see com.ibm.util.SimpleTimeZone * @version 1.31 09/21/99 * @author Chen-Lieh Huang */ @@ -169,7 +169,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { * are localized names. If a zone does not implement daylight savings * time, the daylight savings time names are ignored. * @see java.text.resources.DateFormatZoneData - * @see java.util.TimeZone + * @see com.ibm.util.TimeZone * @serial */ String zoneStrings[][] = null; @@ -505,7 +505,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { * @param ID the given time zone ID. * @return the index of the given time zone ID. Returns -1 if * the given time zone ID can't be located in the DateFormatSymbols object. - * @see java.util.SimpleTimeZone + * @see com.ibm.util.SimpleTimeZone */ final int getZoneIndex (String ID) { diff --git a/icu4j/src/com/ibm/text/SimpleDateFormat.java b/icu4j/src/com/ibm/text/SimpleDateFormat.java index 04f3f33f39..a7f94f0be0 100755 --- a/icu4j/src/com/ibm/text/SimpleDateFormat.java +++ b/icu4j/src/com/ibm/text/SimpleDateFormat.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/text/Attic/SimpleDateFormat.java,v $ - * $Date: 2000/04/27 22:41:39 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:19:35 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -20,12 +20,12 @@ import java.text.NumberFormat; import java.text.FieldPosition; import java.text.ParsePosition; -import java.util.TimeZone; +import com.ibm.util.TimeZone; import com.ibm.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.ResourceBundle; -import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; import com.ibm.util.GregorianCalendar; import java.io.ObjectInputStream; import java.io.IOException; @@ -170,9 +170,9 @@ import java.lang.StringIndexOutOfBoundsException; * time zone. There is one common decimal format to handle all the numbers; * the digit count is handled programmatically according to the pattern. * - * @see java.util.Calendar - * @see java.util.GregorianCalendar - * @see java.util.TimeZone + * @see com.ibm.util.Calendar + * @see com.ibm.util.GregorianCalendar + * @see com.ibm.util.TimeZone * @see DateFormat * @see DateFormatSymbols * @see DecimalFormat diff --git a/icu4j/src/com/ibm/util/BuddhistCalendar.java b/icu4j/src/com/ibm/util/BuddhistCalendar.java index e2f03e8bc6..c91fc35279 100755 --- a/icu4j/src/com/ibm/util/BuddhistCalendar.java +++ b/icu4j/src/com/ibm/util/BuddhistCalendar.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/util/Attic/BuddhistCalendar.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ @@ -16,7 +16,6 @@ package com.ibm.util; import java.util.Date; import com.ibm.util.GregorianCalendar; import java.util.Locale; -import java.util.TimeZone; /** * BuddhistCalendar is a subclass of GregorianCalendar @@ -33,7 +32,7 @@ import java.util.TimeZone; * calendar is not in lenient mode (see setLenient), dates before * 1/1/1 BE are rejected with an IllegalArgumentException. * - * @see java.util.GregorianCalendar + * @see com.ibm.util.GregorianCalendar * * @author Laura Werner */ @@ -49,7 +48,7 @@ public class BuddhistCalendar extends GregorianCalendar { * Constant for the Buddhist Era. This is the only allowable ERA * value for the Buddhist calendar. * - * @see java.util.Calendar#ERA + * @see com.ibm.util.Calendar#ERA */ public static final int BE = 0; diff --git a/icu4j/src/com/ibm/util/Calendar.java b/icu4j/src/com/ibm/util/Calendar.java index 2994d442b1..2cbe725516 100755 --- a/icu4j/src/com/ibm/util/Calendar.java +++ b/icu4j/src/com/ibm/util/Calendar.java @@ -33,7 +33,6 @@ import java.util.Date; import java.util.Hashtable; import java.util.Locale; import java.util.ResourceBundle; -import java.util.TimeZone; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; diff --git a/icu4j/src/com/ibm/util/EasterHoliday.java b/icu4j/src/com/ibm/util/EasterHoliday.java index 8d9cf3c8cb..06fc639f82 100755 --- a/icu4j/src/com/ibm/util/EasterHoliday.java +++ b/icu4j/src/com/ibm/util/EasterHoliday.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/util/Attic/EasterHoliday.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -16,7 +16,7 @@ package com.ibm.util; import java.util.Date; import com.ibm.util.GregorianCalendar; import com.ibm.util.Calendar; -import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; /** * A Holiday subclass which represents holidays that occur diff --git a/icu4j/src/com/ibm/util/GregorianCalendar.java b/icu4j/src/com/ibm/util/GregorianCalendar.java index f1e00ea6f3..3cd09d5330 100755 --- a/icu4j/src/com/ibm/util/GregorianCalendar.java +++ b/icu4j/src/com/ibm/util/GregorianCalendar.java @@ -31,7 +31,6 @@ package com.ibm.util; import java.util.Date; import java.util.Locale; -import java.util.TimeZone; /** * GregorianCalendar is a concrete subclass of @@ -1184,8 +1183,9 @@ public class GregorianCalendar extends Calendar { // getOffset(..., monthLen). This makes some zones behave incorrectly. // Fix this later, if desired, by porting TimeZone and STZ to this pkg. // -Alan - int dstOffset = getTimeZone().getOffset(era,year,month,date,dayOfWeek,millisInDay /*, - monthLength(month), prevMonthLength(month)*/) + // [icu4j fixed after 'port' of tz&stz to com.ibm.util - liu] + int dstOffset = getTimeZone().getOffset(era,year,month,date,dayOfWeek,millisInDay, + monthLength(month), prevMonthLength(month)) - rawOffset; // Adjust our millisInDay for DST, if necessary. @@ -1525,14 +1525,15 @@ public class GregorianCalendar extends Calendar { // getOffset(..., millis). This makes some zones behave incorrectly. // Fix this later, if desired, by porting TimeZone and STZ to this pkg. // -Alan + // [icu4j fixed after 'port' of tz&stz to com.ibm.util - liu] dstOffset = zone.getOffset(era, internalGet(YEAR), internalGet(MONTH), internalGet(DATE), dow, - normalizedMillisInDay[0] /*, + normalizedMillisInDay[0], monthLength(internalGet(MONTH)), - prevMonthLength(internalGet(MONTH)) */) - + prevMonthLength(internalGet(MONTH))) - zoneOffset; // Note: Because we pass in wall millisInDay, rather than // standard millisInDay, we interpret "1:00 am" on the day diff --git a/icu4j/src/com/ibm/util/HebrewCalendar.java b/icu4j/src/com/ibm/util/HebrewCalendar.java index 06c6f4950a..6cb20f59ce 100755 --- a/icu4j/src/com/ibm/util/HebrewCalendar.java +++ b/icu4j/src/com/ibm/util/HebrewCalendar.java @@ -5,17 +5,15 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/util/Attic/HebrewCalendar.java,v $ - * $Date: 2000/03/10 04:17:58 $ - * $Revision: 1.2 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.3 $ * ***************************************************************************************** */ package com.ibm.util; import java.util.Date; -import java.util.GregorianCalendar; import java.util.Locale; -import java.util.TimeZone; /** * HebrewCalendar is a subclass of Calendar @@ -63,7 +61,7 @@ import java.util.TimeZone; * http://www.pip.dknet.dk/~pip10160/calendar.html * *

- * @see java.util.GregorianCalendar + * @see com.ibm.util.GregorianCalendar * * @author Laura Werner */ @@ -352,7 +350,7 @@ public class HebrewCalendar extends IBMCalendar { * * @param field The field whose minimum value is desired. * - * @see java.util.Calendar#getMinimum + * @see com.ibm.util.Calendar#getMinimum */ public int getMinimum(int field) { @@ -570,7 +568,7 @@ public class HebrewCalendar extends IBMCalendar { //------------------------------------------------------------------------- // Functions for converting from field values to milliseconds and back... // - // These are overrides of abstract methods on java.util.Calendar + // These are overrides of abstract methods on com.ibm.util.Calendar //------------------------------------------------------------------------- /** @@ -1099,4 +1097,4 @@ public class HebrewCalendar extends IBMCalendar { System.out.println(str); } } -}; \ No newline at end of file +}; diff --git a/icu4j/src/com/ibm/util/IBMCalendar.java b/icu4j/src/com/ibm/util/IBMCalendar.java index 695e5ad856..bde5eabb0c 100755 --- a/icu4j/src/com/ibm/util/IBMCalendar.java +++ b/icu4j/src/com/ibm/util/IBMCalendar.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/util/Attic/IBMCalendar.java,v $ - * $Date: 2000/04/27 22:34:40 $ - * $Revision: 1.9 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.10 $ * ***************************************************************************************** */ @@ -18,7 +18,6 @@ import com.ibm.util.GregorianCalendar; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; -import java.util.TimeZone; import java.text.MessageFormat; import com.ibm.text.DateFormat; import com.ibm.text.DateFormatSymbols; diff --git a/icu4j/src/com/ibm/util/IslamicCalendar.java b/icu4j/src/com/ibm/util/IslamicCalendar.java index 030abc5f5c..cd80e704c2 100755 --- a/icu4j/src/com/ibm/util/IslamicCalendar.java +++ b/icu4j/src/com/ibm/util/IslamicCalendar.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/util/Attic/IslamicCalendar.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -16,7 +16,6 @@ import com.ibm.util.Calendar; import java.util.Date; import com.ibm.util.GregorianCalendar; import java.util.Locale; -import java.util.TimeZone; import com.ibm.util.CalendarAstronomer; /** @@ -69,7 +68,7 @@ import com.ibm.util.CalendarAstronomer; * fixed-cycle civil calendar is used. However, if setCivil(false) * is called, an approximation of the true lunar calendar will be used. * - * @see java.util.GregorianCalendar + * @see com.ibm.util.GregorianCalendar * * @author Laura Werner * @version 1.0 @@ -297,7 +296,7 @@ public class IslamicCalendar extends IBMCalendar { * * @param field The field whose minimum value is desired. * - * @see java.util.Calendar#getMinimum + * @see com.ibm.util.Calendar#getMinimum */ public int getMinimum(int field) { diff --git a/icu4j/src/com/ibm/util/JapaneseCalendar.java b/icu4j/src/com/ibm/util/JapaneseCalendar.java index 9cdb9ac0fa..24dd4c5c0a 100755 --- a/icu4j/src/com/ibm/util/JapaneseCalendar.java +++ b/icu4j/src/com/ibm/util/JapaneseCalendar.java @@ -5,18 +5,15 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/util/Attic/JapaneseCalendar.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.3 $ + * $Date: 2000/05/12 23:20:10 $ + * $Revision: 1.4 $ * ***************************************************************************************** */ package com.ibm.util; import java.util.Date; -import com.ibm.util.GregorianCalendar; import java.util.Locale; -import java.util.SimpleTimeZone; -import java.util.TimeZone; /** * JapaneseCalendar is a subclass of GregorianCalendar @@ -43,7 +40,7 @@ import java.util.TimeZone; * constants rather than using actual, absolute numbers. *

* - * @see java.util.GregorianCalendar + * @see com.ibm.util.GregorianCalendar * * @author Laura Werner */ diff --git a/icu4j/src/com/ibm/util/SimpleDateRule.java b/icu4j/src/com/ibm/util/SimpleDateRule.java index 43e8d6582b..c1c47dc72d 100755 --- a/icu4j/src/com/ibm/util/SimpleDateRule.java +++ b/icu4j/src/com/ibm/util/SimpleDateRule.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/util/Attic/SimpleDateRule.java,v $ - * $Date: 2000/03/21 02:19:32 $ - * $Revision: 1.4 $ + * $Date: 2000/05/12 23:20:11 $ + * $Revision: 1.5 $ * ***************************************************************************************** */ @@ -16,7 +16,7 @@ package com.ibm.util; import java.util.Date; import com.ibm.util.Calendar; import com.ibm.util.GregorianCalendar; -import java.util.SimpleTimeZone; +import com.ibm.util.SimpleTimeZone; public class SimpleDateRule implements DateRule { diff --git a/icu4j/src/com/ibm/util/SimpleTimeZone.java b/icu4j/src/com/ibm/util/SimpleTimeZone.java new file mode 100755 index 0000000000..ef07b2e3b1 --- /dev/null +++ b/icu4j/src/com/ibm/util/SimpleTimeZone.java @@ -0,0 +1,1461 @@ +/* + * @(#)SimpleTimeZone.java 1.38 00/01/19 + * + * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved. + * + * This software is the proprietary information of Sun Microsystems, Inc. + * Use is subject to license terms. + * + */ + +/* + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - All Rights Reserved + * + * The original version of this source code and documentation is copyrighted + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These + * materials are provided under terms of a License Agreement between Taligent + * and Sun. This technology is protected by multiple US and International + * patents. This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + */ + +package com.ibm.util; + +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.IOException; +import java.util.Date; + +/** + * SimpleTimeZone is a concrete subclass of TimeZone + * that represents a time zone for use with a Gregorian calendar. This + * class does not handle historical changes. + * + *

+ * Use a negative value for dayOfWeekInMonth to indicate that + * SimpleTimeZone should count from the end of the month backwards. + * For example, Daylight Savings Time ends at the last + * (dayOfWeekInMonth = -1) Sunday in October, at 2 AM in standard time. + * + * @see Calendar + * @see GregorianCalendar + * @see TimeZone + * @version 1.38 01/19/00 + * @author David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu + */ +public class SimpleTimeZone extends TimeZone { + /** + * Constructs a SimpleTimeZone with the given base time zone offset from GMT + * and time zone ID. Timezone IDs can be obtained from + * TimeZone.getAvailableIDs. Normally you should use TimeZone.getDefault to + * construct a TimeZone. + * + * @param rawOffset The given base time zone offset to GMT. + * @param ID The time zone ID which is obtained from + * TimeZone.getAvailableIDs. + */ + public SimpleTimeZone(int rawOffset, String ID) + { + this.rawOffset = rawOffset; + setID (ID); + dstSavings = millisPerHour; // In case user sets rules later + } + + /** + * Construct a SimpleTimeZone with the given base time zone offset from + * GMT, time zone ID, time to start and end the daylight time. Timezone IDs + * can be obtained from TimeZone.getAvailableIDs. Normally you should use + * TimeZone.getDefault to create a TimeZone. For a time zone that does not + * use daylight saving time, do not use this constructor; instead you should + * use SimpleTimeZone(rawOffset, ID). + * + * By default, this constructor specifies day-of-week-in-month rules. That + * is, if the startDay is 1, and the startDayOfWeek is SUNDAY, then this + * indicates the first Sunday in the startMonth. A startDay of -1 likewise + * indicates the last Sunday. However, by using negative or zero values for + * certain parameters, other types of rules can be specified. + * + * Day of month. To specify an exact day of the month, such as March 1, set + * startDayOfWeek to zero. + * + * Day of week after day of month. To specify the first day of the week + * occurring on or after an exact day of the month, make the day of the week + * negative. For example, if startDay is 5 and startDayOfWeek is -MONDAY, + * this indicates the first Monday on or after the 5th day of the + * startMonth. + * + * Day of week before day of month. To specify the last day of the week + * occurring on or before an exact day of the month, make the day of the + * week and the day of the month negative. For example, if startDay is -21 + * and startDayOfWeek is -WEDNESDAY, this indicates the last Wednesday on or + * before the 21st of the startMonth. + * + * The above examples refer to the startMonth, startDay, and startDayOfWeek; + * the same applies for the endMonth, endDay, and endDayOfWeek. + * + * @param rawOffset The given base time zone offset to GMT. + * @param ID The time zone ID which is obtained from + * TimeZone.getAvailableIDs. + * @param startMonth The daylight savings starting month. Month is + * 0-based. eg, 0 for January. + * @param startDay The daylight savings starting + * day-of-week-in-month. Please see the member + * description for an example. + * @param startDayOfWeek The daylight savings starting day-of-week. Please + * see the member description for an example. + * @param startTime The daylight savings starting time in local wall + * time, which is standard time in this case. Please see the + * member description for an example. + * @param endMonth The daylight savings ending month. Month is + * 0-based. eg, 0 for January. + * @param endDay The daylight savings ending day-of-week-in-month. + * Please see the member description for an example. + * @param endDayOfWeek The daylight savings ending day-of-week. Please + * see the member description for an example. + * @param endTime The daylight savings ending time in local wall time, + * which is daylight time in this case. Please see the + * member description for an example. + * @exception IllegalArgumentException the month, day, dayOfWeek, or time + * parameters are out of range for the start or end rule + * @since JDK1.1 + */ + public SimpleTimeZone(int rawOffset, String ID, + int startMonth, int startDay, int startDayOfWeek, int startTime, + int endMonth, int endDay, int endDayOfWeek, int endTime) + { + this(rawOffset, ID, + startMonth, startDay, startDayOfWeek, startTime, WALL_TIME, + endMonth, endDay, endDayOfWeek, endTime, WALL_TIME, + millisPerHour); + } + + /** + * Constructor. This constructor is identical to the 10-argument + * constructor, but also takes a dstSavings parameter. + * @param dstSavings The amount of time in ms saved during DST. + * @exception IllegalArgumentException the month, day, dayOfWeek, or time + * parameters are out of range for the start or end rule + * @since 1.2 + */ + public SimpleTimeZone(int rawOffset, String ID, + int startMonth, int startDay, int startDayOfWeek, int startTime, + int endMonth, int endDay, int endDayOfWeek, int endTime, + int dstSavings) + { + this(rawOffset, ID, + startMonth, startDay, startDayOfWeek, startTime, WALL_TIME, + endMonth, endDay, endDayOfWeek, endTime, WALL_TIME, + dstSavings); + } + + /** + * Constructor. + */ + SimpleTimeZone(int rawOffset, String ID, + int startMonth, int startDay, int startDayOfWeek, + int startTime, int startTimeMode, + int endMonth, int endDay, int endDayOfWeek, + int endTime, int endTimeMode, + int dstSavings) { + setID(ID); + this.rawOffset = rawOffset; + this.startMonth = startMonth; + this.startDay = startDay; + this.startDayOfWeek = startDayOfWeek; + this.startTime = startTime; + this.startTimeMode = startTimeMode; + this.endMonth = endMonth; + this.endDay = endDay; + this.endDayOfWeek = endDayOfWeek; + this.endTime = endTime; + this.endTimeMode = endTimeMode; + this.dstSavings = dstSavings; + // this.useDaylight = true; // Set by decodeRules + decodeRules(); + if (dstSavings <= 0) { + throw new IllegalArgumentException("Illegal DST savings"); + } + } + + /** + * Sets the daylight savings starting year. + * + * @param year The daylight savings starting year. + */ + public void setStartYear(int year) + { + startYear = year; + } + + /** + * Sets the daylight savings starting rule. For example, Daylight Savings + * Time starts at the first Sunday in April, at 2 AM in standard time. + * Therefore, you can set the start rule by calling: + * setStartRule(TimeFields.APRIL, 1, TimeFields.SUNDAY, 2*60*60*1000); + * + * @param month The daylight savings starting month. Month is + * 0-based. eg, 0 for January. + * @param dayOfWeekInMonth The daylight savings starting + * day-of-week-in-month. Please see the member + * description for an example. + * @param dayOfWeek The daylight savings starting day-of-week. + * Please see the member description for an + * example. + * @param time The daylight savings starting time in local wall + * time, which is standard time in this case. Please see + * the member description for an example. + * @exception IllegalArgumentException the month, dayOfWeekInMonth, + * dayOfWeek, or time parameters are out of range + */ + public void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, + int time) + { + startMonth = month; + startDay = dayOfWeekInMonth; + startDayOfWeek = dayOfWeek; + startTime = time; + startTimeMode = WALL_TIME; + // useDaylight = true; // Set by decodeRules + decodeStartRule(); + } + + /** + * Sets the DST start rule to a fixed date within a month. + * + * @param month The month in which this rule occurs (0-based). + * @param dayOfMonth The date in that month (1-based). + * @param time The time of that day (number of millis after midnight) + * when DST takes effect in local wall time, which is + * standard time in this case. + * @exception IllegalArgumentException the month, + * dayOfMonth, or time parameters are out of range + * @since 1.2 + */ + public void setStartRule(int month, int dayOfMonth, int time) { + setStartRule(month, dayOfMonth, 0, time); + } + + /** + * Sets the DST start rule to a weekday before or after a give date within + * a month, e.g., the first Monday on or after the 8th. + * + * @param month The month in which this rule occurs (0-based). + * @param dayOfMonth A date within that month (1-based). + * @param dayOfWeek The day of the week on which this rule occurs. + * @param time The time of that day (number of millis after midnight) + * when DST takes effect in local wall time, which is + * standard time in this case. + * @param after If true, this rule selects the first dayOfWeek on + * or after dayOfMonth. If false, this rule selects + * the last dayOfWeek on or before dayOfMonth. + * @exception IllegalArgumentException the month, dayOfMonth, + * dayOfWeek, or time parameters are out of range + * @since 1.2 + */ + public void setStartRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) + { + if (after) + setStartRule(month, dayOfMonth, -dayOfWeek, time); + else + setStartRule(month, -dayOfMonth, -dayOfWeek, time); + } + + /** + * Sets the daylight savings ending rule. For example, Daylight Savings Time + * ends at the last (-1) Sunday in October, at 2 AM in standard time. + * Therefore, you can set the end rule by calling: + * setEndRule(TimeFields.OCTOBER, -1, TimeFields.SUNDAY, 2*60*60*1000); + * + * @param month The daylight savings ending month. Month is + * 0-based. eg, 0 for January. + * @param dayOfWeekInMonth The daylight savings ending + * day-of-week-in-month. Please see the member + * description for an example. + * @param dayOfWeek The daylight savings ending day-of-week. Please + * see the member description for an example. + * @param time The daylight savings ending time in local wall time, + * which is daylight time in this case. Please see the + * member description for an example. + * @exception IllegalArgumentException the month, dayOfWeekInMonth, + * dayOfWeek, or time parameters are out of range + */ + public void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, + int time) + { + endMonth = month; + endDay = dayOfWeekInMonth; + endDayOfWeek = dayOfWeek; + endTime = time; + endTimeMode = WALL_TIME; + // useDaylight = true; // Set by decodeRules + decodeEndRule(); + } + + /** + * Sets the DST end rule to a fixed date within a month. + * + * @param month The month in which this rule occurs (0-based). + * @param dayOfMonth The date in that month (1-based). + * @param time The time of that day (number of millis after midnight) + * when DST ends in local wall time, which is daylight + * time in this case. + * @exception IllegalArgumentException the month, + * dayOfMonth, or time parameters are out of range + * @since 1.2 + */ + public void setEndRule(int month, int dayOfMonth, int time) + { + setEndRule(month, dayOfMonth, 0, time); + } + + /** + * Sets the DST end rule to a weekday before or after a give date within + * a month, e.g., the first Monday on or after the 8th. + * + * @param month The month in which this rule occurs (0-based). + * @param dayOfMonth A date within that month (1-based). + * @param dayOfWeek The day of the week on which this rule occurs. + * @param time The time of that day (number of millis after midnight) + * when DST ends in local wall time, which is daylight + * time in this case. + * @param after If true, this rule selects the first dayOfWeek on + * or after dayOfMonth. If false, this rule selects + * the last dayOfWeek on or before dayOfMonth. + * @exception IllegalArgumentException the month, dayOfMonth, + * dayOfWeek, or time parameters are out of range + * @since 1.2 + */ + public void setEndRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) + { + if (after) + setEndRule(month, dayOfMonth, -dayOfWeek, time); + else + setEndRule(month, -dayOfMonth, -dayOfWeek, time); + } + + /** + * Returns the difference in milliseconds between local time and + * UTC, taking into account both the raw offset and the effect of + * daylight savings, for the specified date and time. This method + * assumes that the start and end month are distinct. It also + * uses a default {@link GregorianCalendar} object as its + * underlying calendar, such as for determining leap years. Do + * not use the result of this method with a calendar other than a + * default GregorianCalendar. + * + *

Note: In general, clients should use + * Calendar.get(ZONE_OFFSET) + Calendar.get(DST_OFFSET) + * instead of calling this method. + * + * @param era The era of the given date. + * @param year The year in the given date. + * @param month The month in the given date. Month is 0-based. e.g., + * 0 for January. + * @param day The day-in-month of the given date. + * @param dayOfWeek The day-of-week of the given date. + * @param millis The milliseconds in day in standard local time. + * @return The milliseconds to add to UTC to get local time. + * @exception IllegalArgumentException the era, month, day, + * dayOfWeek, or millis parameters are out of range + */ + public int getOffset(int era, int year, int month, int day, int dayOfWeek, + int millis) + { + // Check the month before indexing into staticMonthLength. This + // duplicates the test that occurs in the 7-argument getOffset(), + // however, this is unavoidable. We don't mind because this method, in + // fact, should not be called; internal code should always call the + // 7-argument getOffset(), and outside code should use Calendar.get(int + // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of + // this method because it's public API. - liu 8/10/98 + if (month < Calendar.JANUARY + || month > Calendar.DECEMBER) { + throw new IllegalArgumentException("Illegal month " + month); + } + int monthLength, prevMonthLength; + if ((era == GregorianCalendar.AD) && internalCal.isLeapYear(year)) { + monthLength = staticLeapMonthLength[month]; + prevMonthLength = (month > 1) ? staticLeapMonthLength[month - 1] : 31; + } else { + monthLength = staticMonthLength[month]; + prevMonthLength = (month > 1) ? staticMonthLength[month - 1] : 31; + } + + return getOffset(era, year, month, day, dayOfWeek, millis, + monthLength, prevMonthLength); + } + + /** + * Gets offset, for current date, modified in case of + * daylight savings. This is the offset to add to UTC to get local time. + * Gets the time zone offset, for current date, modified in case of daylight + * savings. This is the offset to add *to* UTC to get local time. Assume + * that the start and end month are distinct. + * @param era The era of the given date. + * @param year The year in the given date. + * @param month The month in the given date. Month is 0-based. e.g., + * 0 for January. + * @param day The day-in-month of the given date. + * @param dayOfWeek The day-of-week of the given date. + * @param millis The milliseconds in day in standard local time. + * @param monthLength The length of the given month in days. + * @param prevMonthLength The length of the previous month in days. + * @return The offset to add *to* GMT to get local time. + * @exception IllegalArgumentException the era, month, day, + * dayOfWeek, millis, or monthLength parameters are out of range + */ + int getOffset(int era, int year, int month, int day, int dayOfWeek, + int millis, int monthLength, int prevMonthLength) { + if (false) { + /* Use this parameter checking code for normal operation. Only one + * of these two blocks should actually get compiled into the class + * file. */ + if ((era != GregorianCalendar.AD && era != GregorianCalendar.BC) + || month < Calendar.JANUARY + || month > Calendar.DECEMBER + || day < 1 + || day > monthLength + || dayOfWeek < Calendar.SUNDAY + || dayOfWeek > Calendar.SATURDAY + || millis < 0 + || millis >= millisPerDay + || monthLength < 28 + || monthLength > 31 + || prevMonthLength < 28 + || prevMonthLength > 31) { + throw new IllegalArgumentException(); + } + } else { + /* This parameter checking code is better for debugging, but + * overkill for normal operation. Only one of these two blocks + * should actually get compiled into the class file. */ + if (era != GregorianCalendar.AD && era != GregorianCalendar.BC) { + throw new IllegalArgumentException("Illegal era " + era); + } + if (month < Calendar.JANUARY + || month > Calendar.DECEMBER) { + throw new IllegalArgumentException("Illegal month " + month); + } + if (day < 1 + || day > monthLength) { + throw new IllegalArgumentException("Illegal day " + day); + } + if (dayOfWeek < Calendar.SUNDAY + || dayOfWeek > Calendar.SATURDAY) { + throw new IllegalArgumentException("Illegal day of week " + dayOfWeek); + } + if (millis < 0 + || millis >= millisPerDay) { + throw new IllegalArgumentException("Illegal millis " + millis); + } + if (monthLength < 28 + || monthLength > 31) { + throw new IllegalArgumentException("Illegal month length " + monthLength); + } + if (prevMonthLength < 28 + || prevMonthLength > 31) { + throw new IllegalArgumentException("Illegal previous month length " + prevMonthLength); + } + } + + int result = rawOffset; + + // Bail out if we are before the onset of daylight savings time + if (!useDaylight || year < startYear || era != GregorianCalendar.AD) return result; + + // Check for southern hemisphere. We assume that the start and end + // month are different. + boolean southern = (startMonth > endMonth); + + // Compare the date to the starting and ending rules.+1 = date>rule, -1 + // = date= 0)) { + /* For the ending rule comparison, we add the dstSavings to the millis + * passed in to convert them from standard to wall time. We then must + * normalize the millis to the range 0..millisPerDay-1. */ + endCompare = compareToRule(month, monthLength, prevMonthLength, + day, dayOfWeek, millis, + endTimeMode == WALL_TIME ? dstSavings : + (endTimeMode == UTC_TIME ? -rawOffset : 0), + endMode, endMonth, endDayOfWeek, + endDay, endTime); + } + + // Check for both the northern and southern hemisphere cases. We + // assume that in the northern hemisphere, the start rule is before the + // end rule within the calendar year, and vice versa for the southern + // hemisphere. + if ((!southern && (startCompare >= 0 && endCompare < 0)) || + (southern && (startCompare >= 0 || endCompare < 0))) + result += dstSavings; + + return result; + } + + /** + * Compare a given date in the year to a rule. Return 1, 0, or -1, depending + * on whether the date is after, equal to, or before the rule date. The + * millis are compared directly against the ruleMillis, so any + * standard-daylight adjustments must be handled by the caller. + * + * @return 1 if the date is after the rule date, -1 if the date is before + * the rule date, or 0 if the date is equal to the rule date. + */ + private static int compareToRule(int month, int monthLen, int prevMonthLen, + int dayOfMonth, + int dayOfWeek, int millis, int millisDelta, + int ruleMode, int ruleMonth, int ruleDayOfWeek, + int ruleDay, int ruleMillis) + { + // Make adjustments for startTimeMode and endTimeMode + millis += millisDelta; + while (millis >= millisPerDay) { + millis -= millisPerDay; + ++dayOfMonth; + dayOfWeek = 1 + (dayOfWeek % 7); // dayOfWeek is one-based + if (dayOfMonth > monthLen) { + dayOfMonth = 1; + /* When incrementing the month, it is desirible to overflow + * from DECEMBER to DECEMBER+1, since we use the result to + * compare against a real month. Wraparound of the value + * leads to bug 4173604. */ + ++month; + } + } + while (millis < 0) { + millis += millisPerDay; + --dayOfMonth; + dayOfWeek = 1 + ((dayOfWeek+5) % 7); // dayOfWeek is one-based + if (dayOfMonth < 1) { + dayOfMonth = prevMonthLen; + --month; + } + } + + if (month < ruleMonth) return -1; + else if (month > ruleMonth) return 1; + + int ruleDayOfMonth = 0; + switch (ruleMode) + { + case DOM_MODE: + ruleDayOfMonth = ruleDay; + break; + case DOW_IN_MONTH_MODE: + // In this case ruleDay is the day-of-week-in-month + if (ruleDay > 0) + ruleDayOfMonth = 1 + (ruleDay - 1) * 7 + + (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7; + else // Assume ruleDay < 0 here + { + ruleDayOfMonth = monthLen + (ruleDay + 1) * 7 - + (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7; + } + break; + case DOW_GE_DOM_MODE: + ruleDayOfMonth = ruleDay + + (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth) % 7; + break; + case DOW_LE_DOM_MODE: + ruleDayOfMonth = ruleDay - + (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth) % 7; + // Note at this point ruleDayOfMonth may be <1, although it will + // be >=1 for well-formed rules. + break; + } + + if (dayOfMonth < ruleDayOfMonth) return -1; + else if (dayOfMonth > ruleDayOfMonth) return 1; + + if (millis < ruleMillis) return -1; + else if (millis > ruleMillis) return 1; + else return 0; + } + + /** + * Overrides TimeZone + * Gets the GMT offset for this time zone. + */ + public int getRawOffset() + { + // The given date will be taken into account while + // we have the historical time zone data in place. + return rawOffset; + } + + /** + * Overrides TimeZone + * Sets the base time zone offset to GMT. + * This is the offset to add *to* UTC to get local time. + * Please see TimeZone.setRawOffset for descriptions on the parameter. + */ + public void setRawOffset(int offsetMillis) + { + this.rawOffset = offsetMillis; + } + + /** + * Sets the amount of time in ms that the clock is advanced during DST. + * @param millisSavedDuringDST the number of milliseconds the time is + * advanced with respect to standard time when the daylight savings rules + * are in effect. A positive number, typically one hour (3600000). + * @since 1.2 + */ + public void setDSTSavings(int millisSavedDuringDST) { + if (millisSavedDuringDST <= 0) { + throw new IllegalArgumentException("Illegal DST savings"); + } + dstSavings = millisSavedDuringDST; + } + + /** + * Returns the amount of time in ms that the clock is advanced during DST. + * @return the number of milliseconds the time is + * advanced with respect to standard time when the daylight savings rules + * are in effect. A positive number, typically one hour (3600000). + * @since 1.2 + */ + public int getDSTSavings() { + return dstSavings; + } + + /** + * Overrides TimeZone + * Queries if this time zone uses Daylight Savings Time. + */ + public boolean useDaylightTime() + { + return useDaylight; + } + + /** + * Overrides TimeZone + * Queries if the given date is in Daylight Savings Time. + */ + public boolean inDaylightTime(Date date) + { + GregorianCalendar gc = new GregorianCalendar(this); + gc.setTime(date); + return gc.inDaylightTime(); + } + + /** + * Overrides Cloneable + */ + public Object clone() + { + return super.clone(); + // other fields are bit-copied + } + + /** + * Override hashCode. + * Generates the hash code for the SimpleDateFormat object + */ + public synchronized int hashCode() + { + return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^ + endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset; + } + + /** + * Compares the equality of two SimpleTimeZone objects. + * + * @param obj The SimpleTimeZone object to be compared with. + * @return True if the given obj is the same as this SimpleTimeZone + * object; false otherwise. + */ + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (!(obj instanceof SimpleTimeZone)) + return false; + + SimpleTimeZone that = (SimpleTimeZone) obj; + + return getID().equals(that.getID()) && + hasSameRules(that); + } + + /** + * Return true if this zone has the same rules and offset as another zone. + * @param other the TimeZone object to be compared with + * @return true if the given zone has the same rules and offset as this one + * @since 1.2 + */ + public boolean hasSameRules(TimeZone other) { + if (this == other) return true; + if (!(other instanceof SimpleTimeZone)) return false; + SimpleTimeZone that = (SimpleTimeZone) other; + return rawOffset == that.rawOffset && + useDaylight == that.useDaylight && + (!useDaylight + // Only check rules if using DST + || (dstSavings == that.dstSavings && + startMode == that.startMode && + startMonth == that.startMonth && + startDay == that.startDay && + startDayOfWeek == that.startDayOfWeek && + startTime == that.startTime && + startTimeMode == that.startTimeMode && + endMode == that.endMode && + endMonth == that.endMonth && + endDay == that.endDay && + endDayOfWeek == that.endDayOfWeek && + endTime == that.endTime && + endTimeMode == that.endTimeMode && + startYear == that.startYear)); + } + + /** + * Return a string representation of this time zone. + * @return a string representation of this time zone. + */ + public String toString() { + return getClass().getName() + + "[id=" + getID() + + ",offset=" + rawOffset + + ",dstSavings=" + dstSavings + + ",useDaylight=" + useDaylight + + ",startYear=" + startYear + + ",startMode=" + startMode + + ",startMonth=" + startMonth + + ",startDay=" + startDay + + ",startDayOfWeek=" + startDayOfWeek + + ",startTime=" + startTime + + ",startTimeMode=" + startTimeMode + + ",endMode=" + endMode + + ",endMonth=" + endMonth + + ",endDay=" + endDay + + ",endDayOfWeek=" + endDayOfWeek + + ",endTime=" + endTime + + ",endTimeMode=" + endTimeMode + ']'; + } + + // =======================privates=============================== + + /** + * The month in which daylight savings time starts. This value must be + * between Calendar.JANUARY and + * Calendar.DECEMBER inclusive. This value must not equal + * endMonth. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int startMonth; + + /** + * This field has two possible interpretations: + *

+ *
startMode == DOW_IN_MONTH
+ *
+ * startDay indicates the day of the month of + * startMonth on which daylight + * savings time starts, from 1 to 28, 30, or 31, depending on the + * startMonth. + *
+ *
startMode != DOW_IN_MONTH
+ *
+ * startDay indicates which startDayOfWeek in th + * month startMonth daylight + * savings time starts on. For example, a value of +1 and a + * startDayOfWeek of Calendar.SUNDAY indicates the + * first Sunday of startMonth. Likewise, +2 would indicate the + * second Sunday, and -1 the last Sunday. A value of 0 is illegal. + *
+ * + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int startDay; + + /** + * The day of the week on which daylight savings time starts. This value + * must be between Calendar.SUNDAY and + * Calendar.SATURDAY inclusive. + *

If useDaylight is false or + * startMode == DAY_OF_MONTH, this value is ignored. + * @serial + */ + private int startDayOfWeek; + + /** + * The time in milliseconds after midnight at which daylight savings + * time starts. This value is expressed as wall time, standard time, + * or UTC time, depending on the setting of startTimeMode. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int startTime; + + /** + * The format of startTime, either WALL_TIME, STANDARD_TIME, or UTC_TIME. + * @serial + * @since JDK 1.3 + */ + private int startTimeMode; + + /** + * The month in which daylight savings time ends. This value must be + * between Calendar.JANUARY and + * Calendar.UNDECIMBER. This value must not equal + * startMonth. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int endMonth; + + /** + * This field has two possible interpretations: + *

+ *
endMode == DOW_IN_MONTH
+ *
+ * endDay indicates the day of the month of + * endMonth on which daylight + * savings time ends, from 1 to 28, 30, or 31, depending on the + * endMonth. + *
+ *
endMode != DOW_IN_MONTH
+ *
+ * endDay indicates which endDayOfWeek in th + * month endMonth daylight + * savings time ends on. For example, a value of +1 and a + * endDayOfWeek of Calendar.SUNDAY indicates the + * first Sunday of endMonth. Likewise, +2 would indicate the + * second Sunday, and -1 the last Sunday. A value of 0 is illegal. + *
+ * + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int endDay; + + /** + * The day of the week on which daylight savings time ends. This value + * must be between Calendar.SUNDAY and + * Calendar.SATURDAY inclusive. + *

If useDaylight is false or + * endMode == DAY_OF_MONTH, this value is ignored. + * @serial + */ + private int endDayOfWeek; + + /** + * The time in milliseconds after midnight at which daylight savings + * time ends. This value is expressed as wall time, standard time, + * or UTC time, depending on the setting of endTimeMode. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int endTime; + + /** + * The format of endTime, either WALL_TIME, STANDARD_TIME, or UTC_TIME. + * @serial + * @since JDK 1.3 + */ + private int endTimeMode; + + /** + * The year in which daylight savings time is first observed. This is an AD + * value. If this value is less than 1 then daylight savings is observed + * for all AD years. + *

If useDaylight is false, this value is ignored. + * @serial + */ + private int startYear; + + /** + * The offset in milliseconds between this zone and GMT. Negative offsets + * are to the west of Greenwich. To obtain local standard time, + * add the offset to GMT time. To obtain local wall time it may also be + * necessary to add dstSavings. + * @serial + */ + private int rawOffset; + + /** + * A boolean value which is true if and only if this zone uses daylight + * savings time. If this value is false, several other fields are ignored. + * @serial + */ + private boolean useDaylight=false; // indicate if this time zone uses DST + + private static final int millisPerHour = 60*60*1000; + private static final int millisPerDay = 24*millisPerHour; + + /** + * This field was serialized in JDK 1.1, so we have to keep it that way + * to maintain serialization compatibility. However, there's no need to + * recreate the array each time we create a new time zone. + * @serial An array of bytes containing the values {31, 28, 31, 30, 31, 30, + * 31, 31, 30, 31, 30, 31}. This is ignored as of the Java 2 platform v1.2, however, it must + * be streamed out for compatibility with JDK 1.1. + */ + private final byte monthLength[] = staticMonthLength; + private final static byte staticMonthLength[] = {31,28,31,30,31,30,31,31,30,31,30,31}; + private final static byte staticLeapMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31}; + // Hack: Use the y/m/d constructor in the following line. + // This prevents the infinite recursion that results when + // the GC wants to call STZ.getOffset. - liu + private static GregorianCalendar internalCal = new GregorianCalendar(0, 0, 0); + + /** + * Variables specifying the mode of the start rule. Takes the following + * values: + *

+ *
DOM_MODE
+ *
+ * Exact day of week; e.g., March 1. + *
+ *
DOW_IN_MONTH_MODE
+ *
+ * Day of week in month; e.g., last Sunday in March. + *
+ *
DOW_GE_DOM_MODE
+ *
+ * Day of week after day of month; e.g., Sunday on or after March 15. + *
+ *
DOW_LE_DOM_MODE
+ *
+ * Day of week before day of month; e.g., Sunday on or before March 15. + *
+ *
+ * The setting of this field affects the interpretation of the + * startDay field. + *

If useDaylight is false, this value is ignored. + * @serial + * @since JDK1.1.4 + */ + private int startMode; + + /** + * Variables specifying the mode of the end rule. Takes the following + * values: + *

+ *
DOM_MODE
+ *
+ * Exact day of week; e.g., March 1. + *
+ *
DOW_IN_MONTH_MODE
+ *
+ * Day of week in month; e.g., last Sunday in March. + *
+ *
DOW_GE_DOM_MODE
+ *
+ * Day of week after day of month; e.g., Sunday on or after March 15. + *
+ *
DOW_LE_DOM_MODE
+ *
+ * Day of week before day of month; e.g., Sunday on or before March 15. + *
+ *
+ * The setting of this field affects the interpretation of the + * endDay field. + *

If useDaylight is false, this value is ignored. + * @serial + * @since JDK1.1.4 + */ + private int endMode; + + /** + * A positive value indicating the amount of time saved during DST in + * milliseconds. + * Typically one hour (3600000); sometimes 30 minutes (1800000). + *

If useDaylight is false, this value is ignored. + * @serial + * @since JDK1.1.4 + */ + private int dstSavings; + + /** + * Constants specifying values of startMode and endMode. + */ + private static final int DOM_MODE = 1; // Exact day of month, "Mar 1" + private static final int DOW_IN_MONTH_MODE = 2; // Day of week in month, "lastSun" + private static final int DOW_GE_DOM_MODE = 3; // Day of week after day of month, "Sun>=15" + private static final int DOW_LE_DOM_MODE = 4; // Day of week before day of month, "Sun<=21" + + /** + * Constant for a rule specified as wall time. Wall time is standard time + * for the onset rule, and daylight time for the end rule. Most rules + * are specified as wall time. + */ + static final int WALL_TIME = 0; // Zero for backward compatibility + + /** + * Constant for a rule specified as standard time. + */ + static final int STANDARD_TIME = 1; + + /** + * Constant for a rule specified as UTC. EU rules are specified as UTC + * time. + */ + static final int UTC_TIME = 2; + + // Proclaim compatibility with 1.1 + static final long serialVersionUID = -403250971215465050L; + + // the internal serial version which says which version was written + // - 0 (default) for version up to JDK 1.1.3 + // - 1 for version from JDK 1.1.4, which includes 3 new fields + // - 2 for JDK 1.3, which includes 2 new files + static final int currentSerialVersion = 2; + + /** + * The version of the serialized data on the stream. Possible values: + *

+ *
0 or not present on stream
+ *
+ * JDK 1.1.3 or earlier. + *
+ *
1
+ *
+ * JDK 1.1.4 or later. Includes three new fields: startMode, + * endMode, and dstSavings. + *
+ *
2
+ *
+ * JDK 1.3 or later. Includes two new fields: startTimeMode + * and endTimeMode. + *
+ *
+ * When streaming out this class, the most recent format + * and the highest allowable serialVersionOnStream + * is written. + * @serial + * @since JDK1.1.4 + */ + private int serialVersionOnStream = currentSerialVersion; + + //---------------------------------------------------------------------- + // Rule representation + // + // We represent the following flavors of rules: + // 5 the fifth of the month + // lastSun the last Sunday in the month + // lastMon the last Monday in the month + // Sun>=8 first Sunday on or after the eighth + // Sun<=25 last Sunday on or before the 25th + // This is further complicated by the fact that we need to remain + // backward compatible with the 1.1 FCS. Finally, we need to minimize + // API changes. In order to satisfy these requirements, we support + // three representation systems, and we translate between them. + // + // INTERNAL REPRESENTATION + // This is the format SimpleTimeZone objects take after construction or + // streaming in is complete. Rules are represented directly, using an + // unencoded format. We will discuss the start rule only below; the end + // rule is analogous. + // startMode Takes on enumerated values DAY_OF_MONTH, + // DOW_IN_MONTH, DOW_AFTER_DOM, or DOW_BEFORE_DOM. + // startDay The day of the month, or for DOW_IN_MONTH mode, a + // value indicating which DOW, such as +1 for first, + // +2 for second, -1 for last, etc. + // startDayOfWeek The day of the week. Ignored for DAY_OF_MONTH. + // + // ENCODED REPRESENTATION + // This is the format accepted by the constructor and by setStartRule() + // and setEndRule(). It uses various combinations of positive, negative, + // and zero values to encode the different rules. This representation + // allows us to specify all the different rule flavors without altering + // the API. + // MODE startMonth startDay startDayOfWeek + // DOW_IN_MONTH_MODE >=0 !=0 >0 + // DOM_MODE >=0 >0 ==0 + // DOW_GE_DOM_MODE >=0 >0 <0 + // DOW_LE_DOM_MODE >=0 <0 <0 + // (no DST) don't care ==0 don't care + // + // STREAMED REPRESENTATION + // We must retain binary compatibility with the 1.1 FCS. The 1.1 code only + // handles DOW_IN_MONTH_MODE and non-DST mode, the latter indicated by the + // flag useDaylight. When we stream an object out, we translate into an + // approximate DOW_IN_MONTH_MODE representation so the object can be parsed + // and used by 1.1 code. Following that, we write out the full + // representation separately so that contemporary code can recognize and + // parse it. The full representation is written in a "packed" format, + // consisting of a version number, a length, and an array of bytes. Future + // versions of this class may specify different versions. If they wish to + // include additional data, they should do so by storing them after the + // packed representation below. + //---------------------------------------------------------------------- + + /** + * Given a set of encoded rules in startDay and startDayOfMonth, decode + * them and set the startMode appropriately. Do the same for endDay and + * endDayOfMonth. Upon entry, the day of week variables may be zero or + * negative, in order to indicate special modes. The day of month + * variables may also be negative. Upon exit, the mode variables will be + * set, and the day of week and day of month variables will be positive. + * This method also recognizes a startDay or endDay of zero as indicating + * no DST. + */ + private void decodeRules() + { + decodeStartRule(); + decodeEndRule(); + } + + /** + * Decode the start rule and validate the parameters. The parameters are + * expected to be in encoded form, which represents the various rule modes + * by negating or zeroing certain values. Representation formats are: + *

+ *

+     *            DOW_IN_MONTH  DOM    DOW>=DOM  DOW<=DOM  no DST
+     *            ------------  -----  --------  --------  ----------
+     * month       0..11        same    same      same     don't care
+     * day        -5..5         1..31   1..31    -1..-31   0
+     * dayOfWeek   1..7         0      -1..-7    -1..-7    don't care
+     * time        0..ONEDAY    same    same      same     don't care
+     * 
+ * The range for month does not include UNDECIMBER since this class is + * really specific to GregorianCalendar, which does not use that month. + * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the + * end rule is an exclusive limit point. That is, the range of times that + * are in DST include those >= the start and < the end. For this reason, + * it should be possible to specify an end of ONEDAY in order to include the + * entire day. Although this is equivalent to time 0 of the following day, + * it's not always possible to specify that, for example, on December 31. + * While arguably the start range should still be 0..ONEDAY-1, we keep + * the start and end ranges the same for consistency. + */ + private void decodeStartRule() { + useDaylight = (startDay != 0) && (endDay != 0); + if (startDay != 0) { + if (startMonth < Calendar.JANUARY || startMonth > Calendar.DECEMBER) { + throw new IllegalArgumentException( + "Illegal start month " + startMonth); + } + if (startTime < 0 || startTime >= millisPerDay) { + throw new IllegalArgumentException( + "Illegal start time " + startTime); + } + if (startDayOfWeek == 0) { + startMode = DOM_MODE; + } else { + if (startDayOfWeek > 0) { + startMode = DOW_IN_MONTH_MODE; + } else { + startDayOfWeek = -startDayOfWeek; + if (startDay > 0) { + startMode = DOW_GE_DOM_MODE; + } else { + startDay = -startDay; + startMode = DOW_LE_DOM_MODE; + } + } + if (startDayOfWeek > Calendar.SATURDAY) { + throw new IllegalArgumentException( + "Illegal start day of week " + startDayOfWeek); + } + } + if (startMode == DOW_IN_MONTH_MODE) { + if (startDay < -5 || startDay > 5) { + throw new IllegalArgumentException( + "Illegal start day of week in month " + startDay); + } + } else if (startDay < 1 || startDay > staticMonthLength[startMonth]) { + throw new IllegalArgumentException( + "Illegal start day " + startDay); + } + } + } + + /** + * Decode the end rule and validate the parameters. This method is exactly + * analogous to decodeStartRule(). + * @see decodeStartRule + */ + private void decodeEndRule() { + useDaylight = (startDay != 0) && (endDay != 0); + if (endDay != 0) { + if (endMonth < Calendar.JANUARY || endMonth > Calendar.DECEMBER) { + throw new IllegalArgumentException( + "Illegal end month " + endMonth); + } + if (endTime < 0 || endTime >= millisPerDay) { + throw new IllegalArgumentException( + "Illegal end time " + endTime); + } + if (endDayOfWeek == 0) { + endMode = DOM_MODE; + } else { + if (endDayOfWeek > 0) { + endMode = DOW_IN_MONTH_MODE; + } else { + endDayOfWeek = -endDayOfWeek; + if (endDay > 0) { + endMode = DOW_GE_DOM_MODE; + } else { + endDay = -endDay; + endMode = DOW_LE_DOM_MODE; + } + } + if (endDayOfWeek > Calendar.SATURDAY) { + throw new IllegalArgumentException( + "Illegal end day of week " + endDayOfWeek); + } + } + if (endMode == DOW_IN_MONTH_MODE) { + if (endDay < -5 || endDay > 5) { + throw new IllegalArgumentException( + "Illegal end day of week in month " + endDay); + } + } else if (endDay < 1 || endDay > staticMonthLength[endMonth]) { + throw new IllegalArgumentException( + "Illegal end day " + endDay); + } + } + } + + /** + * Make rules compatible to 1.1 FCS code. Since 1.1 FCS code only understands + * day-of-week-in-month rules, we must modify other modes of rules to their + * approximate equivalent in 1.1 FCS terms. This method is used when streaming + * out objects of this class. After it is called, the rules will be modified, + * with a possible loss of information. startMode and endMode will NOT be + * altered, even though semantically they should be set to DOW_IN_MONTH_MODE, + * since the rule modification is only intended to be temporary. + */ + private void makeRulesCompatible() + { + switch (startMode) + { + case DOM_MODE: + startDay = 1 + (startDay / 7); + startDayOfWeek = Calendar.SUNDAY; + break; + case DOW_GE_DOM_MODE: + // A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE + // that is, Sun>=1 == firstSun. + if (startDay != 1) + startDay = 1 + (startDay / 7); + break; + case DOW_LE_DOM_MODE: + if (startDay >= 30) + startDay = -1; + else + startDay = 1 + (startDay / 7); + break; + } + + switch (endMode) + { + case DOM_MODE: + endDay = 1 + (endDay / 7); + endDayOfWeek = Calendar.SUNDAY; + break; + case DOW_GE_DOM_MODE: + // A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE + // that is, Sun>=1 == firstSun. + if (endDay != 1) + endDay = 1 + (endDay / 7); + break; + case DOW_LE_DOM_MODE: + if (endDay >= 30) + endDay = -1; + else + endDay = 1 + (endDay / 7); + break; + } + + /* Adjust the start and end times to wall time. This works perfectly + * well unless it pushes into the next or previous day. If that + * happens, we attempt to adjust the day rule somewhat crudely. The day + * rules have been forced into DOW_IN_MONTH mode already, so we change + * the day of week to move forward or back by a day. It's possible to + * make a more refined adjustment of the original rules first, but in + * most cases this extra effort will go to waste once we adjust the day + * rules anyway. */ + switch (startTimeMode) { + case UTC_TIME: + startTime += rawOffset; + break; + } + while (startTime < 0) { + startTime += millisPerDay; + startDayOfWeek = 1 + ((startDayOfWeek+5) % 7); // Back 1 day + } + while (startTime >= millisPerDay) { + startTime -= millisPerDay; + startDayOfWeek = 1 + (startDayOfWeek % 7); // Forward 1 day + } + + switch (endTimeMode) { + case UTC_TIME: + endTime += rawOffset + dstSavings; + break; + case STANDARD_TIME: + endTime += dstSavings; + } + while (endTime < 0) { + endTime += millisPerDay; + endDayOfWeek = 1 + ((endDayOfWeek+5) % 7); // Back 1 day + } + while (endTime >= millisPerDay) { + endTime -= millisPerDay; + endDayOfWeek = 1 + (endDayOfWeek % 7); // Forward 1 day + } + } + + /** + * Pack the start and end rules into an array of bytes. Only pack + * data which is not preserved by makeRulesCompatible. + */ + private byte[] packRules() + { + byte[] rules = new byte[6]; + rules[0] = (byte)startDay; + rules[1] = (byte)startDayOfWeek; + rules[2] = (byte)endDay; + rules[3] = (byte)endDayOfWeek; + + // As of serial version 2, include time modes + rules[4] = (byte)startTimeMode; + rules[5] = (byte)endTimeMode; + + return rules; + } + + /** + * Given an array of bytes produced by packRules, interpret them + * as the start and end rules. + */ + private void unpackRules(byte[] rules) + { + startDay = rules[0]; + startDayOfWeek = rules[1]; + endDay = rules[2]; + endDayOfWeek = rules[3]; + + // As of serial version 2, include time modes + if (rules.length >= 6) { + startTimeMode = rules[4]; + endTimeMode = rules[5]; + } + } + + /** + * Pack the start and end times into an array of bytes. This is required + * as of serial version 2. + */ + private int[] packTimes() { + int[] times = new int[2]; + times[0] = startTime; + times[1] = endTime; + return times; + } + + /** + * Unpack the start and end times from an array of bytes. This is required + * as of serial version 2. + */ + private void unpackTimes(int[] times) { + startTime = times[0]; + endTime = times[1]; + } + + /** + * Save the state of this object to a stream (i.e., serialize it). + * + * @serialData We write out two formats, a JDK 1.1 compatible format, using + * DOW_IN_MONTH_MODE rules, in the required section, followed + * by the full rules, in packed format, in the optional section. The + * optional section will be ignored by JDK 1.1 code upon stream in. + *

Contents of the optional section: The length of a byte array is + * emitted (int); this is 4 as of this release. The byte array of the given + * length is emitted. The contents of the byte array are the true values of + * the fields startDay, startDayOfWeek, + * endDay, and endDayOfWeek. The values of these + * fields in the required section are approximate values suited to the rule + * mode DOW_IN_MONTH_MODE, which is the only mode recognized by + * JDK 1.1. + */ + private void writeObject(ObjectOutputStream stream) + throws IOException + { + // Construct a binary rule + byte[] rules = packRules(); + int[] times = packTimes(); + + // Convert to 1.1 FCS rules. This step may cause us to lose information. + makeRulesCompatible(); + + // Write out the 1.1 FCS rules + stream.defaultWriteObject(); + + // Write out the binary rules in the optional data area of the stream. + stream.writeInt(rules.length); + stream.write(rules); + stream.writeObject(times); + + // Recover the original rules. This recovers the information lost + // by makeRulesCompatible. + unpackRules(rules); + unpackTimes(times); + } + + /** + * Reconstitute this object from a stream (i.e., deserialize it). + * + * We handle both JDK 1.1 + * binary formats and full formats with a packed byte array. + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + + if (serialVersionOnStream < 1) + { + // Fix a bug in the 1.1 SimpleTimeZone code -- namely, + // startDayOfWeek and endDayOfWeek were usually uninitialized. We can't do + // too much, so we assume SUNDAY, which actually works most of the time. + if (startDayOfWeek == 0) startDayOfWeek = Calendar.SUNDAY; + if (endDayOfWeek == 0) endDayOfWeek = Calendar.SUNDAY; + + // The variables dstSavings, startMode, and endMode are post-1.1, so they + // won't be present if we're reading from a 1.1 stream. Fix them up. + startMode = endMode = DOW_IN_MONTH_MODE; + dstSavings = millisPerHour; + } + else + { + // For 1.1.4, in addition to the 3 new instance variables, we also + // store the actual rules (which have not be made compatible with 1.1) + // in the optional area. Read them in here and parse them. + int length = stream.readInt(); + byte[] rules = new byte[length]; + stream.readFully(rules); + unpackRules(rules); + } + + if (serialVersionOnStream >= 2) { + int[] times = (int[]) stream.readObject(); + unpackTimes(times); + } + + serialVersionOnStream = currentSerialVersion; + } +} + +//eof diff --git a/icu4j/src/com/ibm/util/SimpleTimeZoneAdapter.java b/icu4j/src/com/ibm/util/SimpleTimeZoneAdapter.java new file mode 100755 index 0000000000..7fc8f16051 --- /dev/null +++ b/icu4j/src/com/ibm/util/SimpleTimeZoneAdapter.java @@ -0,0 +1,157 @@ +/* Copyright (c) 2000 International Business Machines Corporation and + * others. All Rights Reserved. + * + * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/util/Attic/SimpleTimeZoneAdapter.java,v $ + * $Date: 2000/05/12 23:20:11 $ + * $Revision: 1.1 $ + */ +package com.ibm.util; +import java.util.Date; + +/** + * SimpleTimeZoneAdapter wraps a + * com.ibm.util.SimpleTimeZone and inherits from java.util.TimeZone. + * Without this class, we would need to 'port' java.util.Date to + * com.ibm.util as well, so that Date could interoperate properly with + * the com.ibm.util TimeZone and Calendar classes. With this class, + * we can (mostly) use java.util.Date together with com.ibm.util + * classes. + * + *

This solution is imperfect because of the faulty design of + * java.util.TimeZone. Specifically, TZ contains a package private + * method, getOffset(), that should really be public. Because it is + * package private, it cannot be overridden from where we are, and we + * cannot properly delegate its operation to our contained + * com.ibm.util.STZ object. + * + *

For the moment we live with this problem. It appear not to + * cause too much trouble since most real computations happen using + * the com.ibm.util classes. However, if this becomes a problem in + * the future, we will have to stop using this adapter, and 'port' + * java.util.Date into com.ibm.util. + * + * @see com.ibm.util.TimeZone#setDefault + * @author Alan Liu + */ +public class SimpleTimeZoneAdapter extends java.util.TimeZone { + + /** + * The contained com.ibm.util.SimpleTimeZone object. + * We delegate all methods to this object. + */ + private SimpleTimeZone zone; + + public SimpleTimeZoneAdapter(SimpleTimeZone zone) { + this.zone = zone; + } + + /** + * Override TimeZone + */ + public String getID() { + return zone.getID(); + } + + /** + * Override TimeZone + */ + public void setID(String ID) { + zone.setID(ID); + } + + /** + * Override TimeZone + */ + public boolean hasSameRules(java.util.TimeZone other) { + return other instanceof SimpleTimeZoneAdapter && + zone.hasSameRules(((SimpleTimeZoneAdapter)other).zone); + } + + /** + * Override TimeZone + */ + public int getOffset(int era, int year, int month, int day, int dayOfWeek, + int millis) { + return zone.getOffset(era, year, month, day, dayOfWeek, millis); + } + + // This doesn't work! Because this is a package-private method, + // it cannot override the corresponding method in java.util.TZ. + // This reflects a fundamental bug in the architecture of + // java.util.TZ. If not for this, this adapter class would + // work flawlessly. - liu +//! /** +//! * Override TimeZone +//! */ +//! int getOffset(int era, int year, int month, int day, int dayOfWeek, +//! int millis, int monthLength, int prevMonthLength) { +//! return zone.getOffset(era, year, month, day, dayOfWeek, +//! millis, monthLength, prevMonthLength); +//! } + + /** + * Overrides TimeZone + * Gets the GMT offset for this time zone. + */ + public int getRawOffset() { + return zone.getRawOffset(); + } + + /** + * Overrides TimeZone + */ + public void setRawOffset(int offsetMillis) { + zone.setRawOffset(offsetMillis); + } + + /** + * Overrides TimeZone + */ + public boolean useDaylightTime() { + return zone.useDaylightTime(); + } + + /** + * Overrides TimeZone + */ + public boolean inDaylightTime(Date date) { + return zone.inDaylightTime(date); + } + + /** + * Overrides Cloneable + */ + public Object clone() { + return new SimpleTimeZoneAdapter((SimpleTimeZone)zone.clone()); + } + + /** + * Override hashCode. + */ + public synchronized int hashCode() { + return zone.hashCode(); + } + + /** + * Compares the equality of two SimpleTimeZone objects. + * + * @param obj The SimpleTimeZone object to be compared with. + * @return True if the given obj is the same as this SimpleTimeZone + * object; false otherwise. + */ + public boolean equals(Object obj) { + if (obj instanceof SimpleTimeZoneAdapter) { + obj = ((SimpleTimeZoneAdapter)obj).zone; + } + return zone.equals(obj); + } + + /** + * Return a string representation of this time zone. + * @return a string representation of this time zone. + */ + public String toString() { + // Should probably show our class name here...fix later. + return zone.toString(); + } +} diff --git a/icu4j/src/com/ibm/util/TimeZone.java b/icu4j/src/com/ibm/util/TimeZone.java new file mode 100755 index 0000000000..98810f3962 --- /dev/null +++ b/icu4j/src/com/ibm/util/TimeZone.java @@ -0,0 +1,2036 @@ +/* + * @(#)TimeZone.java 1.51 00/01/19 + * + * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved. + * + * This software is the proprietary information of Sun Microsystems, Inc. + * Use is subject to license terms. + * + */ + +/* + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - All Rights Reserved + * + * The original version of this source code and documentation is copyrighted + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These + * materials are provided under terms of a License Agreement between Taligent + * and Sun. This technology is protected by multiple US and International + * patents. This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + */ + +package com.ibm.util; +import java.io.Serializable; +import java.lang.ref.SoftReference; +import java.security.AccessController; +import java.security.PrivilegedAction; +import com.ibm.text.SimpleDateFormat; +import com.ibm.text.NumberFormat; +import java.text.ParsePosition; +import sun.security.action.GetPropertyAction; +import java.util.Date; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +/** + * TimeZone represents a time zone offset, and also figures out daylight + * savings. + * + *

+ * Typically, you get a TimeZone using getDefault + * which creates a TimeZone based on the time zone where the program + * is running. For example, for a program running in Japan, getDefault + * creates a TimeZone object based on Japanese Standard Time. + * + *

+ * You can also get a TimeZone using getTimeZone + * along with a time zone ID. For instance, the time zone ID for the + * U.S. Pacific Time zone is "America/Los_Angeles". So, you can get a + * U.S. Pacific Time TimeZone object with: + *

+ *
+ * TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
+ * 
+ *
+ * You can use getAvailableIDs method to iterate through + * all the supported time zone IDs. You can then choose a + * supported ID to get a TimeZone. + * If the time zone you want is not represented by one of the + * supported IDs, then you can create a custom time zone ID with + * the following syntax: + * + *
+ *
+ * GMT[+|-]hh[[:]mm]
+ * 
+ *
+ * + * For example, you might specify GMT+14:00 as a custom + * time zone ID. The TimeZone that is returned + * when you specify a custom time zone ID does not include + * daylight savings time. + *

+ * For compatibility with JDK 1.1.x, some other three-letter time zone IDs + * (such as "PST", "CTT", "AST") are also supported. However, their + * use is deprecated because the same abbreviation is often used + * for multiple time zones (for example, "CST" could be U.S. "Central Standard + * Time" and "China Standard Time"), and the Java platform can then only + * recognize one of them. + * + * + * @see Calendar + * @see GregorianCalendar + * @see SimpleTimeZone + * @version 1.51 01/19/00 + * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu + * @since JDK1.1 + */ +abstract public class TimeZone implements Serializable, Cloneable { + /** + * Sole constructor. (For invocation by subclass constructors, typically + * implicit.) + */ + public TimeZone() { + } + + /** + * A style specifier for getDisplayName() indicating + * a short name, such as "PST." + * @see #LONG + * @since 1.2 + */ + public static final int SHORT = 0; + + /** + * A style specifier for getDisplayName() indicating + * a long name, such as "Pacific Standard Time." + * @see #SHORT + * @since 1.2 + */ + public static final int LONG = 1; + + // Constants used internally; unit is milliseconds + private static final int ONE_MINUTE = 60*1000; + private static final int ONE_HOUR = 60*ONE_MINUTE; + private static final int ONE_DAY = 24*ONE_HOUR; + + /** + * Cache to hold the SimpleDateFormat objects for a Locale. + */ + private static Hashtable cachedLocaleData = new Hashtable(3); + + // Proclaim serialization compatibility with JDK 1.1 + static final long serialVersionUID = 3581463369166924961L; + + /** + * Gets the time zone offset, for current date, modified in case of + * daylight savings. This is the offset to add *to* UTC to get local time. + * @param era the era of the given date. + * @param year the year in the given date. + * @param month the month in the given date. + * Month is 0-based. e.g., 0 for January. + * @param day the day-in-month of the given date. + * @param dayOfWeek the day-of-week of the given date. + * @param milliseconds the millis in day in standard local time. + * @return the offset to add *to* GMT to get local time. + */ + abstract public int getOffset(int era, int year, int month, int day, + int dayOfWeek, int milliseconds); + + /** + * Gets the time zone offset, for current date, modified in case of + * daylight savings. This is the offset to add *to* UTC to get local time. + * @param era the era of the given date. + * @param year the year in the given date. + * @param month the month in the given date. + * Month is 0-based. e.g., 0 for January. + * @param day the day-in-month of the given date. + * @param dayOfWeek the day-of-week of the given date. + * @param milliseconds the millis in day in standard local time. + * @param monthLength the length of the given month in days. + * @param prevMonthLength the length of the previous month in days. + * @return the offset to add *to* GMT to get local time. + */ + int getOffset(int era, int year, int month, int day, + int dayOfWeek, int milliseconds, int monthLength, int prevMonthLength) { + // Default implementation which ignores the monthLength. + // SimpleTimeZone overrides this and actually uses monthLength. + return getOffset(era, year, month, day, dayOfWeek, milliseconds); + } + + + /** + * Sets the base time zone offset to GMT. + * This is the offset to add *to* UTC to get local time. + * @param offsetMillis the given base time zone offset to GMT. + */ + abstract public void setRawOffset(int offsetMillis); + + /** + * Gets unmodified offset, NOT modified in case of daylight savings. + * This is the offset to add *to* UTC to get local time. + * @return the unmodified offset to add *to* UTC to get local time. + */ + abstract public int getRawOffset(); + + /** + * Gets the ID of this time zone. + * @return the ID of this time zone. + */ + public String getID() + { + return ID; + } + + /** + * Sets the time zone ID. This does not change any other data in + * the time zone object. + * @param ID the new time zone ID. + */ + public void setID(String ID) + { + if (ID == null) { + throw new NullPointerException(); + } + this.ID = ID; + } + + /** + * Returns a name of this time zone suitable for presentation to the user + * in the default locale. + * This method returns the long name, not including daylight savings. + * If the display name is not available for the locale, + * then this method returns a string in the format + * GMT[+-]hh:mm. + * @return the human-readable name of this time zone in the default locale. + * @since 1.2 + */ + public final String getDisplayName() { + return getDisplayName(false, LONG, Locale.getDefault()); + } + + /** + * Returns a name of this time zone suitable for presentation to the user + * in the specified locale. + * This method returns the long name, not including daylight savings. + * If the display name is not available for the locale, + * then this method returns a string in the format + * GMT[+-]hh:mm. + * @param locale the locale in which to supply the display name. + * @return the human-readable name of this time zone in the given locale + * or in the default locale if the given locale is not recognized. + * @since 1.2 + */ + public final String getDisplayName(Locale locale) { + return getDisplayName(false, LONG, locale); + } + + /** + * Returns a name of this time zone suitable for presentation to the user + * in the default locale. + * If the display name is not available for the locale, + * then this method returns a string in the format + * GMT[+-]hh:mm. + * @param daylight if true, return the daylight savings name. + * @param style either LONG or SHORT + * @return the human-readable name of this time zone in the default locale. + * @since 1.2 + */ + public final String getDisplayName(boolean daylight, int style) { + return getDisplayName(daylight, style, Locale.getDefault()); + } + + /** + * Returns a name of this time zone suitable for presentation to the user + * in the specified locale. + * If the display name is not available for the locale, + * then this method returns a string in the format + * GMT[+-]hh:mm. + * @param daylight if true, return the daylight savings name. + * @param style either LONG or SHORT + * @param locale the locale in which to supply the display name. + * @return the human-readable name of this time zone in the given locale + * or in the default locale if the given locale is not recognized. + * @exception IllegalArgumentException style is invalid. + * @since 1.2 + */ + public String getDisplayName(boolean daylight, int style, Locale locale) { + /* NOTES: + * (1) We use SimpleDateFormat for simplicity; we could do this + * more efficiently but it would duplicate the SimpleDateFormat code + * here, which is undesirable. + * (2) Attempts to move the code from SimpleDateFormat to here also run + * aground because this requires SimpleDateFormat to keep a Locale + * object around, which it currently doesn't; to synthesize such a + * locale upon resurrection; and to somehow handle the special case of + * construction from a DateFormatSymbols object. + */ + if (style != SHORT && style != LONG) { + throw new IllegalArgumentException("Illegal style: " + style); + } + // We keep a cache, indexed by locale. The cache contains a + // SimpleDateFormat object, which we create on demand. + SoftReference data = (SoftReference)cachedLocaleData.get(locale); + SimpleDateFormat format; + if (data == null || + (format = (SimpleDateFormat)data.get()) == null) { + format = new SimpleDateFormat(null, locale); + cachedLocaleData.put(locale, new SoftReference(format)); + } + // Create a new SimpleTimeZone as a stand-in for this zone; the stand-in + // will have no DST, or DST during January, but the same ID and offset, + // and hence the same display name. We don't cache these because + // they're small and cheap to create. + SimpleTimeZone tz; + if (daylight && useDaylightTime()) { + int savings = ONE_HOUR; + try { + savings = ((SimpleTimeZone) this).getDSTSavings(); + } catch (ClassCastException e) {} + tz = new SimpleTimeZone(getRawOffset(), getID(), + Calendar.JANUARY, 1, 0, 0, + Calendar.FEBRUARY, 1, 0, 0, + savings); + } else { + tz = new SimpleTimeZone(getRawOffset(), getID()); + } + format.applyPattern(style == LONG ? "zzzz" : "z"); + format.setTimeZone(tz); + // Format a date in January. We use the value 10*ONE_DAY == Jan 11 1970 + // 0:00 GMT. + return format.format(new Date(864000000L)); + } + + /** + * Queries if this time zone uses daylight savings time. + * @return true if this time zone uses daylight savings time, + * false, otherwise. + */ + abstract public boolean useDaylightTime(); + + /** + * Queries if the given date is in daylight savings time in + * this time zone. + * @param date the given Date. + * @return true if the given date is in daylight savings time, + * false, otherwise. + */ + abstract public boolean inDaylightTime(Date date); + + /** + * Gets the TimeZone for the given ID. + * + * @param ID the ID for a TimeZone, either an abbreviation + * such as "PST", a full name such as "America/Los_Angeles", or a custom + * ID such as "GMT-8:00". Note that the support of abbreviations is + * for JDK 1.1.x compatibility only and full names should be used. + * + * @return the specified TimeZone, or the GMT zone if the given ID + * cannot be understood. + */ + public static synchronized TimeZone getTimeZone(String ID) { + /* We first try to lookup the zone ID in our hashtable. If this fails, + * we try to parse it as a custom string GMT[+-]hh:mm. This allows us + * to recognize zones in user.timezone that otherwise cannot be + * identified. We do the recognition here, rather than in getDefault(), + * so that the default zone is always the result of calling + * getTimeZone() with the property user.timezone. + * + * If all else fails, we return GMT, which is probably not what the user + * wants, but at least is a functioning TimeZone object. */ + TimeZone zone = TimeZoneData.get(ID); + if (zone == null) zone = parseCustomTimeZone(ID); + if (zone == null) zone = (TimeZone)GMT.clone(); + return zone; + } + + /** + * Gets the available IDs according to the given time zone offset. + * @param rawOffset the given time zone GMT offset. + * @return an array of IDs, where the time zone for that ID has + * the specified GMT offset. For example, "America/Phoenix" and "America/Denver" + * both have GMT-07:00, but differ in daylight savings behavior. + */ + public static synchronized String[] getAvailableIDs(int rawOffset) { + String[] result; + Vector matched = new Vector(); + + /* The array TimeZoneData.zones is no longer sorted by raw offset. + * Now scanning through all zone data to match offset. + */ + for (int i = 0; i < TimeZoneData.zones.length; ++i) { + if (TimeZoneData.zones[i].getRawOffset() == rawOffset) + matched.add(TimeZoneData.zones[i].getID()); + } + result = new String[matched.size()]; + matched.toArray(result); + + return result; + } + + /** + * Gets all the available IDs supported. + * @return an array of IDs. + */ + public static synchronized String[] getAvailableIDs() { + String[] resultArray = new String[TimeZoneData.zones.length]; + int count = 0; + for (int i = 0; i < TimeZoneData.zones.length; ++i) + resultArray[count++] = TimeZoneData.zones[i].getID(); + + // copy into array of the right size and return + String[] finalResult = new String[count]; + System.arraycopy(resultArray, 0, finalResult, 0, count); + + return finalResult; + } + + /** + * Gets the platform defined TimeZone ID. + **/ + private static native String getSystemTimeZoneID(String javaHome, + String region); + + /** + * Gets the default TimeZone for this host. + * The source of the default TimeZone + * may vary with implementation. + * @return a default TimeZone. + */ + public static synchronized TimeZone getDefault() { + if (defaultZone == null) { + // get the time zone ID from the system properties + String zoneID = (String) AccessController.doPrivileged( + new GetPropertyAction("user.timezone")); + + // if the time zone ID is not set (yet), perform the + // platform to Java time zone ID mapping. + if (zoneID == null || zoneID.equals("")) { + //String region = (String) AccessController.doPrivileged( + // new GetPropertyAction("user.region")); + //String javaHome = (String) AccessController.doPrivileged( + // new GetPropertyAction("java.home")); + //zoneID = getSystemTimeZoneID(javaHome, region); + + // [icu4j We get the default zone by querying java.util.TimeZone, + // and then attempting to map the ID. - liu ] + java.util.TimeZone _default = java.util.TimeZone.getDefault(); + if (false) System.out.println("java.util.TZ.default " + _default); + zoneID = _default.getID(); + defaultZone = TimeZoneData.get(zoneID); + if (defaultZone == null) { + // [icu4j This means that the zone returned by the JDK does + // not exist in our table. We will, for the moment, map to + // a std zone that has the same raw offset. In the future + // we might find it worthwhile to extract the rules from the + // system default zone, but this is too much trouble for + // now. It will be easier to extend our mapping table to + // match the JDKs we want to support. - liu ] + try { + java.util.SimpleTimeZone s = (java.util.SimpleTimeZone) _default; + defaultZone = new SimpleTimeZone(s.getRawOffset(), s.getID()); + } catch (ClassCastException e) {} + } else { + if (zoneID == null) { + zoneID = GMT_ID; + } + final String id = zoneID; + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + System.setProperty("user.timezone", id); + return null; + } + }); + } + } + if (defaultZone == null) { + defaultZone = getTimeZone(zoneID); + } + if (false) System.out.println("com.ibm.util.TZ.default " + defaultZone); + } + return (TimeZone)defaultZone.clone(); + } + + /** + * Sets the TimeZone that is + * returned by the getDefault method. If zone + * is null, reset the default to the value it had originally when the + * VM first started. + * @param zone the new default time zone + */ + public static synchronized void setDefault(TimeZone zone) + { + defaultZone = zone; + // [icu4j Keep java.util.TimeZone default in sync so java.util.Date + // can interoperate with com.ibm.util classes. This solution + // is _imperfect_; see SimpleTimeZoneAdapter. - liu] + try { + java.util.TimeZone.setDefault( + new SimpleTimeZoneAdapter((SimpleTimeZone) zone)); + } catch (ClassCastException e) {} + } + + /** + * Returns true if this zone has the same rule and offset as another zone. + * That is, if this zone differs only in ID, if at all. Returns false + * if the other zone is null. + * @param other the TimeZone object to be compared with + * @return true if the other zone is not null and is the same as this one, + * with the possible exception of the ID + * @since 1.2 + */ + public boolean hasSameRules(TimeZone other) { + return other != null && getRawOffset() == other.getRawOffset() && + useDaylightTime() == other.useDaylightTime(); + } + + /** + * Overrides Cloneable + */ + public Object clone() + { + try { + TimeZone other = (TimeZone) super.clone(); + other.ID = ID; + return other; + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } + + // =======================privates=============================== + + /** + * The string identifier of this TimeZone. This is a + * programmatic identifier used internally to look up TimeZone + * objects from the system table and also to map them to their localized + * display names. ID values are unique in the system + * table but may not be for dynamically created zones. + * @serial + */ + private String ID; + private static TimeZone defaultZone = null; + + static final String GMT_ID = "GMT"; + private static final int GMT_ID_LENGTH = 3; + private static final String CUSTOM_ID = "Custom"; + + private static NumberFormat numberFormat = null; + + private static final TimeZone GMT = new SimpleTimeZone(0, GMT_ID); + + /** + * Parse a custom time zone identifier and return a corresponding zone. + * @param id a string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or + * GMT[+-]hh. + * @return a newly created SimpleTimeZone with the given offset and + * no daylight savings time, or null if the id cannot be parsed. + */ + private static final SimpleTimeZone parseCustomTimeZone(String id) { + if (id.length() > GMT_ID_LENGTH && + id.regionMatches(true, 0, GMT_ID, 0, GMT_ID_LENGTH)) { + ParsePosition pos = new ParsePosition(GMT_ID_LENGTH); + boolean negative = false; + int offset; + + if (id.charAt(pos.getIndex()) == '-') + negative = true; + else if (id.charAt(pos.getIndex()) != '+') + return null; + pos.setIndex(pos.getIndex() + 1); + + // Create NumberFormat if necessary + synchronized (TimeZoneData.class) { + if (numberFormat == null) { + numberFormat = NumberFormat.getInstance(); + numberFormat.setParseIntegerOnly(true); + } + } + + synchronized (numberFormat) { + // Look for either hh:mm, hhmm, or hh + int start = pos.getIndex(); + Number n = numberFormat.parse(id, pos); + if (n == null) return null; + offset = n.intValue(); + + if (pos.getIndex() < id.length() && + id.charAt(pos.getIndex()) == ':') { + // hh:mm + offset *= 60; + pos.setIndex(pos.getIndex() + 1); + n = numberFormat.parse(id, pos); + if (n == null) return null; + offset += n.intValue(); + } + else { + // hhmm or hh + + // Be strict about interpreting something as hh; it must be + // an offset < 30, and it must be one or two digits. Thus + // 0010 is interpreted as 00:10, but 10 is interpreted as + // 10:00. + if (offset < 30 && (pos.getIndex() - start) <= 2) + offset *= 60; // hh, from 00 to 29; 30 is 00:30 + else + offset = offset % 100 + offset / 100 * 60; // hhmm + } + + if (negative) offset = -offset; + return new SimpleTimeZone(offset * 60000, CUSTOM_ID); + } + } + + return null; + } + + // Internal Implementation Notes [LIU] + // + // TimeZone data is stored in two parts. The first is an encoding of the + // rules for each TimeZone. A TimeZone rule includes the offset of a zone + // in milliseconds from GMT, the starting month and day for daylight savings + // time, if there is any, and the ending month and day for daylight savings + // time. The starting and ending days are specified in terms of the n-th + // day of the week, for instance, the first Sunday or the last ("-1"-th) + // Sunday of the month. The rules are stored as statically-constructed + // SimpleTimeZone objects in the TimeZone class. + // + // Each rule has a unique internal identifier string which is used to + // specify it. This identifier string is arbitrary, and is not to be shown + // to the user -- it is for programmatic use only. In order to instantiate + // a TimeZone object, you pass its identifier string to + // TimeZone.getTimeZone(). (This identifier is also used to index the + // localized string data.) + // + // The second part of the data consists of localized string names used by + // DateFormat to describe various TimeZones. A TimeZone may have up to four + // names: The abbreviated and long name for standard time in that zone, and + // the abbreviated and long name for daylight savings time in that zone. + // The data also includes a representative city. For example, [ "PST", + // "Pacific Standard Time", "PDT", "Pacific Daylight Time", "Los Angeles" ] + // might be one such set of string names in the en_US locale. These strings + // are intended to be shown to the user. The string data is indexed in the + // system by a pair (String id, Locale locale). The id is the unique string + // identifier for the rule for the given TimeZone (as passed to + // TimeZone.getTimeZone()). String names are stored as localized resource + // data of the class java.text.resources.DateFormatZoneData??? where ??? is + // the Locale specifier (e.g., DateFormatZoneData_en_US). This data is a + // two-dimensional array of strings with N rows and 6 columns. The columns + // are id, short standard name, long standard name, short daylight name, + // long daylight name, representative city name. + // + // The mapping between rules (SimpleTimeZone objects) and localized string + // names (DateFormatZoneData objects) is one-to-many. That is, there will + // sometimes be more than one localized string name sets associated with + // each rule. + // + // Each locale can potentially have localized name data for all time zones. + // Since we support approximately 90 time zones and approximately 50 + // locales, there can be over 4500 sets of localized names. In practice, + // only a fraction of these names are provided. If a time zone needs to be + // displayed to the user in a given locale, and there is no string data in + // that locale for that time zone, then the default representation will be + // shown. This is a string of the form GMT+HHMM or GMT-HHMM, where HHMM + // represents the offset in hours and minutes with respect to GMT. This + // format is used because it is recognized in all locales. In order to make + // this mechanism to work, the root resource data (in the class + // DateFormatZoneData) is left empty. + // + // The current default TimeZone is determined via the system property + // user.timezone. This is set by the platform-dependent native code to + // a three-letter abbreviation. We interpret these into our own internal + // IDs using a lookup table. +} + +/** + * Encapsulates data for international timezones. This package-private class is for + * internal use only by TimeZone. It encapsulates the list of recognized international + * timezones. By implementing this as a separate class, the loading and initialization + * cost for this array is delayed until a TimeZone object is actually created from its ID. + * This class contains only static variables and static methods; it cannot be instantiated. + */ +class TimeZoneData +{ + static final TimeZone get(String ID) { + Object o = lookup.get(ID); + return o == null ? null : (TimeZone)((TimeZone)o).clone(); // [sic] + } + + // ---------------- BEGIN GENERATED DATA ---------------- + private static final int ONE_HOUR = 60*60*1000; + + static SimpleTimeZone zones[] = { + // The following data is current as of 1998. + // Total Unix zones: 343 + // Total Java zones: 289 + // Not all Unix zones become Java zones due to duplication and overlap. + //---------------------------------------------------------- + new SimpleTimeZone(-11*ONE_HOUR, "Pacific/Niue" /*NUT*/), + // Pacific/Niue Niue(NU) -11:00 - NUT + //---------------------------------------------------------- + new SimpleTimeZone(-11*ONE_HOUR, "Pacific/Apia" /*WST*/), + // Pacific/Apia W Samoa(WS) -11:00 - WST # W Samoa Time + new SimpleTimeZone(-11*ONE_HOUR, "MIT" /*alias for Pacific/Apia*/), + //---------------------------------------------------------- + new SimpleTimeZone(-11*ONE_HOUR, "Pacific/Pago_Pago" /*SST*/), + // Pacific/Pago_Pago American Samoa(US) -11:00 - SST # S=Samoa + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "Pacific/Tahiti" /*TAHT*/), + // Pacific/Tahiti French Polynesia(PF) -10:00 - TAHT # Tahiti Time + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "Pacific/Fakaofo" /*TKT*/), + // Pacific/Fakaofo Tokelau Is(TK) -10:00 - TKT # Tokelau Time + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "Pacific/Honolulu" /*HST*/), + // Pacific/Honolulu Hawaii(US) -10:00 - HST + new SimpleTimeZone(-10*ONE_HOUR, "HST" /*alias for Pacific/Honolulu*/), + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "America/Adak" /*HA%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Adak Alaska(US) -10:00 US HA%sT + //---------------------------------------------------------- + new SimpleTimeZone(-10*ONE_HOUR, "Pacific/Rarotonga"), + // Zone Pacific/Rarotonga Cook Is(CK) -10:00 Cook CK%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(-9.5*ONE_HOUR), "Pacific/Marquesas" /*MART*/), + // Pacific/Marquesas French Polynesia(PF) -9:30 - MART # Marquesas Time + //---------------------------------------------------------- + new SimpleTimeZone(-9*ONE_HOUR, "Pacific/Gambier" /*GAMT*/), + // Pacific/Gambier French Polynesia(PF) -9:00 - GAMT # Gambier Time + //---------------------------------------------------------- + new SimpleTimeZone(-9*ONE_HOUR, "America/Anchorage" /*AK%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Anchorage Alaska(US) -9:00 US AK%sT + new SimpleTimeZone(-9*ONE_HOUR, "AST" /*alias for America/Anchorage*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone((int)(-8.5*ONE_HOUR), "Pacific/Pitcairn" /*PNT*/), + // Pacific/Pitcairn Pitcairn(PN) -8:30 - PNT # Pitcairn Time + //---------------------------------------------------------- + new SimpleTimeZone(-8*ONE_HOUR, "America/Vancouver" /*P%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Vanc 1962 max - Oct lastSun 2:00 0 S + // Rule Vanc 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Vancouver British Columbia(CA) -8:00 Vanc P%sT + //---------------------------------------------------------- + new SimpleTimeZone(-8*ONE_HOUR, "America/Tijuana" /*P%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mexico 1996 max - Apr Sun>=1 2:00 1:00 D + // Rule Mexico 1996 max - Oct lastSun 2:00 0 S + // America/Tijuana Mexico(MX) -8:00 Mexico P%sT + //---------------------------------------------------------- + new SimpleTimeZone(-8*ONE_HOUR, "America/Los_Angeles" /*P%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Los_Angeles US Pacific time, represented by Los Angeles(US) -8:00 US P%sT + new SimpleTimeZone(-8*ONE_HOUR, "PST" /*alias for America/Los_Angeles*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Dawson_Creek" /*MST*/), + // America/Dawson_Creek British Columbia(CA) -7:00 - MST + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Phoenix" /*MST*/), + // America/Phoenix ?(US) -7:00 - MST + new SimpleTimeZone(-7*ONE_HOUR, "PNT" /*alias for America/Phoenix*/), + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Edmonton" /*M%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Edm 1972 max - Oct lastSun 2:00 0 S + // Rule Edm 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Edmonton Alberta(CA) -7:00 Edm M%sT + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Mazatlan" /*M%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mexico 1996 max - Apr Sun>=1 2:00 1:00 D + // Rule Mexico 1996 max - Oct lastSun 2:00 0 S + // America/Mazatlan Mexico(MX) -7:00 Mexico M%sT + //---------------------------------------------------------- + new SimpleTimeZone(-7*ONE_HOUR, "America/Denver" /*M%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Denver US Mountain time, represented by Denver(US) -7:00 US M%sT + new SimpleTimeZone(-7*ONE_HOUR, "MST" /*alias for America/Denver*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Belize" /*C%sT*/), + // America/Belize Belize(BZ) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Regina" /*CST*/), + // America/Regina Saskatchewan(CA) -6:00 - CST + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "Pacific/Galapagos" /*GALT*/), + // Pacific/Galapagos Ecuador(EC) -6:00 - GALT # Galapagos Time + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Guatemala" /*C%sT*/), + // America/Guatemala Guatemala(GT) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Tegucigalpa" /*C%sT*/), + // America/Tegucigalpa Honduras(HN) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/El_Salvador" /*C%sT*/), + // America/El_Salvador El Salvador(SV) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Costa_Rica" /*C%sT*/), + // America/Costa_Rica Costa Rica(CR) -6:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg" /*C%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Winn 1966 max - Oct lastSun 2:00 0 S + // Rule Winn 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Winnipeg Manitoba(CA) -6:00 Winn C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "Pacific/Easter" /*EAS%sT*/, + Calendar.OCTOBER, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.MARCH, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Chile 1969 max - Oct Sun>=9 0:00 1:00 S + // Rule Chile 1970 max - Mar Sun>=9 0:00 0 - + // Pacific/Easter Chile(CL) -6:00 Chile EAS%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Mexico_City" /*C%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mexico 1996 max - Apr Sun>=1 2:00 1:00 D + // Rule Mexico 1996 max - Oct lastSun 2:00 0 S + // America/Mexico_City Mexico(MX) -6:00 Mexico C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-6*ONE_HOUR, "America/Chicago" /*C%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Chicago US Central time, represented by Chicago(US) -6:00 US C%sT + new SimpleTimeZone(-6*ONE_HOUR, "CST" /*alias for America/Chicago*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Porto_Acre" /*AST*/), + // America/Porto_Acre Brazil(BR) -5:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Bogota" /*CO%sT*/), + // America/Bogota Colombia(CO) -5:00 - CO%sT # Colombia Time + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Guayaquil" /*ECT*/), + // America/Guayaquil Ecuador(EC) -5:00 - ECT # Ecuador Time + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Jamaica" /*EST*/), + // America/Jamaica Jamaica(JM) -5:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Cayman" /*EST*/), + // America/Cayman Cayman Is(KY) -5:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Managua" /*EST*/), + // America/Managua Nicaragua(NI) -5:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Panama" /*EST*/), + // America/Panama Panama(PA) -5:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Lima" /*PE%sT*/), + // America/Lima Peru(PE) -5:00 - PE%sT # Peru Time + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Indianapolis" /*EST*/), + // America/Indianapolis Indiana(US) -5:00 - EST + new SimpleTimeZone(-5*ONE_HOUR, "IET" /*alias for America/Indianapolis*/), + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Nassau" /*E%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Bahamas 1964 max - Oct lastSun 2:00 0 S + // Rule Bahamas 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Nassau Bahamas(BS) -5:00 Bahamas E%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Montreal" /*E%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mont 1957 max - Oct lastSun 2:00 0 S + // Rule Mont 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Montreal Ontario, Quebec(CA) -5:00 Mont E%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Havana", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule Cuba 1998 max - Mar lastSun 0:00s 1:00 D + // Rule Cuba 1998 max - Oct lastSun 0:00s 0 S + // Zone America/Havana Cuba(CU) -5:00 Cuba C%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Port-au-Prince"), + // Zone America/Port-au-Prince Haiti(HT) -5:00 Haiti E%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/Grand_Turk" /*E%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule TC 1979 max - Oct lastSun 0:00 0 S + // Rule TC 1987 max - Apr Sun>=1 0:00 1:00 D + // America/Grand_Turk Turks and Caicos(TC) -5:00 TC E%sT + //---------------------------------------------------------- + new SimpleTimeZone(-5*ONE_HOUR, "America/New_York" /*E%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule US 1967 max - Oct lastSun 2:00 0 S + // Rule US 1987 max - Apr Sun>=1 2:00 1:00 D + // America/New_York US Eastern time, represented by New York(US) -5:00 US E%sT + new SimpleTimeZone(-5*ONE_HOUR, "EST" /*alias for America/New_York*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Antigua" /*AST*/), + // America/Antigua Antigua and Barbuda(AG) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Anguilla" /*AST*/), + // America/Anguilla Anguilla(AI) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Curacao" /*AST*/), + // America/Curacao Curacao(AN) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Aruba" /*AST*/), + // America/Aruba Aruba(AW) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Barbados" /*A%sT*/), + // America/Barbados Barbados(BB) -4:00 - A%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/La_Paz" /*BOT*/), + // America/La_Paz Bolivia(BO) -4:00 - BOT # Bolivia Time + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Manaus" /*WST*/), + // America/Manaus Brazil(BR) -4:00 - WST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Dominica" /*AST*/), + // America/Dominica Dominica(DM) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Santo_Domingo" /*AST*/), + // America/Santo_Domingo Dominican Republic(DO) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Grenada" /*AST*/), + // America/Grenada Grenada(GD) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Guadeloupe" /*AST*/), + // America/Guadeloupe Guadeloupe(GP) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Guyana" /*GYT*/), + // America/Guyana Guyana(GY) -4:00 - GYT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/St_Kitts" /*AST*/), + // America/St_Kitts St Kitts-Nevis(KN) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/St_Lucia" /*AST*/), + // America/St_Lucia St Lucia(LC) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Martinique" /*AST*/), + // America/Martinique Martinique(MQ) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Montserrat" /*AST*/), + // America/Montserrat Montserrat(MS) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Puerto_Rico" /*AST*/), + // America/Puerto_Rico Puerto Rico(PR) -4:00 - AST + new SimpleTimeZone(-4*ONE_HOUR, "PRT" /*alias for America/Puerto_Rico*/), + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Port_of_Spain" /*AST*/), + // America/Port_of_Spain Trinidad and Tobago(TT) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/St_Vincent" /*AST*/), + // America/St_Vincent St Vincent and the Grenadines(VC) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Tortola" /*AST*/), + // America/Tortola British Virgin Is(VG) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/St_Thomas" /*AST*/), + // America/St_Thomas Virgin Is(VI) -4:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Caracas" /*VET*/), + // America/Caracas Venezuela(VE) -4:00 - VET + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "Antarctica/Palmer" /*CL%sT*/, + Calendar.OCTOBER, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.MARCH, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule ChileAQ 1969 max - Oct Sun>=9 0:00 1:00 S + // Rule ChileAQ 1970 max - Mar Sun>=9 0:00 0 - + // Antarctica/Palmer USA - year-round bases(AQ) -4:00 ChileAQ CL%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "Atlantic/Bermuda" /*A%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Bahamas 1964 max - Oct lastSun 2:00 0 S + // Rule Bahamas 1987 max - Apr Sun>=1 2:00 1:00 D + // Atlantic/Bermuda Bermuda(BM) -4:00 Bahamas A%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Cuiaba"), + // Zone America/Cuiaba Brazil(BR) -4:00 - WST + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Halifax" /*A%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Halifax 1962 max - Oct lastSun 2:00 0 S + // Rule Halifax 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Halifax ?(CA) -4:00 Halifax A%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "Atlantic/Stanley" /*FK%sT*/, + Calendar.SEPTEMBER, 8, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.APRIL, 16, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Falk 1986 max - Apr Sun>=16 0:00 0 - + // Rule Falk 1996 max - Sep Sun>=8 0:00 1:00 S + // Atlantic/Stanley Falklands(FK) -4:00 Falk FK%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Thule" /*A%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Thule 1993 max - Apr Sun>=1 2:00 1:00 D + // Rule Thule 1993 max - Oct lastSun 2:00 0 S + // America/Thule ?(GL) -4:00 Thule A%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion", + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.FEBRUARY, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Para 1996 max - Oct Sun>=1 0:00 1:00 S + // Rule Para 1999 max - Feb lastSun 0:00 0 - + // Zone America/Asuncion Paraguay(PY) -4:00 Para PY%sT + //---------------------------------------------------------- + new SimpleTimeZone(-4*ONE_HOUR, "America/Santiago" /*CL%sT*/, + Calendar.OCTOBER, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, + Calendar.MARCH, 9, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Chile 1969 max - Oct Sun>=9 0:00 1:00 S + // Rule Chile 1970 max - Mar Sun>=9 0:00 0 - + // America/Santiago Chile(CL) -4:00 Chile CL%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(-3.5*ONE_HOUR), "America/St_Johns" /*N%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule StJohns 1960 max - Oct lastSun 2:00 0 S + // Rule StJohns 1989 max - Apr Sun>=1 2:00 1:00 D + // America/St_Johns Canada(CA) -3:30 StJohns N%sT + new SimpleTimeZone((int)(-3.5*ONE_HOUR), "CNT" /*alias for America/St_Johns*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Fortaleza" /*EST*/), + // America/Fortaleza Brazil(BR) -3:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Cayenne" /*GFT*/), + // America/Cayenne French Guiana(GF) -3:00 - GFT + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Paramaribo" /*SRT*/), + // America/Paramaribo Suriname(SR) -3:00 - SRT + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Montevideo" /*UY%sT*/), + // America/Montevideo Uruguay(UY) -3:00 - UY%sT + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Buenos_Aires" /*AR%sT*/), + // America/Buenos_Aires Argentina(AR) -3:00 - AR%sT + new SimpleTimeZone(-3*ONE_HOUR, "AGT" /*alias for America/Buenos_Aires*/), + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Godthab", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone America/Godthab ?(GL) -3:00 EU WG%sT + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Miquelon" /*PM%sT*/, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Mont 1957 max - Oct lastSun 2:00 0 S + // Rule Mont 1987 max - Apr Sun>=1 2:00 1:00 D + // America/Miquelon St Pierre and Miquelon(PM) -3:00 Mont PM%sT # Pierre & Miquelon Time + //---------------------------------------------------------- + new SimpleTimeZone(-3*ONE_HOUR, "America/Sao_Paulo", + Calendar.OCTOBER, 8, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.FEBRUARY, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Brazil 1998 max - Oct Sun>=8 0:00 1:00 D + // Rule Brazil 1999 max - Feb Sun>=15 0:00 0 S + // Zone America/Sao_Paulo Brazil(BR) -3:00 Brazil E%sT + new SimpleTimeZone(-3*ONE_HOUR, "BET" /*alias for America/Sao_Paulo*/, + Calendar.OCTOBER, 8, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.FEBRUARY, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(-2*ONE_HOUR, "America/Noronha" /*FST*/), + // America/Noronha Brazil(BR) -2:00 - FST + //---------------------------------------------------------- + new SimpleTimeZone(-2*ONE_HOUR, "Atlantic/South_Georgia" /*GST*/), + // Atlantic/South_Georgia South Georgia(GS) -2:00 - GST # South Georgia Time + //---------------------------------------------------------- + new SimpleTimeZone(-1*ONE_HOUR, "Atlantic/Jan_Mayen" /*EGT*/), + // Atlantic/Jan_Mayen ?(NO) -1:00 - EGT + //---------------------------------------------------------- + new SimpleTimeZone(-1*ONE_HOUR, "Atlantic/Cape_Verde" /*CVT*/), + // Atlantic/Cape_Verde Cape Verde(CV) -1:00 - CVT + //---------------------------------------------------------- + new SimpleTimeZone(-1*ONE_HOUR, "America/Scoresbysund", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone America/Scoresbysund ?(GL) -1:00 EU EG%sT + //---------------------------------------------------------- + new SimpleTimeZone(-1*ONE_HOUR, "Atlantic/Azores", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Atlantic/Azores Portugal(PT) -1:00 EU AZO%sT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Ouagadougou" /*GMT*/), + // Africa/Ouagadougou Burkina Faso(BF) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Abidjan" /*GMT*/), + // Africa/Abidjan Cote D'Ivoire(CI) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Accra" /*%s*/), + // Africa/Accra Ghana(GH) 0:00 - %s + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Banjul" /*GMT*/), + // Africa/Banjul Gambia(GM) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Conakry" /*GMT*/), + // Africa/Conakry Guinea(GN) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Bissau" /*GMT*/), + // Africa/Bissau Guinea-Bissau(GW) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Atlantic/Reykjavik" /*GMT*/), + // Atlantic/Reykjavik Iceland(IS) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Monrovia" /*GMT*/), + // Africa/Monrovia Liberia(LR) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Casablanca" /*WET*/), + // Africa/Casablanca Morocco(MA) 0:00 - WET + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Timbuktu" /*GMT*/), + // Africa/Timbuktu Mali(ML) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Nouakchott" /*GMT*/), + // Africa/Nouakchott Mauritania(MR) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Atlantic/St_Helena" /*GMT*/), + // Atlantic/St_Helena St Helena(SH) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Freetown" /*%s*/), + // Africa/Freetown Sierra Leone(SL) 0:00 - %s + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Dakar" /*GMT*/), + // Africa/Dakar Senegal(SN) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Sao_Tome" /*GMT*/), + // Africa/Sao_Tome Sao Tome and Principe(ST) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Africa/Lome" /*GMT*/), + // Africa/Lome Togo(TG) 0:00 - GMT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "GMT" /*GMT*/), + // GMT -(-) 0:00 - GMT + new SimpleTimeZone(0*ONE_HOUR, "UTC" /*alias for GMT*/), + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Atlantic/Faeroe", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Atlantic/Faeroe Denmark, Faeroe Islands, and Greenland(DK) 0:00 EU WE%sT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Atlantic/Canary", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Atlantic/Canary Spain(ES) 0:00 EU WE%sT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Europe/Dublin", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Dublin ---(IE) 0:00 EU GMT/IST + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Europe/Lisbon", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Lisbon Portugal(PT) 0:00 EU WE%sT + //---------------------------------------------------------- + new SimpleTimeZone(0*ONE_HOUR, "Europe/London", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/London ---(GB) 0:00 EU GMT/BST + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Luanda" /*WAT*/), + // Africa/Luanda Angola(AO) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Porto-Novo" /*WAT*/), + // Africa/Porto-Novo Benin(BJ) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Bangui" /*WAT*/), + // Africa/Bangui Central African Republic(CF) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Kinshasa" /*WAT*/), + // Africa/Kinshasa Democratic Republic of Congo(CG) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Douala" /*WAT*/), + // Africa/Douala Cameroon(CM) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Libreville" /*WAT*/), + // Africa/Libreville Gabon(GA) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Malabo" /*WAT*/), + // Africa/Malabo Equatorial Guinea(GQ) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Niamey" /*WAT*/), + // Africa/Niamey Niger(NE) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Lagos" /*WAT*/), + // Africa/Lagos Nigeria(NG) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Ndjamena" /*WAT*/), + // Africa/Ndjamena Chad(TD) 1:00 - WAT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Tunis" /*CE%sT*/), + // Africa/Tunis Tunisia(TN) 1:00 - CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Algiers" /*CET*/), + // Africa/Algiers Algeria(DZ) 1:00 - CET + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Andorra", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Andorra Andorra(AD) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Tirane", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Tirane Albania(AL) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Vienna", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Vienna Austria(AT) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Brussels", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Brussels Belgium(BE) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Zurich", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Zurich Switzerland(CH) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Prague", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Prague Czech Republic(CZ) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Berlin", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Berlin Germany(DE) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Copenhagen", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Copenhagen Denmark, Faeroe Islands, and Greenland(DK) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Madrid", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Madrid Spain(ES) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Gibraltar", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Gibraltar Gibraltar(GI) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Budapest", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Budapest Hungary(HU) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Rome", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Rome Italy(IT) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Vaduz", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Vaduz Liechtenstein(LI) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Luxembourg", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Luxembourg Luxembourg(LU) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Tripoli"), + // Zone Africa/Tripoli Libya(LY) 2:00 - EET + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Monaco", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Monaco Monaco(MC) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Malta", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Malta Malta(MT) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Africa/Windhoek" /*WA%sT*/, + Calendar.SEPTEMBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.APRIL, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, 1*ONE_HOUR), + // Rule Namibia 1994 max - Sep Sun>=1 2:00 1:00 S + // Rule Namibia 1995 max - Apr Sun>=1 2:00 0 - + // Africa/Windhoek Namibia(NA) 1:00 Namibia WA%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Amsterdam", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Amsterdam Netherlands(NL) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Oslo", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Oslo Norway(NO) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Warsaw", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Warsaw 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Stockholm", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Stockholm Sweden(SE) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Belgrade", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Belgrade Yugoslavia(YU) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Paris", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Paris France(FR) 1:00 EU CE%sT + new SimpleTimeZone(1*ONE_HOUR, "ECT" /*alias for Europe/Paris*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Bujumbura" /*CAT*/), + // Africa/Bujumbura Burundi(BI) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Gaborone" /*CAT*/), + // Africa/Gaborone Botswana(BW) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Lubumbashi" /*CAT*/), + // Africa/Lubumbashi Democratic Republic of Congo(CG) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Maseru" /*SAST*/), + // Africa/Maseru Lesotho(LS) 2:00 - SAST + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Blantyre" /*CAT*/), + // Africa/Blantyre Malawi(ML) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Maputo" /*CAT*/), + // Africa/Maputo Mozambique(MZ) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Kigali" /*CAT*/), + // Africa/Kigali Rwanda(RW) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Khartoum" /*CA%sT*/), + // Africa/Khartoum Sudan(SD) 2:00 - CA%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Mbabane" /*SAST*/), + // Africa/Mbabane Swaziland(SZ) 2:00 - SAST + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Lusaka" /*CAT*/), + // Africa/Lusaka Zambia(ZM) 2:00 - CAT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Harare" /*CAT*/), + // Africa/Harare Zimbabwe(ZW) 2:00 - CAT + new SimpleTimeZone(2*ONE_HOUR, "CAT" /*alias for Africa/Harare*/), + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Johannesburg" /*SAST*/), + // Africa/Johannesburg South Africa(ZA) 2:00 - SAST + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Sofia" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-Eur 1996 max - Oct lastSun 0:00 0 - + // Europe/Sofia Bulgaria(BG) 2:00 E-Eur EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Minsk" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Europe/Minsk Belarus(BY) 2:00 Russia EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Nicosia", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EUAsia 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EUAsia 1996 max - Oct lastSun 1:00u 0 - + // Zone Asia/Nicosia Cyprus(CY) 2:00 EUAsia EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Tallinn", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Tallinn Estonia(EE) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Africa/Cairo", + Calendar.APRIL, 22, -Calendar.FRIDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.SEPTEMBER, -1, Calendar.THURSDAY /*DOW_IN_MON*/, 23*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule Egypt 1995 max - Apr Fri>=22 0:00s 1:00 S + // Rule Egypt 1995 max - Sep lastThu 23:00s 0 - + // Zone Africa/Cairo Egypt(EG) 2:00 Egypt EE%sT + new SimpleTimeZone(2*ONE_HOUR, "ART" /*alias for Africa/Cairo*/, + Calendar.APRIL, 22, -Calendar.FRIDAY /*DOW>=DOM*/, 0*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.SEPTEMBER, -1, Calendar.THURSDAY /*DOW_IN_MON*/, 23*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Helsinki", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Helsinki Finland(FI) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Athens", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Athens Greece(GR) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Jerusalem", + Calendar.APRIL, 1, -Calendar.FRIDAY /*DOW>=DOM*/, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.SEPTEMBER, 1, -Calendar.FRIDAY /*DOW>=DOM*/, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Zion 2000 max - Apr Fri>=1 2:00 1:00 D + // Rule Zion 2000 max - Sep Fri>=1 2:00 0 S + // Zone Asia/Jerusalem Israel(IL) 2:00 Zion I%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Amman"), + // Zone Asia/Amman 2:00 Jordan EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Beirut" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.SEPTEMBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Lebanon 1993 max - Mar lastSun 0:00 1:00 S + // Rule Lebanon 1993 max - Sep lastSun 0:00 0 - + // Asia/Beirut Lebanon(LB) 2:00 Lebanon EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(1*ONE_HOUR, "Europe/Vilnius", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Vilnius Lithuania(LT) 1:00 EU CE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Riga", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Riga Latvia(LV) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Chisinau" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-Eur 1996 max - Oct lastSun 0:00 0 - + // Europe/Chisinau Moldova(MD) 2:00 E-Eur EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Bucharest" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-Eur 1996 max - Oct lastSun 0:00 0 - + // Europe/Bucharest Romania(RO) 2:00 E-Eur EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Kaliningrad" /*EE%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Europe/Kaliningrad Russia(RU) 2:00 Russia EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/, + Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Syria 1994 max - Apr 1 0:00 1:00 S + // Rule Syria 1994 max - Oct 1 0:00 0 - + // Asia/Damascus Syria(SY) 2:00 Syria EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Kiev", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Kiev Ukraine(UA) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Istanbul", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Istanbul Turkey(TR) 2:00 EU EE%sT + new SimpleTimeZone(2*ONE_HOUR, "EET" /*alias for Europe/Istanbul*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Bahrain" /*AST*/), + // Asia/Bahrain Bahrain(BH) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Djibouti" /*EAT*/), + // Africa/Djibouti Djibouti(DJ) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Asmera" /*EAT*/), + // Africa/Asmera Eritrea(ER) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Addis_Ababa" /*EAT*/), + // Africa/Addis_Ababa Ethiopia(ET) 3:00 - EAT + new SimpleTimeZone(3*ONE_HOUR, "EAT" /*alias for Africa/Addis_Ababa*/), + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Nairobi" /*EAT*/), + // Africa/Nairobi Kenya(KE) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Indian/Comoro" /*EAT*/), + // Indian/Comoro Comoros(KM) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Kuwait" /*AST*/), + // Asia/Kuwait Kuwait(KW) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Indian/Antananarivo" /*EAT*/), + // Indian/Antananarivo Madagascar(MK) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Qatar" /*AST*/), + // Asia/Qatar Qatar(QA) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Mogadishu" /*EAT*/), + // Africa/Mogadishu Somalia(SO) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Dar_es_Salaam" /*EAT*/), + // Africa/Dar_es_Salaam Tanzania(TZ) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Africa/Kampala" /*EAT*/), + // Africa/Kampala Uganda(UG) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Aden" /*AST*/), + // Asia/Aden Yemen(YE) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Indian/Mayotte" /*EAT*/), + // Indian/Mayotte Mayotte(YT) 3:00 - EAT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Riyadh" /*AST*/), + // Asia/Riyadh Saudi Arabia(SA) 3:00 - AST + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Asia/Baghdad" /*A%sT*/, + Calendar.APRIL, 1, 0 /*DOM*/, 3*ONE_HOUR, + Calendar.OCTOBER, 1, 0 /*DOM*/, 4*ONE_HOUR, 1*ONE_HOUR), + // Rule Iraq 1991 max - Apr 1 3:00s 1:00 D + // Rule Iraq 1991 max - Oct 1 3:00s 0 D + // Asia/Baghdad Iraq(IQ) 3:00 Iraq A%sT + //---------------------------------------------------------- + new SimpleTimeZone(2*ONE_HOUR, "Europe/Simferopol", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.UTC_TIME, 1*ONE_HOUR), + // Rule EU 1981 max - Mar lastSun 1:00u 1:00 S + // Rule EU 1996 max - Oct lastSun 1:00u 0 - + // Zone Europe/Simferopol Ukraine(UA) 2:00 EU EE%sT + //---------------------------------------------------------- + new SimpleTimeZone(3*ONE_HOUR, "Europe/Moscow" /*MSK/MSD*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Europe/Moscow Russia(RU) 3:00 Russia MSK/MSD + //---------------------------------------------------------- + new SimpleTimeZone((int)(3.5*ONE_HOUR), "Asia/Tehran", + Calendar.MARCH, 20, 0 /*DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.SEPTEMBER, 22, 0 /*DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Iran 2000 only - Mar 20 0:00 1:00 S + // Rule Iran 2000 only - Sep 22 0:00 0 - + // Zone Asia/Tehran Iran(IR) 3:30 Iran IR%sT + new SimpleTimeZone((int)(3.5*ONE_HOUR), "MET" /*alias for Asia/Tehran*/, + Calendar.MARCH, 20, 0 /*DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.SEPTEMBER, 22, 0 /*DOM*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Dubai" /*GST*/), + // Asia/Dubai United Arab Emirates(AE) 4:00 - GST + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Indian/Mauritius" /*MUT*/), + // Indian/Mauritius Mauritius(MU) 4:00 - MUT # Mauritius Time + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Muscat" /*GST*/), + // Asia/Muscat Oman(OM) 4:00 - GST + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Indian/Reunion" /*RET*/), + // Indian/Reunion Reunion(RE) 4:00 - RET # Reunion Time + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Indian/Mahe" /*SCT*/), + // Indian/Mahe Seychelles(SC) 4:00 - SCT # Seychelles Time + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Yerevan", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule RussiaAsia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule RussiaAsia 1996 max - Oct lastSun 2:00s 0 - + // Zone Asia/Yerevan Armenia(AM) 4:00 RussiaAsia AM%sT + new SimpleTimeZone(4*ONE_HOUR, "NET" /*alias for Asia/Yerevan*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Baku", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 1*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Azer 1997 max - Mar lastSun 1:00 1:00 S + // Rule Azer 1997 max - Oct lastSun 1:00 0 - + // Zone Asia/Baku Azerbaijan(AZ) 4:00 Azer AZ%sT + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Aqtau" /*AQT%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 - + // Asia/Aqtau Kazakhstan(KZ) 4:00 E-EurAsia AQT%sT + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Europe/Samara" /*SAM%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Europe/Samara Russia(RU) 4:00 Russia SAM%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(4.5*ONE_HOUR), "Asia/Kabul" /*AFT*/), + // Asia/Kabul Afghanistan(AF) 4:30 - AFT + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Indian/Kerguelen" /*TFT*/), + // Indian/Kerguelen France - year-round bases(FR) 5:00 - TFT # ISO code TF Time + //---------------------------------------------------------- + new SimpleTimeZone(4*ONE_HOUR, "Asia/Tbilisi", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 - + // Zone Asia/Tbilisi Georgia(GE) 4:00 E-EurAsia GE%sT + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Indian/Chagos" /*IOT*/), + // Indian/Chagos British Indian Ocean Territory(IO) 5:00 - IOT # BIOT Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Indian/Maldives" /*MVT*/), + // Indian/Maldives Maldives(MV) 5:00 - MVT # Maldives Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Dushanbe" /*TJT*/), + // Asia/Dushanbe Tajikistan(TJ) 5:00 - TJT # Tajikistan Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Ashkhabad" /*TMT*/), + // Asia/Ashkhabad Turkmenistan(TM) 5:00 - TMT # Turkmenistan Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Tashkent" /*UZT*/), + // Asia/Tashkent Uzbekistan(UZ) 5:00 - UZT # Uzbekistan Time + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Karachi" /*PKT*/), + // Asia/Karachi Pakistan(PK) 5:00 - PKT # Pakistan Time + new SimpleTimeZone(5*ONE_HOUR, "PLT" /*alias for Asia/Karachi*/), + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Bishkek", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, (int)(2.5*ONE_HOUR), SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, (int)(2.5*ONE_HOUR), SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Kirgiz 1997 max - Mar lastSun 2:30 1:00 S + // Rule Kirgiz 1997 max - Oct lastSun 2:30 0 - + // Zone Asia/Bishkek Kirgizstan(KG) 5:00 Kirgiz KG%sT + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Aqtobe" /*AQT%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 - + // Asia/Aqtobe Kazakhstan(KZ) 5:00 E-EurAsia AQT%sT + //---------------------------------------------------------- + new SimpleTimeZone(5*ONE_HOUR, "Asia/Yekaterinburg" /*YEK%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Yekaterinburg Russia(RU) 5:00 Russia YEK%sT # Yekaterinburg Time + //---------------------------------------------------------- + new SimpleTimeZone((int)(5.5*ONE_HOUR), "Asia/Calcutta" /*IST*/), + // Asia/Calcutta India(IN) 5:30 - IST + new SimpleTimeZone((int)(5.5*ONE_HOUR), "IST" /*alias for Asia/Calcutta*/), + //---------------------------------------------------------- + new SimpleTimeZone((int)(5.75*ONE_HOUR), "Asia/Katmandu" /*NPT*/), + // Asia/Katmandu Nepal(NP) 5:45 - NPT # Nepal Time + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Antarctica/Mawson" /*MAWT*/), + // Antarctica/Mawson Australia - territories(AQ) 6:00 - MAWT # Mawson Time + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Thimbu" /*BTT*/), + // Asia/Thimbu Bhutan(BT) 6:00 - BTT # Bhutan Time + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Colombo" /*LKT*/), + // Asia/Colombo Sri Lanka(LK) 6:00 - LKT + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Dacca" /*BDT*/), + // Asia/Dacca Bangladesh(BD) 6:00 - BDT # Bangladesh Time + new SimpleTimeZone(6*ONE_HOUR, "BST" /*alias for Asia/Dacca*/), + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Almaty", + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 0*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S + // Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 - + // Zone Asia/Almaty 6:00 E-EurAsia ALM%sT + //---------------------------------------------------------- + new SimpleTimeZone(6*ONE_HOUR, "Asia/Novosibirsk" /*NOV%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Novosibirsk Russia(RU) 6:00 Russia NOV%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(6.5*ONE_HOUR), "Indian/Cocos" /*CCT*/), + // Indian/Cocos Cocos(CC) 6:30 - CCT # Cocos Islands Time + //---------------------------------------------------------- + new SimpleTimeZone((int)(6.5*ONE_HOUR), "Asia/Rangoon" /*MMT*/), + // Asia/Rangoon Burma / Myanmar(MM) 6:30 - MMT # Myanmar Time + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Indian/Christmas" /*CXT*/), + // Indian/Christmas Australian miscellany(AU) 7:00 - CXT # Christmas Island Time + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Jakarta" /*JAVT*/), + // Asia/Jakarta Indonesia(ID) 7:00 - JAVT + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Phnom_Penh" /*ICT*/), + // Asia/Phnom_Penh Cambodia(KH) 7:00 - ICT + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Vientiane" /*ICT*/), + // Asia/Vientiane Laos(LA) 7:00 - ICT + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Saigon" /*ICT*/), + // Asia/Saigon Vietnam(VN) 7:00 - ICT + new SimpleTimeZone(7*ONE_HOUR, "VST" /*alias for Asia/Saigon*/), + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Bangkok" /*ICT*/), + // Asia/Bangkok Thailand(TH) 7:00 - ICT + //---------------------------------------------------------- + new SimpleTimeZone(7*ONE_HOUR, "Asia/Krasnoyarsk" /*KRA%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Krasnoyarsk Russia(RU) 7:00 Russia KRA%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Antarctica/Casey" /*WST*/), + // Antarctica/Casey Australia - territories(AQ) 8:00 - WST # Western (Aus) Standard Time + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Australia/Perth" /*WST*/), + // Australia/Perth Australia(AU) 8:00 - WST + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Brunei" /*BNT*/), + // Asia/Brunei Brunei(BN) 8:00 - BNT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Hong_Kong" /*C%sT*/), + // Asia/Hong_Kong China(HK) 8:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Ujung_Pandang" /*BORT*/), + // Asia/Ujung_Pandang Indonesia(ID) 8:00 - BORT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Macao" /*C%sT*/), + // Asia/Macao Macao(MO) 8:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Kuala_Lumpur" /*MYT*/), + // Asia/Kuala_Lumpur Malaysia(MY) 8:00 - MYT # Malaysia Time + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Manila" /*PH%sT*/), + // Asia/Manila Philippines(PH) 8:00 - PH%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Singapore" /*SGT*/), + // Asia/Singapore Singapore(SG) 8:00 - SGT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Taipei" /*C%sT*/), + // Asia/Taipei Taiwan(TW) 8:00 - C%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Shanghai" /*C%sT*/), + // Asia/Shanghai China(CN) 8:00 - C%sT + new SimpleTimeZone(8*ONE_HOUR, "CTT" /*alias for Asia/Shanghai*/), + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Ulan_Bator" /*ULA%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, + Calendar.SEPTEMBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), + // Rule Mongol 1991 max - Mar lastSun 0:00 1:00 S + // Rule Mongol 1997 max - Sep lastSun 0:00 0 - + // Asia/Ulan_Bator Mongolia(MN) 8:00 Mongol ULA%sT + //---------------------------------------------------------- + new SimpleTimeZone(8*ONE_HOUR, "Asia/Irkutsk" /*IRK%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Irkutsk Russia(RU) 8:00 Russia IRK%sT + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Jayapura" /*JAYT*/), + // Asia/Jayapura Indonesia(ID) 9:00 - JAYT + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Pyongyang" /*KST*/), + // Asia/Pyongyang ?(KP) 9:00 - KST + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Seoul" /*K%sT*/), + // Asia/Seoul ?(KR) 9:00 - K%sT + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Pacific/Palau" /*PWT*/), + // Pacific/Palau Palau(PW) 9:00 - PWT # Palau Time + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Tokyo" /*JST*/), + // Asia/Tokyo Japan(JP) 9:00 - JST + new SimpleTimeZone(9*ONE_HOUR, "JST" /*alias for Asia/Tokyo*/), + //---------------------------------------------------------- + new SimpleTimeZone(9*ONE_HOUR, "Asia/Yakutsk" /*YAK%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Yakutsk Russia(RU) 9:00 Russia YAK%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(9.5*ONE_HOUR), "Australia/Darwin" /*CST*/), + // Australia/Darwin Australia(AU) 9:30 - CST + new SimpleTimeZone((int)(9.5*ONE_HOUR), "ACT" /*alias for Australia/Darwin*/), + //---------------------------------------------------------- + new SimpleTimeZone((int)(9.5*ONE_HOUR), "Australia/Adelaide", + Calendar.AUGUST, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule AS 2000 only - Aug lastSun 2:00s 1:00 - + // Rule AS 1995 max - Mar lastSun 2:00s 0 - + // Zone Australia/Adelaide 9:30 AS CST + //---------------------------------------------------------- + new SimpleTimeZone((int)(9.5*ONE_HOUR), "Australia/Broken_Hill", + Calendar.AUGUST, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule AN 2000 only - Aug lastSun 2:00s 1:00 - + // Rule AN 1996 max - Mar lastSun 2:00s 0 - + // Zone Australia/Broken_Hill 9:30 AN CST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Australia/Hobart", + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule AT 1991 max - Oct Sun>=1 2:00s 1:00 - + // Rule AT 1991 max - Mar lastSun 2:00s 0 - + // Australia/Hobart 10:00 AT EST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Antarctica/DumontDUrville" /*DDUT*/), + // Antarctica/DumontDUrville France - year-round bases(AQ) 10:00 - DDUT # Dumont-d'Urville Time + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Pacific/Truk" /*TRUT*/), + // Pacific/Truk Micronesia(FM) 10:00 - TRUT # Truk Time + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Pacific/Guam" /*GST*/), + // Pacific/Guam Guam(GU) 10:00 - GST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Pacific/Saipan" /*MPT*/), + // Pacific/Saipan N Mariana Is(MP) 10:00 - MPT + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Pacific/Port_Moresby" /*PGT*/), + // Pacific/Port_Moresby Papua New Guinea(PG) 10:00 - PGT # Papua New Guinea Time + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Australia/Brisbane" /*EST*/), + // Australia/Brisbane Australia(AU) 10:00 - EST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Asia/Vladivostok" /*VLA%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Vladivostok Russia(RU) 10:00 Russia VLA%sT + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "Australia/Sydney", + Calendar.AUGUST, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + // Rule AN 2000 only - Aug lastSun 2:00s 1:00 - + // Rule AN 1996 max - Mar lastSun 2:00s 0 - + // Zone Australia/Sydney 10:00 AN EST + //---------------------------------------------------------- + new SimpleTimeZone(10*ONE_HOUR, "AET" /*alias for Australia/Sydney*/, + Calendar.AUGUST, 26, 0 /*DOM*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone((int)(10.5*ONE_HOUR), "Australia/Lord_Howe", + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, (int)(0.5*ONE_HOUR)), + // Rule LH 1987 max - Oct lastSun 2:00s 0:30 - + // Rule LH 1996 max - Mar lastSun 2:00s 0 - + // Zone Australia/Lord_Howe Lord Howe Island(AU) 10:30 LH LHST + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Pacific/Ponape" /*PONT*/), + // Pacific/Ponape Micronesia(FM) 11:00 - PONT # Ponape Time + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Pacific/Efate" /*VU%sT*/), + // Pacific/Efate Vanuatu(VU) 11:00 - VU%sT # Vanuatu Time + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Pacific/Guadalcanal" /*SBT*/), + // Pacific/Guadalcanal Solomon Is(SB) 11:00 - SBT # Solomon Is Time + new SimpleTimeZone(11*ONE_HOUR, "SST" /*alias for Pacific/Guadalcanal*/), + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Pacific/Noumea"), + // Zone Pacific/Noumea New Caledonia(NC) 11:00 NC NC%sT + //---------------------------------------------------------- + new SimpleTimeZone(11*ONE_HOUR, "Asia/Magadan" /*MAG%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Magadan Russia(RU) 11:00 Russia MAG%sT + //---------------------------------------------------------- + new SimpleTimeZone((int)(11.5*ONE_HOUR), "Pacific/Norfolk" /*NFT*/), + // Pacific/Norfolk Norfolk(NF) 11:30 - NFT # Norfolk Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Kosrae" /*KOST*/), + // Pacific/Kosrae Micronesia(FM) 12:00 - KOST # Kosrae Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Tarawa" /*GILT*/), + // Pacific/Tarawa Kiribati(KI) 12:00 - GILT # Gilbert Is Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Majuro" /*MHT*/), + // Pacific/Majuro Marshall Is(MH) 12:00 - MHT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Nauru" /*NRT*/), + // Pacific/Nauru Nauru(NR) 12:00 - NRT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Funafuti" /*TVT*/), + // Pacific/Funafuti Tuvalu(TV) 12:00 - TVT # Tuvalu Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Wake" /*WAKT*/), + // Pacific/Wake Wake(US) 12:00 - WAKT # Wake Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Wallis" /*WFT*/), + // Pacific/Wallis Wallis and Futuna(WF) 12:00 - WFT # Wallis & Futuna Time + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Fiji", + Calendar.NOVEMBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.FEBRUARY, -1, Calendar.SUNDAY /*DOW_IN_MON*/, 3*ONE_HOUR, SimpleTimeZone.WALL_TIME, 1*ONE_HOUR), + // Rule Fiji 1998 max - Nov Sun>=1 2:00 1:00 S + // Rule Fiji 1999 max - Feb lastSun 3:00 0 - + // Zone Pacific/Fiji Fiji(FJ) 12:00 Fiji FJ%sT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Antarctica/McMurdo" /*NZ%sT*/, + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.MARCH, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule NZAQ 1990 max - Oct Sun>=1 2:00s 1:00 D + // Rule NZAQ 1990 max - Mar Sun>=15 2:00s 0 S + // Antarctica/McMurdo USA - year-round bases(AQ) 12:00 NZAQ NZ%sT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Asia/Kamchatka" /*PET%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Kamchatka Russia(RU) 12:00 Russia PET%sT + //---------------------------------------------------------- + new SimpleTimeZone(12*ONE_HOUR, "Pacific/Auckland" /*NZ%sT*/, + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.MARCH, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule NZ 1990 max - Oct Sun>=1 2:00s 1:00 D + // Rule NZ 1990 max - Mar Sun>=15 2:00s 0 S + // Pacific/Auckland New Zealand(NZ) 12:00 NZ NZ%sT + new SimpleTimeZone(12*ONE_HOUR, "NST" /*alias for Pacific/Auckland*/, + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, 2*ONE_HOUR, + Calendar.MARCH, 15, -Calendar.SUNDAY /*DOW>=DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + //---------------------------------------------------------- + new SimpleTimeZone((int)(12.75*ONE_HOUR), "Pacific/Chatham" /*CHA%sT*/, + Calendar.OCTOBER, 1, -Calendar.SUNDAY /*DOW>=DOM*/, (int)(2.75*ONE_HOUR), + Calendar.MARCH, 15, -Calendar.SUNDAY /*DOW>=DOM*/, (int)(3.75*ONE_HOUR), 1*ONE_HOUR), + // Rule Chatham 1990 max - Oct Sun>=1 2:45s 1:00 D + // Rule Chatham 1991 max - Mar Sun>=15 2:45s 0 S + // Pacific/Chatham New Zealand(NZ) 12:45 Chatham CHA%sT + //---------------------------------------------------------- + new SimpleTimeZone(13*ONE_HOUR, "Pacific/Enderbury" /*PHOT*/), + // Pacific/Enderbury Kiribati(KI) 13:00 - PHOT + //---------------------------------------------------------- + new SimpleTimeZone(13*ONE_HOUR, "Pacific/Tongatapu" /*TOT*/), + // Pacific/Tongatapu Tonga(TO) 13:00 - TOT + //---------------------------------------------------------- + new SimpleTimeZone(13*ONE_HOUR, "Asia/Anadyr" /*ANA%sT*/, + Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 3*ONE_HOUR, 1*ONE_HOUR), + // Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S + // Rule Russia 1996 max - Oct lastSun 2:00s 0 - + // Asia/Anadyr Russia(RU) 13:00 Russia ANA%sT + //---------------------------------------------------------- + new SimpleTimeZone(14*ONE_HOUR, "Pacific/Kiritimati" /*LINT*/), + // Pacific/Kiritimati Kiribati(KI) 14:00 - LINT + }; + // ---------------- END GENERATED DATA ---------------- + + private static Hashtable lookup = new Hashtable(zones.length); + + static { + for (int i=0; i < zones.length; ++i) + lookup.put(zones[i].getID(), zones[i]); + TimeZone.getDefault(); // to cache default system time zone + } +} + +//eof