]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/intltest/tzregts.cpp
ICU-511.34.tar.gz
[apple/icu.git] / icuSources / test / intltest / tzregts.cpp
index dc07ddf102da92cbea4a5b28f8ec478b39c5965e..274b3f561b79ff653277b1b00938334bfbbb5d25 100644 (file)
@@ -1,7 +1,6 @@
 /********************************************************************
- * COPYRIGHT: 
- * Copyright (c) 1997-2003, International Business Machines Corporation and
- * others. All Rights Reserved.
+ * Copyright (c) 1997-2013, International Business Machines
+ * Corporation and others. All Rights Reserved.
  ********************************************************************/
  
 #include "unicode/utypes.h"
@@ -18,7 +17,8 @@
 // *****************************************************************************
 // class TimeZoneRegressionTest
 // *****************************************************************************
-
+/* length of an array */
+#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
 
 void 
@@ -44,7 +44,8 @@ TimeZoneRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &
         CASE(14, TestJ186);
         CASE(15, TestJ449);
         CASE(16, TestJDK12API);
-
+        CASE(17, Test4176686);
+        CASE(18, Test4184229);
         default: name = ""; break;
     }
 }
@@ -126,7 +127,7 @@ void TimeZoneRegressionTest:: Test4073215()
 {
     UErrorCode status = U_ZERO_ERROR;
     UnicodeString str, str2;
-    SimpleTimeZone *z = (SimpleTimeZone*) TimeZone::createTimeZone("GMT");
+    SimpleTimeZone *z = new SimpleTimeZone(0, "GMT");
     if (z->useDaylightTime())
         errln("Fail: Fix test to start with non-DST zone");
     z->setStartRule(UCAL_FEBRUARY, 1, UCAL_SUNDAY, 0, status);
@@ -138,7 +139,7 @@ void TimeZoneRegressionTest:: Test4073215()
 
     GregorianCalendar cal(1997, UCAL_JANUARY, 31, status);
     if(U_FAILURE(status)) {
-      errln("Error creating calendar %s", u_errorName(status));
+      dataerrln("Error creating calendar %s", u_errorName(status));
       return;
     }
     failure(status, "new GregorianCalendar");
@@ -146,7 +147,7 @@ void TimeZoneRegressionTest:: Test4073215()
 
     SimpleDateFormat sdf((UnicodeString)"E d MMM yyyy G HH:mm", status); 
     if(U_FAILURE(status)) {
-      errln("Error creating date format %s", u_errorName(status));
+      dataerrln("Error creating date format %s", u_errorName(status));
       return;
     }
     sdf.setCalendar(cal); 
@@ -221,25 +222,36 @@ void TimeZoneRegressionTest:: Test4084933() {
      *  The following was added just for consistency.  It shows that going *to* Daylight
      *  Savings Time (PDT) does work at 2am.
      */
-
     int32_t offset5 = tz->getOffset(1,
         1997, UCAL_APRIL, 6, UCAL_SUNDAY, (2*60*60*1000), status);
     int32_t offset6 = tz->getOffset(1,
         1997, UCAL_APRIL, 6, UCAL_SUNDAY, (2*60*60*1000)-1, status);
-
+    int32_t offset5a = tz->getOffset(1,
+        1997, UCAL_APRIL, 6, UCAL_SUNDAY, (3*60*60*1000), status);
+    int32_t offset6a = tz->getOffset(1,
+        1997, UCAL_APRIL, 6, UCAL_SUNDAY, (3*60*60*1000)-1, status);
     int32_t offset7 = tz->getOffset(1,
         1997, UCAL_APRIL, 6, UCAL_SUNDAY, (1*60*60*1000), status);
     int32_t offset8 = tz->getOffset(1,
         1997, UCAL_APRIL, 6, UCAL_SUNDAY, (1*60*60*1000)-1, status);
-
     int32_t SToffset = (int32_t)(-8 * 60*60*1000L);
     int32_t DToffset = (int32_t)(-7 * 60*60*1000L);
-    if (offset1 != SToffset || offset2 != SToffset ||
-        offset3 != SToffset || offset4 != DToffset ||
-        offset5 != DToffset || offset6 != SToffset ||
-        offset7 != SToffset || offset8 != SToffset
-        || U_FAILURE(status))
-        errln("Fail: TimeZone misbehaving");
+        
+#define ERR_IF_FAIL(x) if(x) { dataerrln("FAIL: TimeZone misbehaving - %s", #x); }
+
+        ERR_IF_FAIL(U_FAILURE(status))
+        ERR_IF_FAIL(offset1 != SToffset)
+        ERR_IF_FAIL(offset2 != SToffset)
+        ERR_IF_FAIL(offset3 != SToffset)
+        ERR_IF_FAIL(offset4 != DToffset)
+        ERR_IF_FAIL(offset5 != DToffset)
+        ERR_IF_FAIL(offset6 != SToffset)
+        ERR_IF_FAIL(offset5a != DToffset)
+        ERR_IF_FAIL(offset6a != DToffset)
+        ERR_IF_FAIL(offset7 != SToffset)
+        ERR_IF_FAIL(offset8 != SToffset)
+
+#undef ERR_IF_FAIL
 
     delete tz;
 }
@@ -298,7 +310,7 @@ void TimeZoneRegressionTest:: Test4109314() {
     UErrorCode status = U_ZERO_ERROR;
     GregorianCalendar *testCal = (GregorianCalendar*)Calendar::createInstance(status); 
     if(U_FAILURE(status)) {
-      errln("Error creating calendar %s", u_errorName(status));
+      dataerrln("Error creating calendar %s", u_errorName(status));
       delete testCal;
       return;
     }
@@ -440,7 +452,7 @@ void TimeZoneRegressionTest:: Test4126678()
     UErrorCode status = U_ZERO_ERROR;
     Calendar *cal = Calendar::createInstance(status);
     if(U_FAILURE(status)) {
-      errln("Error creating calendar %s", u_errorName(status));
+      dataerrln("Error creating calendar %s", u_errorName(status));
       delete cal;
       return;
     }
@@ -448,11 +460,10 @@ void TimeZoneRegressionTest:: Test4126678()
     TimeZone *tz = TimeZone::createTimeZone("PST");
     cal->adoptTimeZone(tz);
 
-    cal->set(1998 - 1900, UCAL_APRIL, 5, 10, 0);
-    //Date dt = new Date(1998-1900, Calendar::APRIL, 5, 10, 0);
+    cal->set(1998, UCAL_APRIL, 5, 10, 0);
     
     if (! tz->useDaylightTime() || U_FAILURE(status))
-        errln("We're not in Daylight Savings Time and we should be.\n");
+        dataerrln("We're not in Daylight Savings Time and we should be. - %s", u_errorName(status));
 
     //cal.setTime(dt);
     int32_t era = cal->get(UCAL_ERA, status);
@@ -469,8 +480,9 @@ void TimeZoneRegressionTest:: Test4126678()
     failure(status, "cal->get");
     int32_t offset = tz->getOffset((uint8_t)era, year, month, day, (uint8_t)dayOfWeek, millis, status);
     int32_t raw_offset = tz->getRawOffset();
+
     if (offset == raw_offset)
-        errln("Offsets should not match when in DST");
+        dataerrln("Offsets should match");
 
     delete cal;
 }
@@ -486,7 +498,7 @@ void TimeZoneRegressionTest:: Test4151406() {
         // h is in half-hours from GMT; rawoffset is in millis
         int32_t rawoffset = h * 1800000;
         int32_t hh = (h<0) ? -h : h;
-        UnicodeString hname = ((h<0) ? UnicodeString("GMT-") : UnicodeString("GMT+")) +
+        UnicodeString hname = UnicodeString((h<0) ? "GMT-" : "GMT+") +
             ((hh/2 < 10) ? "0" : "") +
             (hh/2) + ':' +
             ((hh%2==0) ? "00" : "30");
@@ -494,11 +506,18 @@ void TimeZoneRegressionTest:: Test4151406() {
             UErrorCode ec = U_ZERO_ERROR;
             int32_t count;
             StringEnumeration* ids = TimeZone::createEnumeration(rawoffset);
+            if (ids == NULL) {
+                dataerrln("Fail: TimeZone::createEnumeration(rawoffset)");
+                continue;
+            }
             count = ids->count(ec);
             if (count> max) 
                 max = count;
-            logln(hname + ' ' + count +
-                  ((count > 0) ? (" e.g. " + *ids->snext(ec)) : UnicodeString("")));
+            if (count > 0) {
+                logln(hname + ' ' + (UnicodeString)count + (UnicodeString)" e.g. " + *ids->snext(ec));
+            } else {
+                logln(hname + ' ' + count);
+            }
             // weiv 11/27/2002: why uprv_free? This should be a delete
             delete ids;
             //delete [] ids;
@@ -795,10 +814,17 @@ TimeZoneRegressionTest::Test4154650()
         //   e = ex;
         //}
         if(good != U_SUCCESS(status)) {
+            UnicodeString errMsg;
+            if (good) {
+                errMsg = (UnicodeString(") threw ") + u_errorName(status));
+            }
+            else {
+                errMsg = UnicodeString(") accepts invalid args", "");
+            }
             errln(UnicodeString("Fail: getOffset(") +
                   DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +
                   DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +
-                  (good ? (UnicodeString(") threw ") + u_errorName(status)) : UnicodeString(") accepts invalid args")));
+                  errMsg);
         }
         status = U_ZERO_ERROR; // reset
     }
@@ -816,7 +842,7 @@ TimeZoneRegressionTest::Test4162593()
     UErrorCode status = U_ZERO_ERROR;
     SimpleDateFormat *fmt = new SimpleDateFormat("z", Locale::getUS(), status);
     if(U_FAILURE(status)) {
-      errln("Error creating calendar %s", u_errorName(status));
+      dataerrln("Error creating calendar %s", u_errorName(status));
       delete fmt;
       return;
     }
@@ -834,9 +860,10 @@ TimeZoneRegressionTest::Test4162593()
       0, 0, 0 };
 
     int32_t DATA_INT [] [5] = {
-        {98, UCAL_SEPTEMBER, 30, 22, 0},
-        {100, UCAL_FEBRUARY, 28, 22, 0},
-        {100, UCAL_FEBRUARY, 29, 22, 0},
+        // These years must be AFTER the Gregorian cutover
+        {1998, UCAL_SEPTEMBER, 30, 22, 0},
+        {2000, UCAL_FEBRUARY, 28, 22, 0},
+        {2000, UCAL_FEBRUARY, 29, 22, 0},
      };
 
     UBool DATA_BOOL [] = {
@@ -860,16 +887,16 @@ TimeZoneRegressionTest::Test4162593()
         // Must construct the Date object AFTER setting the default zone
         int32_t *p = (int32_t*)DATA_INT[j];
         UDate d = CalendarRegressionTest::makeDate(p[0], p[1], p[2], p[3], p[4]);
-        UBool transitionExpected = DATA_BOOL[j];
+       UBool transitionExpected = DATA_BOOL[j];
 
         UnicodeString temp;
         logln(tz->getID(temp) + ":");
         for (int32_t i = 0; i < 4; ++i) {
             FieldPosition pos(0);
             zone[i].remove();
-            zone[i] = fmt->format(d, zone[i], pos);
+            zone[i] = fmt->format(d+ i*ONE_HOUR, zone[i], pos);
             logln(UnicodeString("") + i + ": " + d + " / " + zone[i]);
-            d += (double) ONE_HOUR;
+            //d += (double) ONE_HOUR;
         }
         if(zone[0] == zone[1] &&
             (zone[1] == zone[2]) != transitionExpected &&
@@ -885,6 +912,77 @@ TimeZoneRegressionTest::Test4162593()
     delete DATA_TZ[0];
 }
 
+  /**
+    * getDisplayName doesn't work with unusual savings/offsets.
+    */
+void TimeZoneRegressionTest::Test4176686() {
+    // Construct a zone that does not observe DST but
+    // that does have a DST savings (which should be ignored).
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t offset = 90 * 60000; // 1:30
+    SimpleTimeZone* z1 = new SimpleTimeZone(offset, "_std_zone_");
+    z1->setDSTSavings(45 * 60000, status); // 0:45
+
+    // Construct a zone that observes DST for the first 6 months.
+    SimpleTimeZone* z2 = new SimpleTimeZone(offset, "_dst_zone_");
+    z2->setDSTSavings(45 * 60000, status); // 0:45
+    z2->setStartRule(UCAL_JANUARY, 1, 0, status);
+    z2->setEndRule(UCAL_JULY, 1, 0, status);
+
+    // Also check DateFormat
+    DateFormat* fmt1 = new SimpleDateFormat(UnicodeString("z"), status);
+    if (U_FAILURE(status)) {
+        dataerrln("Failure trying to construct: %s", u_errorName(status));
+        return;
+    }
+    fmt1->setTimeZone(*z1); // Format uses standard zone
+    DateFormat* fmt2 = new SimpleDateFormat(UnicodeString("z"), status);
+    if(!assertSuccess("trying to construct", status))return;
+    fmt2->setTimeZone(*z2); // Format uses DST zone
+    Calendar* tempcal = Calendar::createInstance(status);
+    tempcal->clear();
+    tempcal->set(1970, UCAL_FEBRUARY, 1);
+    UDate dst = tempcal->getTime(status); // Time in DST
+    tempcal->set(1970, UCAL_AUGUST, 1);
+    UDate std = tempcal->getTime(status); // Time in standard
+
+    // Description, Result, Expected Result
+    UnicodeString a,b,c,d,e,f,g,h,i,j,k,l;
+    UnicodeString DATA[] = {
+        "z1->getDisplayName(false, SHORT)/std zone",
+        z1->getDisplayName(FALSE, TimeZone::SHORT, a), "GMT+1:30",
+        "z1->getDisplayName(false, LONG)/std zone",
+        z1->getDisplayName(FALSE, TimeZone::LONG, b), "GMT+01:30",
+        "z1->getDisplayName(true, SHORT)/std zone",
+        z1->getDisplayName(TRUE, TimeZone::SHORT, c), "GMT+1:30",
+        "z1->getDisplayName(true, LONG)/std zone",
+        z1->getDisplayName(TRUE, TimeZone::LONG, d ), "GMT+01:30",
+        "z2->getDisplayName(false, SHORT)/dst zone",
+        z2->getDisplayName(FALSE, TimeZone::SHORT, e), "GMT+1:30",
+        "z2->getDisplayName(false, LONG)/dst zone",
+        z2->getDisplayName(FALSE, TimeZone::LONG, f ), "GMT+01:30",
+        "z2->getDisplayName(true, SHORT)/dst zone",
+        z2->getDisplayName(TRUE, TimeZone::SHORT, g), "GMT+2:15",
+        "z2->getDisplayName(true, LONG)/dst zone",
+        z2->getDisplayName(TRUE, TimeZone::LONG, h ), "GMT+02:15",
+        "DateFormat.format(std)/std zone", fmt1->format(std, i), "GMT+1:30",
+        "DateFormat.format(dst)/std zone", fmt1->format(dst, j), "GMT+1:30",
+        "DateFormat.format(std)/dst zone", fmt2->format(std, k), "GMT+1:30",
+        "DateFormat.format(dst)/dst zone", fmt2->format(dst, l), "GMT+2:15",
+    };
+
+    for (int32_t idx=0; idx<(int32_t)ARRAY_LENGTH(DATA); idx+=3) {
+        if (DATA[idx+1]!=(DATA[idx+2])) {
+            errln("FAIL: " + DATA[idx] + " -> " + DATA[idx+1] + ", exp " + DATA[idx+2]);
+        }
+    }
+    delete z1;
+    delete z2;
+    delete fmt1;
+    delete fmt2;
+    delete tempcal;
+}
+
 /**
  * Make sure setStartRule and setEndRule set the DST savings to nonzero
  * if it was zero.
@@ -933,7 +1031,7 @@ void TimeZoneRegressionTest::TestJ449() {
     // specify two zones in the same equivalency group.  One must have
     // locale data in 'loc'; the other must not.
     const char* idWithLocaleData = "America/Los_Angeles";
-    const char* idWithoutLocaleData = "America/Vancouver";
+    const char* idWithoutLocaleData = "US/Pacific";
     const Locale loc("en", "", "");
 
     TimeZone *zoneWith = TimeZone::createTimeZone(idWithLocaleData);
@@ -941,7 +1039,7 @@ void TimeZoneRegressionTest::TestJ449() {
     // Make sure we got valid zones
     if (zoneWith->getID(str) != UnicodeString(idWithLocaleData) ||
         zoneWithout->getID(str) != UnicodeString(idWithoutLocaleData)) {
-        errln("Fail: Unable to create zones");
+      dataerrln(UnicodeString("Fail: Unable to create zones - wanted ") + idWithLocaleData + ", got " + zoneWith->getID(str) + ", and wanted " + idWithoutLocaleData + " but got " + zoneWithout->getID(str));
     } else {
         GregorianCalendar calWith(*zoneWith, status);
         GregorianCalendar calWithout(*zoneWithout, status);
@@ -975,13 +1073,31 @@ void TimeZoneRegressionTest::TestJ449() {
 void
 TimeZoneRegressionTest::TestJDK12API()
 {
-    TimeZone *pst = TimeZone::createTimeZone("PST");
-    TimeZone *cst1 = TimeZone::createTimeZone("CST");
-
-    SimpleTimeZone *cst = 0;
+    // TimeZone *pst = TimeZone::createTimeZone("PST");
+    // TimeZone *cst1 = TimeZone::createTimeZone("CST");
+    UErrorCode ec = U_ZERO_ERROR;
+    //d,-28800,3,1,-1,120,w,9,-1,1,120,w,60
+    TimeZone *pst = new SimpleTimeZone(-28800*U_MILLIS_PER_SECOND,
+                                       "PST",
+                                       3,1,-1,120*U_MILLIS_PER_MINUTE,
+                                       SimpleTimeZone::WALL_TIME,
+                                       9,-1,1,120*U_MILLIS_PER_MINUTE,
+                                       SimpleTimeZone::WALL_TIME,
+                                       60*U_MILLIS_PER_MINUTE,ec);
+    //d,-21600,3,1,-1,120,w,9,-1,1,120,w,60
+    TimeZone *cst1 = new SimpleTimeZone(-21600*U_MILLIS_PER_SECOND,
+                                       "CST",
+                                       3,1,-1,120*U_MILLIS_PER_MINUTE,
+                                       SimpleTimeZone::WALL_TIME,
+                                       9,-1,1,120*U_MILLIS_PER_MINUTE,
+                                       SimpleTimeZone::WALL_TIME,
+                                       60*U_MILLIS_PER_MINUTE,ec);
+    if (U_FAILURE(ec)) {
+        errln("FAIL: SimpleTimeZone constructor");
+        return;
+    }
 
-    if(cst1->getDynamicClassID() == SimpleTimeZone::getStaticClassID())
-        cst = (SimpleTimeZone*) cst1;
+    SimpleTimeZone *cst = dynamic_cast<SimpleTimeZone *>(cst1);
 
     if(pst->hasSameRules(*cst)) {
         errln("FAILURE: PST and CST have same rules");
@@ -1002,7 +1118,7 @@ TimeZoneRegressionTest::TestJDK12API()
 
     // verify error checking
     pst->getOffset(1,
-        1997, (UCalendarDateFields)-1, 26, UCAL_SUNDAY, (2*60*60*1000), status);
+        1997, UCAL_FIELD_COUNT+1, 26, UCAL_SUNDAY, (2*60*60*1000), status);
     if(U_SUCCESS(status))
         errln("FAILURE: getOffset() succeeded with -1 for month");
 
@@ -1018,5 +1134,76 @@ TimeZoneRegressionTest::TestJDK12API()
     delete pst;
     delete cst;
 }
+/**
+ * SimpleTimeZone allows invalid DOM values.
+ */
+void TimeZoneRegressionTest::Test4184229() {
+    SimpleTimeZone* zone = NULL;
+    UErrorCode status = U_ZERO_ERROR;
+    zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, status);
+    if(U_SUCCESS(status)){
+        errln("Failed. No exception has been thrown for DOM -1 startDay");
+    }else{
+       logln("(a) " + UnicodeString( u_errorName(status)));
+    }
+    status = U_ZERO_ERROR;
+    delete zone;
+
+    zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, status);
+    if(U_SUCCESS(status)){
+        errln("Failed. No exception has been thrown for DOM -1 endDay");
+    }else{
+       logln("(b) " + UnicodeString(u_errorName(status)));
+    }
+    status = U_ZERO_ERROR;
+    delete zone;
+
+    zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 1000, status);
+    if(U_SUCCESS(status)){
+        errln("Failed. No exception has been thrown for DOM -1 startDay+savings");
+    }else{
+       logln("(c) " + UnicodeString(u_errorName(status)));
+    }
+    status = U_ZERO_ERROR;
+    delete zone;
+    zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000, status);
+    if(U_SUCCESS(status)){
+        errln("Failed. No exception has been thrown for DOM -1 endDay+ savings");
+    }else{
+       logln("(d) " + UnicodeString(u_errorName(status)));
+    }
+    status = U_ZERO_ERROR;
+    delete zone;
+    // Make a valid constructor call for subsequent tests.
+    zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0, status);
+    
+    zone->setStartRule(0, -1, 0, 0, status);
+    if(U_SUCCESS(status)){
+        errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings");
+    } else{
+        logln("(e) " + UnicodeString(u_errorName(status)));
+    }
+    zone->setStartRule(0, -1, 0, status);
+    if(U_SUCCESS(status)){
+        errln("Failed. No exception has been thrown for DOM -1 setStartRule");
+    } else{
+        logln("(f) " + UnicodeString(u_errorName(status)));
+    }
+
+    zone->setEndRule(0, -1, 0, 0, status);
+    if(U_SUCCESS(status)){
+        errln("Failed. No exception has been thrown for DOM -1 setEndRule+savings");
+    } else{
+        logln("(g) " + UnicodeString(u_errorName(status)));
+    }   
+
+    zone->setEndRule(0, -1, 0, status);
+    if(U_SUCCESS(status)){
+        errln("Failed. No exception has been thrown for DOM -1 setEndRule");
+    } else{
+        logln("(h) " + UnicodeString(u_errorName(status)));
+    }
+    delete zone;
+}
 
 #endif /* #if !UCONFIG_NO_FORMATTING */