]> granicus.if.org Git - icu/commitdiff
ICU-9452 Fixed calendar add issue with the Samoa Dec 2011 24 hour transition.
authorYoshito Umaoka <y.umaoka@gmail.com>
Thu, 9 Aug 2012 21:29:53 +0000 (21:29 +0000)
committerYoshito Umaoka <y.umaoka@gmail.com>
Thu, 9 Aug 2012 21:29:53 +0000 (21:29 +0000)
X-SVN-Rev: 32141

icu4c/source/i18n/calendar.cpp
icu4c/source/test/intltest/calregts.cpp
icu4c/source/test/intltest/calregts.h

index 2e5560f2a510d985c142acca05ee8b26a8373f7f..fa4f83b9bddcf1a92b77a4d98bad74ca751c47e4 100644 (file)
@@ -2005,10 +2005,19 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status
             // danger of adjusting into a different day. To avoid
             // this we make the adjustment only if it actually
             // maintains the hour.
-            double t = internalGetTime();
-            setTimeInMillis(t + prevOffset - newOffset, status);
-            if (get(UCAL_HOUR_OF_DAY, status) != hour) {
-                setTimeInMillis(t, status);
+
+            // When the difference of the previous UTC offset and
+            // the new UTC offset exceeds 1 full day, we do not want
+            // to roll over/back the date. For now, this only happens
+            // in Samoa (Pacific/Apia) on Dec 30, 2011. See ticket:9452.
+            int32_t adjAmount = prevOffset - newOffset;
+            adjAmount = adjAmount >= 0 ? adjAmount % (int32_t)kOneDay : -(-adjAmount % (int32_t)kOneDay);
+            if (adjAmount != 0) {
+                double t = internalGetTime();
+                setTimeInMillis(t + adjAmount, status);
+                if (get(UCAL_HOUR_OF_DAY, status) != hour) {
+                    setTimeInMillis(t, status);
+                }
             }
         }
     } 
index 7d05e096ddc6dede96138fee2577e371a2eeb256..b60c8b62fd0c5edc7b397ec56e2a2bfd49f9fc2d 100644 (file)
@@ -87,6 +87,7 @@ CalendarRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &
         CASE(47,TestT8057);
         CASE(48,TestT8596);
         CASE(49,Test9019);
+        CASE(50,TestT9452);
     default: name = ""; break;
     }
 }
@@ -2898,4 +2899,47 @@ void CalendarRegressionTest::TestT8596(void) {
     delete gc;
 }
 
+// Test case for ticket 9452
+// Calendar addition fall onto the missing date - 2011-12-30 in Samoa
+void CalendarRegressionTest::TestT9452(void) {
+    UErrorCode status = U_ZERO_ERROR;
+    GregorianCalendar cal(TimeZone::createTimeZone("Pacific/Apia"), status);
+    failure(status, "initializing GregorianCalendar");
+
+    SimpleDateFormat sdf(UnicodeString("y-MM-dd'T'HH:mm:ssZZZZZ"), status);
+    failure(status, "initializing SimpleDateFormat");
+    sdf.setCalendar(cal);
+
+    UnicodeString dstr;
+
+    // Set date to 2011-12-29 00:00
+    cal.clear();
+    cal.set(2011, UCAL_DECEMBER, 29, 0, 0, 0);
+
+    UDate d = cal.getTime(status);
+    failure(status, "getTime for initial date");
+    sdf.format(d, dstr);
+    logln(UnicodeString("Initial date: ") + dstr);
+
+    // Add 1 day
+    cal.add(UCAL_DATE, 1, status);
+    failure(status, "add 1 day");
+    d = cal.getTime(status);
+    failure(status, "getTime after +1 day");
+    dstr.remove();
+    sdf.format(d, dstr);
+    logln(UnicodeString("+1 day: ") + dstr);
+    assertEquals("Add 1 day", UnicodeString("2011-12-31T00:00:00+14:00"), dstr);
+
+    // Subtract 1 day
+    cal.add(UCAL_DATE, -1, status);
+    failure(status, "subtract 1 day");
+    d = cal.getTime(status);
+    failure(status, "getTime after -1 day");
+    dstr.remove();
+    sdf.format(d, dstr);
+    logln(UnicodeString("-1 day: ") + dstr);
+    assertEquals("Subtract 1 day", UnicodeString("2011-12-29T00:00:00-10:00"), dstr);
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
index 294d3345df125bcbe16ec48aca9f2525a823212f..c099d2bbaff8a4a3a3ae1b1bc48bc61bc49ddbbf 100644 (file)
@@ -74,6 +74,7 @@ public:
     void TestDeprecates(void);
     void TestT8596(void);
     void Test9019(void);
+    void TestT9452(void);
 
     void printdate(GregorianCalendar *cal, const char *string);
     void dowTest(UBool lenient) ;