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