Blob Blame Raw
Index: icu4c/source/test/intltest/tzregts.cpp
===================================================================
--- icu4c/source/test/intltest/tzregts.cpp	(リビジョン 40953)
+++ icu4c/source/test/intltest/tzregts.cpp	(リビジョン 40954)
@@ -12,6 +12,7 @@
 #include "unicode/simpletz.h"
 #include "unicode/smpdtfmt.h"
 #include "unicode/strenum.h"
+#include "unicode/gregocal.h"
 #include "tzregts.h"
 #include "calregts.h"
 #include "cmemory.h"
@@ -46,6 +47,7 @@
         CASE(16, TestJDK12API);
         CASE(17, Test4176686);
         CASE(18, Test4184229);
+        CASE(19, TestNegativeDaylightSaving);
         default: name = ""; break;
     }
 }
@@ -709,10 +711,10 @@
     int32_t DATA [] = {
         1, GOOD,
         0, BAD,
-        -1, BAD,
+        -1, GOOD,   // #13566 updates SimpleTimeZone to support negative DST saving amount
         60*60*1000, GOOD,
-        INT32_MIN, BAD,
-        // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
+        INT32_MAX, GOOD,    // no upper limit on DST savings at this time
+        INT32_MIN, GOOD     // no lower limit as well
     };
 
     UErrorCode status = U_ZERO_ERROR;
@@ -1206,4 +1208,61 @@
     delete zone;
 }
 
+void TimeZoneRegressionTest::TestNegativeDaylightSaving() {
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t stdOff = 1 * 60*60*1000;    // Standard offset UTC+1
+    int save = -1 * 60*60*1000;     // DST saving amount -1 hour
+    SimpleTimeZone stzDublin(stdOff, "Dublin-2018",
+                                UCAL_OCTOBER, -1, -UCAL_SUNDAY, 2*60*60*1000,
+                                UCAL_MARCH, -1, -UCAL_SUNDAY, 1*60*60*1000,
+                                save, status);
+    failure(status, "SimpleTimeZone constructor");
+
+    if (save != stzDublin.getDSTSavings()) {
+        errln((UnicodeString)"FAIL: DST saving is not " + save);
+    }
+
+    GregorianCalendar cal(* TimeZone::getGMT(), status);
+    failure(status, "GregorianCalendar constructor");
+
+    UDate testDate;
+    int32_t rawOffset;
+    int32_t dstOffset;
+
+    cal.set(2018, UCAL_JANUARY, 15, 0, 0, 0);
+    testDate = cal.getTime(status);
+    failure(status, "calendar getTime() - Jan 15");
+
+    if (!stzDublin.inDaylightTime(testDate, status)) {
+        errln("FAIL: The test date (Jan 15) must be in DST.");
+    }
+    failure(status, "inDaylightTime() - Jan 15");
+
+    stzDublin.getOffset(testDate, FALSE, rawOffset, dstOffset, status);
+    failure(status, "getOffset() - Jan 15");
+    if (rawOffset != stdOff || dstOffset != save) {
+        errln((UnicodeString)"FAIL: Expected [stdoff=" + stdOff + ",save=" + save
+            + "] on the test date (Jan 15), actual[stdoff=" + rawOffset
+            + ",save=" + dstOffset + "]");
+    }
+
+    cal.set(2018, UCAL_JULY, 15, 0, 0, 0);
+    testDate = cal.getTime(status);
+    failure(status, "calendar getTime() - Jul 15");
+
+    if (stzDublin.inDaylightTime(testDate, status)) {
+        errln("FAIL: The test date (Jul 15) must be in DST.");
+    }
+    failure(status, "inDaylightTime() - Jul 15");
+
+    stzDublin.getOffset(testDate, FALSE, rawOffset, dstOffset, status);
+    failure(status, "getOffset() - Jul 15");
+    if (rawOffset != stdOff || dstOffset != 0) {
+        errln((UnicodeString)"FAIL: Expected [stdoff=" + stdOff + ",save=" + 0
+            + "] on the test date (Jul 15), actual[stdoff=" + rawOffset
+            + ",save=" + dstOffset + "]");
+    }
+}
+
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
Index: icu4c/source/test/intltest/tzregts.h
===================================================================
--- icu4c/source/test/intltest/tzregts.h	(リビジョン 40953)
+++ icu4c/source/test/intltest/tzregts.h	(リビジョン 40954)
@@ -49,6 +49,7 @@
     void TestJDK12API(void);
     void Test4184229(void);
     UBool checkCalendar314(GregorianCalendar *testCal, TimeZone *testTZ);
+    void TestNegativeDaylightSaving(void);
 
 
 protected:
Index: icu4c/source/i18n/simpletz.cpp
===================================================================
--- icu4c/source/i18n/simpletz.cpp	(リビジョン 40953)
+++ icu4c/source/i18n/simpletz.cpp	(リビジョン 40954)
@@ -177,7 +177,7 @@
 
     decodeRules(status);
 
-    if (savingsDST <= 0) {
+    if (savingsDST == 0) {
         status = U_ILLEGAL_ARGUMENT_ERROR;
     }
 }
@@ -686,7 +686,7 @@
 void 
 SimpleTimeZone::setDSTSavings(int32_t millisSavedDuringDST, UErrorCode& status) 
 {
-    if (millisSavedDuringDST <= 0) {
+    if (millisSavedDuringDST == 0) {
         status = U_ILLEGAL_ARGUMENT_ERROR;
     }
     else {
Index: icu4c/source/i18n/unicode/simpletz.h
===================================================================
--- icu4c/source/i18n/unicode/simpletz.h	(リビジョン 40953)
+++ icu4c/source/i18n/unicode/simpletz.h	(リビジョン 40954)
@@ -647,7 +647,8 @@
      * 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).
+     * are in effect. Typically one hour (+3600000). The amount could be negative,
+     * but not 0.
      * @param status  An UErrorCode to receive the status.
      * @stable ICU 2.0
      */
@@ -657,7 +658,8 @@
      * 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).
+     * are in effect. Typically one hour (+3600000). The amount could be negative,
+     * but not 0.
      * @stable ICU 2.0
      */
     virtual int32_t getDSTSavings(void) const;