U_CAPI int32_t U_EXPORT2 ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec) { int32_t result = 0; TimeZone* zone = _createTimeZone(zoneID, -1, ec); if (U_SUCCESS(*ec)) { SimpleTimeZone* stz = dynamic_cast<SimpleTimeZone*>(zone); if (stz != NULL) { result = stz->getDSTSavings(); } else { // Since there is no getDSTSavings on TimeZone, we use a // heuristic: Starting with the current time, march // forwards for one year, looking for DST savings. // Stepping by weeks is sufficient. UDate d = Calendar::getNow(); for (int32_t i=0; i<53; ++i, d+=U_MILLIS_PER_DAY*7.0) { int32_t raw, dst; zone->getOffset(d, FALSE, raw, dst, *ec); if (U_FAILURE(*ec)) { break; } else if (dst != 0) { result = dst; break; } } } } delete zone; return result; }
void SimpleTimeZone::checkTransitionRules(UErrorCode& status) const { if (U_FAILURE(status)) { return; } umtx_lock(&gLock); if (!transitionRulesInitialized) { SimpleTimeZone *ncThis = const_cast<SimpleTimeZone*>(this); ncThis->initTransitionRules(status); } umtx_unlock(&gLock); }
UDate TimeZoneRegressionTest::findTransitionStepwise(const SimpleTimeZone& tz, UDate min, UDate max) { UErrorCode status = U_ZERO_ERROR; UBool startsInDST = tz.inDaylightTime(min, status); if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; while (min < max) { if (tz.inDaylightTime(min, status) != startsInDST) { return min; } if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; min += (UDate)24*60*60*1000; // one day } return 0; }
/** * @bug 4154537 * SimpleTimeZone::hasSameRules() doesn't work for zones with no DST * and different DST parameters. */ void TimeZoneRegressionTest:: Test4154537() { UErrorCode status = U_ZERO_ERROR; // tz1 and tz2 have no DST and different rule parameters SimpleTimeZone *tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0, status); SimpleTimeZone *tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0, status); // tza and tzA have the same rule params SimpleTimeZone *tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0, status); SimpleTimeZone *tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0, status); // tzb differs from tza SimpleTimeZone *tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0, status); if(U_FAILURE(status)) errln("Couldn't create TimeZones"); if (tz1->useDaylightTime() || tz2->useDaylightTime() || !tza->useDaylightTime() || !tzA->useDaylightTime() || !tzb->useDaylightTime()) { errln("Test is broken -- rewrite it"); } if (!tza->hasSameRules(*tzA) || tza->hasSameRules(*tzb)) { errln("Fail: hasSameRules() broken for zones with rules"); } if (!tz1->hasSameRules(*tz2)) { errln("Fail: hasSameRules() returns false for zones without rules"); //errln("zone 1 = " + tz1); //errln("zone 2 = " + tz2); } delete tz1; delete tz2; delete tza; delete tzA; delete tzb; }
UDate TimeZoneRegressionTest::findTransitionBinary(const SimpleTimeZone& tz, UDate min, UDate max) { UErrorCode status = U_ZERO_ERROR; UBool startsInDST = tz.inDaylightTime(min, status); if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; if (tz.inDaylightTime(max, status) == startsInDST) { logln((UnicodeString)"Error: inDaylightTime() != " + ((!startsInDST)?"TRUE":"FALSE")); return 0; } if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; while ((max - min) > 100) { // Min accuracy in ms UDate mid = (min + max) / 2; if (tz.inDaylightTime(mid, status) == startsInDST) { min = mid; } else { max = mid; } if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; } return (min + max) / 2; }
/** * @bug 4154542 * SimpleTimeZOne constructors, setStartRule(), and setEndRule() don't * check for out-of-range arguments. */ void TimeZoneRegressionTest:: Test4154542() { const int32_t GOOD = 1; const int32_t BAD = 0; const int32_t GOOD_MONTH = UCAL_JANUARY; const int32_t GOOD_DAY = 1; const int32_t GOOD_DAY_OF_WEEK = UCAL_SUNDAY; const int32_t GOOD_TIME = 0; int32_t DATA [] = { GOOD, INT32_MIN, 0, INT32_MAX, INT32_MIN, GOOD, UCAL_JANUARY, -5, UCAL_SUNDAY, 0, GOOD, UCAL_DECEMBER, 5, UCAL_SATURDAY, 24*60*60*1000, BAD, UCAL_DECEMBER, 5, UCAL_SATURDAY, 24*60*60*1000+1, BAD, UCAL_DECEMBER, 5, UCAL_SATURDAY, -1, BAD, UCAL_JANUARY, -6, UCAL_SUNDAY, 0, BAD, UCAL_DECEMBER, 6, UCAL_SATURDAY, 24*60*60*1000, GOOD, UCAL_DECEMBER, 1, 0, 0, GOOD, UCAL_DECEMBER, 31, 0, 0, BAD, UCAL_APRIL, 31, 0, 0, BAD, UCAL_DECEMBER, 32, 0, 0, BAD, UCAL_JANUARY-1, 1, UCAL_SUNDAY, 0, BAD, UCAL_DECEMBER+1, 1, UCAL_SUNDAY, 0, GOOD, UCAL_DECEMBER, 31, -UCAL_SUNDAY, 0, GOOD, UCAL_DECEMBER, 31, -UCAL_SATURDAY, 0, BAD, UCAL_DECEMBER, 32, -UCAL_SATURDAY, 0, BAD, UCAL_DECEMBER, -32, -UCAL_SATURDAY, 0, BAD, UCAL_DECEMBER, 31, -UCAL_SATURDAY-1, 0, }; SimpleTimeZone *zone = new SimpleTimeZone(0, "Z"); for (int32_t i=0; i < 18*5; i+=5) { UBool shouldBeGood = (DATA[i] == GOOD); int32_t month = DATA[i+1]; int32_t day = DATA[i+2]; int32_t dayOfWeek = DATA[i+3]; int32_t time = DATA[i+4]; UErrorCode status = U_ZERO_ERROR; //Exception ex = null; //try { zone->setStartRule(month, day, dayOfWeek, time, status); //} catch (IllegalArgumentException e) { // ex = e; //} if (U_SUCCESS(status) != shouldBeGood) { errln(UnicodeString("setStartRule(month=") + month + ", day=" + day + ", dayOfWeek=" + dayOfWeek + ", time=" + time + (shouldBeGood ? (") should work") : ") should fail but doesn't")); } //ex = null; //try { status = U_ZERO_ERROR; zone->setEndRule(month, day, dayOfWeek, time, status); //} catch (IllegalArgumentException e) { // ex = e; //} if (U_SUCCESS(status) != shouldBeGood) { errln(UnicodeString("setEndRule(month=") + month + ", day=" + day + ", dayOfWeek=" + dayOfWeek + ", time=" + time + (shouldBeGood ? (") should work") : ") should fail but doesn't")); } //ex = null; //try { // {sfb} need to look into ctor problems! (UErrorCode vs. dst signature confusion) status = U_ZERO_ERROR; SimpleTimeZone *temp = new SimpleTimeZone(0, "Z", (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time, (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK, GOOD_TIME,status); //} catch (IllegalArgumentException e) { // ex = e; //} if (U_SUCCESS(status) != shouldBeGood) { errln(UnicodeString("SimpleTimeZone(month=") + month + ", day=" + day + ", dayOfWeek=" + dayOfWeek + ", time=" + time + (shouldBeGood ? (", <end>) should work")// + ex) : ", <end>) should fail but doesn't")); } delete temp; //ex = null; //try { status = U_ZERO_ERROR; temp = new SimpleTimeZone(0, "Z", (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK, GOOD_TIME, (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time,status); //} catch (IllegalArgumentException e) { // ex = e; //} if (U_SUCCESS(status) != shouldBeGood) { errln(UnicodeString("SimpleTimeZone(<start>, month=") + month + ", day=" + day + ", dayOfWeek=" + dayOfWeek + ", time=" + time + (shouldBeGood ? (") should work")// + ex) : ") should fail but doesn't")); } delete temp; } delete zone; }
// {sfb} will this work using a Calendar? void TimeZoneRegressionTest:: Test4073215() { UErrorCode status = U_ZERO_ERROR; UnicodeString str, str2; 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); failure(status, "z->setStartRule()"); z->setEndRule(UCAL_MARCH, -1, UCAL_SUNDAY, 0, status); failure(status, "z->setStartRule()"); if (!z->useDaylightTime()) errln("Fail: DST not active"); GregorianCalendar cal(1997, UCAL_JANUARY, 31, status); if(U_FAILURE(status)) { dataerrln("Error creating calendar %s", u_errorName(status)); return; } failure(status, "new GregorianCalendar"); cal.adoptTimeZone(z); SimpleDateFormat sdf((UnicodeString)"E d MMM yyyy G HH:mm", status); if(U_FAILURE(status)) { dataerrln("Error creating date format %s", u_errorName(status)); return; } sdf.setCalendar(cal); failure(status, "new SimpleDateFormat"); UDate jan31, mar1, mar31; UBool indt = z->inDaylightTime(jan31=cal.getTime(status), status); failure(status, "inDaylightTime or getTime call on Jan 31"); if (indt) { errln("Fail: Jan 31 inDaylightTime=TRUE, exp FALSE"); } cal.set(1997, UCAL_MARCH, 1); indt = z->inDaylightTime(mar1=cal.getTime(status), status); failure(status, "inDaylightTime or getTime call on Mar 1"); if (!indt) { UnicodeString str; sdf.format(cal.getTime(status), str); failure(status, "getTime"); errln((UnicodeString)"Fail: " + str + " inDaylightTime=FALSE, exp TRUE"); } cal.set(1997, UCAL_MARCH, 31); indt = z->inDaylightTime(mar31=cal.getTime(status), status); failure(status, "inDaylightTime or getTime call on Mar 31"); if (indt) { errln("Fail: Mar 31 inDaylightTime=TRUE, exp FALSE"); } /* cal.set(1997, Calendar::DECEMBER, 31); UDate dec31 = cal.getTime(status); failure(status, "getTime"); UDate trans = findTransitionStepwise(*z, jan31, dec31); logln((UnicodeString)"Stepwise from " + sdf.format(jan31, str.remove()) + "; transition at " + (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE")); trans = findTransitionStepwise(*z, mar1, dec31); logln((UnicodeString)"Stepwise from " + sdf.format(mar1, str.remove()) + "; transition at " + (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE")); trans = findTransitionStepwise(*z, mar31, dec31); logln((UnicodeString)"Stepwise from " + sdf.format(mar31, str.remove()) + "; transition at " + (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE")); */ }
/** * 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; }
// test new API for JDK 1.2 8/31 putback void TimeZoneRegressionTest::TestJDK12API() { // 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; } SimpleTimeZone *cst = dynamic_cast<SimpleTimeZone *>(cst1); if(pst->hasSameRules(*cst)) { errln("FAILURE: PST and CST have same rules"); } UErrorCode status = U_ZERO_ERROR; int32_t offset1 = pst->getOffset(1, 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), status); failure(status, "getOffset() failed"); int32_t offset2 = cst->getOffset(1, 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), 31, status); failure(status, "getOffset() failed"); if(offset1 == offset2) errln("FAILURE: Sunday Oct. 26 1997 2:00 has same offset for PST and CST"); // verify error checking pst->getOffset(1, 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"); status = U_ZERO_ERROR; cst->setDSTSavings(60*60*1000, status); failure(status, "setDSTSavings() failed"); int32_t savings = cst->getDSTSavings(); if(savings != 60*60*1000) { errln("setDSTSavings() failed"); } delete pst; delete cst; }