/*
*******************************************************************************
-* Copyright (C) 2007-2008, International Business Machines Corporation and *
-* others. All Rights Reserved. *
+* Copyright (C) 2007-2016, International Business Machines Corporation and
+* others. All Rights Reserved.
*******************************************************************************
*/
#include "unicode/gregocal.h"
#include "unicode/ucal.h"
#include "unicode/unistr.h"
+#include "unicode/ustring.h"
#include "unicode/tztrans.h"
#include "unicode/vtzone.h"
#include "tzrulets.h"
+#include "zrule.h"
+#include "ztrans.h"
+#include "vzone.h"
+#include "cmemory.h"
#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
#define HOUR (60*60*1000)
"Etc/GMT+8"
};
+static UBool hasEquivalentTransitions(/*const*/ BasicTimeZone& tz1, /*const*/BasicTimeZone& tz2,
+ UDate start, UDate end,
+ UBool ignoreDstAmount, int32_t maxTransitionTimeDelta,
+ UErrorCode& status);
+
class TestZIDEnumeration : public StringEnumeration {
public:
TestZIDEnumeration(UBool all = FALSE);
len = tzenum->count(status);
} else {
tzenum = NULL;
- len = (int32_t)sizeof(TESTZIDS)/sizeof(TESTZIDS[0]);
+ len = UPRV_LENGTHOF(TESTZIDS);
}
}
CASE(12, TestVTimeZoneCoverage);
CASE(13, TestVTimeZoneParse);
CASE(14, TestT6216);
+ CASE(15, TestT6669);
+ CASE(16, TestVTimeZoneWrapper);
+ CASE(17, TestT8943);
default: name = ""; break;
}
}
GregorianCalendar *cal = new GregorianCalendar(status);
if (U_FAILURE(status)) {
- errln("FAIL: Could not create a Gregorian calendar instance.");
+ dataerrln("FAIL: Could not create a Gregorian calendar instance.: %s", u_errorName(status));
+ delete rbtz1;
+ delete rbtz2;
+ delete rbtz3;
+ delete rbtz1c;
+ return;
}
cal->setTimeZone(*rbtz1);
cal->clear();
UDate jan1_2010 = getUTCMillis(2010, UCAL_JANUARY, 1);
if (!ny->hasEquivalentTransitions(*rbtz, jan1_1967, jan1_2010, TRUE, status)) {
- errln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010");
+ dataerrln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010");
}
if (U_FAILURE(status)) {
errln("FAIL: error returned from hasEquivalentTransitions for ny/rbtz 1967-2010");
// Same with above, but calling RBTZ#hasEquivalentTransitions against OlsonTimeZone
if (!rbtz->hasEquivalentTransitions(*ny, jan1_1967, jan1_2010, TRUE, status)) {
- errln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010");
+ dataerrln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010 ");
}
if (U_FAILURE(status)) {
errln("FAIL: error returned from hasEquivalentTransitions for rbtz/ny 1967-2010");
errln("FAIL: ny->getOffset failed");
}
if (offset1 != offset2 || dst1 != dst2) {
- errln("FAIL: Incompatible time zone offset/dstSavings for ny and rbtz");
+ dataerrln("FAIL: Incompatible time zone offset/dstSavings for ny and rbtz");
}
// Check inDaylightTime
if (rbtz->inDaylightTime(times[i], status) != ny->inDaylightTime(times[i], status)) {
- errln("FAIL: Incompatible daylight saving time for ny and rbtz");
+ dataerrln("FAIL: Incompatible daylight saving time for ny and rbtz");
}
if (U_FAILURE(status)) {
errln("FAIL: inDaylightTime failed");
UDate jan1_2011 = getUTCMillis(2010, UCAL_JANUARY, 1);
if (newyork->hasEquivalentTransitions(*indianapolis, jan1_2005, jan1_2011, TRUE, status)) {
- errln("FAIL: New_York is not equivalent to Indianapolis between 2005 and 2010");
+ dataerrln("FAIL: New_York is not equivalent to Indianapolis between 2005 and 2010");
}
if (U_FAILURE(status)) {
errln("FAIL: error status is returned from hasEquivalentTransition");
errln("FAIL: error status is returned from hasEquivalentTransition");
}
if (indianapolis->hasEquivalentTransitions(*gmt_5, jan1_1971, jan1_2007, TRUE, status)) {
- errln("FAIL: Indianapolis is not equivalent to GMT+5 between 1971 and 2006");
+ dataerrln("FAIL: Indianapolis is not equivalent to GMT+5 between 1971 and 2006");
}
if (U_FAILURE(status)) {
errln("FAIL: error status is returned from hasEquivalentTransition");
// raw offsets are different
BasicTimeZone *losangeles = (BasicTimeZone*)TimeZone::createTimeZone("America/Los_Angeles");
if (newyork->hasEquivalentTransitions(*losangeles, jan1_2006, jan1_2011, TRUE, status)) {
- errln("FAIL: New_York is not equivalent to Los Angeles, but returned true");
+ dataerrln("FAIL: New_York is not equivalent to Los Angeles, but returned true");
}
if (U_FAILURE(status)) {
errln("FAIL: error status is returned from hasEquivalentTransition for newyork/losangeles");
if (avail) {
if (!vtz_new->hasEquivalentTransitions(*tz, trans.getTime(),
endTime, TRUE, status)) {
- errln("FAIL: VTimeZone for " + *tzid +
- " is not equivalent to its OlsonTimeZone corresponding.");
+ int32_t maxDelta = 1000;
+ if (!hasEquivalentTransitions(*vtz_new, *tz, trans.getTime() + maxDelta,
+ endTime, TRUE, maxDelta, status)) {
+ errln("FAIL: VTimeZone for " + *tzid +
+ " is not equivalent to its OlsonTimeZone corresponding.");
+ } else {
+ logln("VTimeZone for " + *tzid +
+ " differs from its OlsonTimeZone corresponding with maximum transition time delta - " + maxDelta);
+ }
}
if (U_FAILURE(status)) {
errln("FAIL: error status is returned from hasEquivalentTransition");
if (avail) {
if (!vtz_new->hasEquivalentTransitions(*tz, trans.getTime(),
endTime, TRUE, status)) {
- errln("FAIL: VTimeZone for " + *tzid +
- " is not equivalent to its OlsonTimeZone corresponding.");
+ int32_t maxDelta = 1000;
+ if (!hasEquivalentTransitions(*vtz_new, *tz, trans.getTime() + maxDelta,
+ endTime, TRUE, maxDelta, status)) {
+ errln("FAIL: VTimeZone for " + *tzid +
+ " is not equivalent to its OlsonTimeZone corresponding.");
+ } else {
+ logln("VTimeZone for " + *tzid +
+ " differs from its OlsonTimeZone corresponding with maximum transition time delta - " + maxDelta);
+ }
+
}
if (U_FAILURE(status)) {
errln("FAIL: error status is returned from hasEquivalentTransition");
getUTCMillis(2005, UCAL_JULY, 1),
getUTCMillis(2010, UCAL_NOVEMBER, 1),
};
- int32_t numTimes = sizeof(testTimes)/sizeof(UDate);
+ int32_t numTimes = UPRV_LENGTHOF(testTimes);
UErrorCode status = U_ZERO_ERROR;
TestZIDEnumeration tzenum(!quick);
InitialTimeZoneRule *initial;
if (initial == NULL) {
errln("FAIL: initial rule must not be NULL");
break;
- } else if (!(std == NULL && dst == NULL || std != NULL && dst != NULL)) {
+ } else if (!((std == NULL && dst == NULL) || (std != NULL && dst != NULL))) {
errln("FAIL: invalid std/dst pair.");
break;
}
}
b1 = a3->getNextStart(time2, -3*HOUR, 0, FALSE, d1);
if (b1) {
- errln("FAIL: getNextStart must return FALSE when no start time is available after the base time");
+ dataerrln("FAIL: getNextStart must return FALSE when no start time is available after the base time");
}
b1 = a3->getFinalStart(-3*HOUR, 0, d1);
b2 = a3->getPreviousStart(time2, -3*HOUR, 0, FALSE, d2);
if (!b1 || !b2 || d1 != d2) {
- errln("FAIL: getPreviousStart does not match with getFinalStart after the end year");
+ dataerrln("FAIL: getPreviousStart does not match with getFinalStart after the end year");
}
// AnnualTimeZone::isEquavalentTo
// TimeArrayTimeZoneRule::getNextStart/getPreviousStart
b1 = t3->getNextStart(time1, -3*HOUR, 1*HOUR, FALSE, d1);
if (b1) {
- errln("FAIL: getNextStart returned TRUE after the final transition for t3");
+ dataerrln("FAIL: getNextStart returned TRUE after the final transition for t3");
}
b1 = t3->getPreviousStart(time1, -3*HOUR, 1*HOUR, FALSE, d1);
if (!b1 || d1 != trtimes2[1]) {
- errln("FAIL: Bad start time returned by getPreviousStart for t3");
+ dataerrln("FAIL: Bad start time returned by getPreviousStart for t3");
} else {
b2 = t3->getPreviousStart(d1, -3*HOUR, 1*HOUR, FALSE, d2);
if (!b2 || d2 != trtimes2[0]) {
UBool inDst1, inDst2;
inDst1 = otz->inDaylightTime(t, status);
if (U_FAILURE(status)) {
- errln("FAIL: inDaylightTime failed for otz");
+ dataerrln("FAIL: inDaylightTime failed for otz: %s", u_errorName(status));
}
inDst2 = vtz->inDaylightTime(t, status);
if (U_FAILURE(status)) {
- errln("FAIL: inDaylightTime failed for vtz");
+ dataerrln("FAIL: inDaylightTime failed for vtz: %s", u_errorName(status));
}
if (inDst1 != inDst2) {
errln("FAIL: inDaylightTime returned different results in VTimeZone and OlsonTimeZone");
UBool btr1 = otz->getNextTransition(base, TRUE, tzt1);
UBool btr2 = vtz->getNextTransition(base, TRUE, tzt2);
if (!btr1 || !btr2 || tzt1 != tzt2) {
- errln("FAIL: getNextTransition returned different results in VTimeZone and OlsonTimeZone");
+ dataerrln("FAIL: getNextTransition returned different results in VTimeZone and OlsonTimeZone");
}
btr1 = otz->getPreviousTransition(base, FALSE, tzt1);
btr2 = vtz->getPreviousTransition(base, FALSE, tzt2);
if (!btr1 || !btr2 || tzt1 != tzt2) {
- errln("FAIL: getPreviousTransition returned different results in VTimeZone and OlsonTimeZone");
+ dataerrln("FAIL: getPreviousTransition returned different results in VTimeZone and OlsonTimeZone");
}
// TimeZoneTransition constructor/clone
UDate time2 = getUTCMillis(2020, UCAL_JANUARY, 1);
UBool equiv = vtz->hasEquivalentTransitions(*otz, time1, time2, FALSE, status);
if (U_FAILURE(status)) {
- errln("FAIL: hasEquivalentTransitions failed for vtz/otz");
+ dataerrln("FAIL: hasEquivalentTransitions failed for vtz/otz: %s", u_errorName(status));
}
if (!equiv) {
- errln("FAIL: hasEquivalentTransitons returned false for the same time zone");
+ dataerrln("FAIL: hasEquivalentTransitons returned false for the same time zone");
}
// operator=/operator==/operator!=
errln("FAIL: VTimeZone vtz1 is equal to vtz, but got wrong result");
}
+ // Creation from BasicTimeZone
+ //
+ status = U_ZERO_ERROR;
+ VTimeZone *vtzFromBasic = NULL;
+ SimpleTimeZone *simpleTZ = new SimpleTimeZone(28800000, "Asia/Singapore");
+ simpleTZ->setStartYear(1970);
+ simpleTZ->setStartRule(0, // month
+ 1, // day of week
+ 0, // time
+ status);
+ simpleTZ->setEndRule(1, 1, 0, status);
+ if (U_FAILURE(status)) {
+ errln("File %s, line %d, failed with status = %s", __FILE__, __LINE__, u_errorName(status));
+ goto end_basic_tz_test;
+ }
+ vtzFromBasic = VTimeZone::createVTimeZoneFromBasicTimeZone(*simpleTZ, status);
+ if (U_FAILURE(status) || vtzFromBasic == NULL) {
+ dataerrln("File %s, line %d, failed with status = %s", __FILE__, __LINE__, u_errorName(status));
+ goto end_basic_tz_test;
+ }
+
+ // delete the source time zone, to make sure there are no dependencies on it.
+ delete simpleTZ;
+
+ // Create another simple time zone w the same rules, and check that it is the
+ // same as the test VTimeZone created above.
+ {
+ SimpleTimeZone simpleTZ2(28800000, "Asia/Singapore");
+ simpleTZ2.setStartYear(1970);
+ simpleTZ2.setStartRule(0, // month
+ 1, // day of week
+ 0, // time
+ status);
+ simpleTZ2.setEndRule(1, 1, 0, status);
+ if (U_FAILURE(status)) {
+ errln("File %s, line %d, failed with status = %s", __FILE__, __LINE__, u_errorName(status));
+ goto end_basic_tz_test;
+ }
+ if (vtzFromBasic->hasSameRules(simpleTZ2) == FALSE) {
+ errln("File %s, line %d, failed hasSameRules() ", __FILE__, __LINE__);
+ goto end_basic_tz_test;
+ }
+ }
+end_basic_tz_test:
+ delete vtzFromBasic;
+
delete otz;
delete vtz;
delete tmpvtz;
{0, 0, 0}
};
- static const UnicodeString TestZones[] = {
+ /*static*/ const UnicodeString TestZones[] = {
UnicodeString(tokyoTZ),
UnicodeString(finalOverlap),
UnicodeString(finalNonOverlap),
int32_t i, j;
// Get test times
- UDate times[sizeof(TestDates) / (3 * sizeof(int32_t))];
+ UDate times[UPRV_LENGTHOF(TestDates)];
int32_t numTimes;
UErrorCode status = U_ZERO_ERROR;
TimeZone *utc = TimeZone::createTimeZone("Etc/GMT");
GregorianCalendar cal(utc, status);
if (U_FAILURE(status)) {
- errln("FAIL: Failed to creat a GregorianCalendar");
+ dataerrln("FAIL: Failed to creat a GregorianCalendar: %s", u_errorName(status));
return;
}
for (i = 0; TestDates[i][2] != 0; i++) {
}
}
+void
+TimeZoneRuleTest::TestT6669(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ SimpleTimeZone stz(0, "CustomID", UCAL_JANUARY, 1, UCAL_SUNDAY, 0, UCAL_JULY, 1, UCAL_SUNDAY, 0, status);
+ if (U_FAILURE(status)) {
+ errln("FAIL: Failed to creat a SimpleTimeZone");
+ return;
+ }
+
+ UDate t = 1230681600000.0; //2008-12-31T00:00:00
+ UDate expectedNext = 1231027200000.0; //2009-01-04T00:00:00
+ UDate expectedPrev = 1215298800000.0; //2008-07-06T00:00:00
+
+ TimeZoneTransition tzt;
+ UBool avail = stz.getNextTransition(t, FALSE, tzt);
+ if (!avail) {
+ errln("FAIL: No transition returned by getNextTransition.");
+ } else if (tzt.getTime() != expectedNext) {
+ errln((UnicodeString)"FAIL: Wrong transition time returned by getNextTransition - "
+ + tzt.getTime() + " Expected: " + expectedNext);
+ }
+
+ avail = stz.getPreviousTransition(t, TRUE, tzt);
+ if (!avail) {
+ errln("FAIL: No transition returned by getPreviousTransition.");
+ } else if (tzt.getTime() != expectedPrev) {
+ errln((UnicodeString)"FAIL: Wrong transition time returned by getPreviousTransition - "
+ + tzt.getTime() + " Expected: " + expectedPrev);
+ }
+}
+
+void
+TimeZoneRuleTest::TestVTimeZoneWrapper(void) {
+#if 0
+ // local variables
+ UBool b;
+ UChar * data = NULL;
+ int32_t length = 0;
+ int32_t i;
+ UDate result;
+ UDate base = 1231027200000.0; //2009-01-04T00:00:00
+ UErrorCode status;
+
+ const char *name = "Test Initial";
+ UChar uname[20];
+
+ UClassID cid1;
+ UClassID cid2;
+
+ ZRule * r;
+ IZRule* ir1;
+ IZRule* ir2;
+ ZTrans* zt1;
+ ZTrans* zt2;
+ VZone* v1;
+ VZone* v2;
+
+ uprv_memset(uname, 0, sizeof(uname));
+ u_uastrcpy(uname, name);
+
+ // create rules
+ ir1 = izrule_open(uname, 13, 2*HOUR, 0);
+ ir2 = izrule_clone(ir1);
+
+ // test equality
+ b = izrule_equals(ir1, ir2);
+ b = izrule_isEquivalentTo(ir1, ir2);
+
+ // test accessors
+ izrule_getName(ir1, data, length);
+ i = izrule_getRawOffset(ir1);
+ i = izrule_getDSTSavings(ir1);
+
+ b = izrule_getFirstStart(ir1, 2*HOUR, 0, result);
+ b = izrule_getFinalStart(ir1, 2*HOUR, 0, result);
+ b = izrule_getNextStart(ir1, base , 2*HOUR, 0, true, result);
+ b = izrule_getPreviousStart(ir1, base, 2*HOUR, 0, true, result);
+
+ // test class ids
+ cid1 = izrule_getStaticClassID(ir1);
+ cid2 = izrule_getDynamicClassID(ir1);
+
+ // test transitions
+ zt1 = ztrans_open(base, ir1, ir2);
+ zt2 = ztrans_clone(zt1);
+ zt2 = ztrans_openEmpty();
+
+ // test equality
+ b = ztrans_equals(zt1, zt2);
+
+ // test accessors
+ result = ztrans_getTime(zt1);
+ ztrans_setTime(zt1, result);
+
+ r = (ZRule*)ztrans_getFrom(zt1);
+ ztrans_setFrom(zt1, (void*)ir1);
+ ztrans_adoptFrom(zt1, (void*)ir1);
+
+ r = (ZRule*)ztrans_getTo(zt1);
+ ztrans_setTo(zt1, (void*)ir2);
+ ztrans_adoptTo(zt1, (void*)ir2);
+
+ // test class ids
+ cid1 = ztrans_getStaticClassID(zt1);
+ cid2 = ztrans_getDynamicClassID(zt2);
+
+ // test vzone
+ v1 = vzone_openID((UChar*)"America/Chicago", sizeof("America/Chicago"));
+ v2 = vzone_clone(v1);
+ //v2 = vzone_openData(const UChar* vtzdata, int32_t vtzdataLength, UErrorCode& status);
+
+ // test equality
+ b = vzone_equals(v1, v2);
+ b = vzone_hasSameRules(v1, v2);
+
+ // test accessors
+ b = vzone_getTZURL(v1, data, length);
+ vzone_setTZURL(v1, data, length);
+
+ b = vzone_getLastModified(v1, result);
+ vzone_setLastModified(v1, result);
+
+ // test writers
+ vzone_write(v1, data, length, status);
+ vzone_writeFromStart(v1, result, data, length, status);
+ vzone_writeSimple(v1, result, data, length, status);
+
+ // test more accessors
+ i = vzone_getRawOffset(v1);
+ vzone_setRawOffset(v1, i);
+
+ b = vzone_useDaylightTime(v1);
+ b = vzone_inDaylightTime(v1, result, status);
+
+ b = vzone_getNextTransition(v1, result, false, zt1);
+ b = vzone_getPreviousTransition(v1, result, false, zt1);
+ i = vzone_countTransitionRules(v1, status);
+
+ cid1 = vzone_getStaticClassID(v1);
+ cid2 = vzone_getDynamicClassID(v1);
+
+ // cleanup
+ vzone_close(v1);
+ vzone_close(v2);
+ ztrans_close(zt1);
+ ztrans_close(zt2);
+#endif
+}
+
//----------- private test helpers -------------------------------------------------
UDate
Calendar *cal = Calendar::createInstance(*tz, status);
if (U_FAILURE(status)) {
delete cal;
- errln("FAIL: Calendar::createInstance failed");
+ dataerrln("FAIL: Calendar::createInstance failed: %s", u_errorName(status));
return 0.0;
}
cal->set(y, m, d, hr, min, sec);
}
}
+// Slightly modified version of BasicTimeZone::hasEquivalentTransitions.
+// This version returns TRUE if transition time delta is within the given
+// delta range.
+static UBool hasEquivalentTransitions(/*const*/ BasicTimeZone& tz1, /*const*/BasicTimeZone& tz2,
+ UDate start, UDate end,
+ UBool ignoreDstAmount, int32_t maxTransitionTimeDelta,
+ UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return FALSE;
+ }
+ if (tz1.hasSameRules(tz2)) {
+ return TRUE;
+ }
+ // Check the offsets at the start time
+ int32_t raw1, raw2, dst1, dst2;
+ tz1.getOffset(start, FALSE, raw1, dst1, status);
+ if (U_FAILURE(status)) {
+ return FALSE;
+ }
+ tz2.getOffset(start, FALSE, raw2, dst2, status);
+ if (U_FAILURE(status)) {
+ return FALSE;
+ }
+ if (ignoreDstAmount) {
+ if ((raw1 + dst1 != raw2 + dst2)
+ || (dst1 != 0 && dst2 == 0)
+ || (dst1 == 0 && dst2 != 0)) {
+ return FALSE;
+ }
+ } else {
+ if (raw1 != raw2 || dst1 != dst2) {
+ return FALSE;
+ }
+ }
+ // Check transitions in the range
+ UDate time = start;
+ TimeZoneTransition tr1, tr2;
+ while (TRUE) {
+ UBool avail1 = tz1.getNextTransition(time, FALSE, tr1);
+ UBool avail2 = tz2.getNextTransition(time, FALSE, tr2);
+
+ if (ignoreDstAmount) {
+ // Skip a transition which only differ the amount of DST savings
+ while (TRUE) {
+ if (avail1
+ && tr1.getTime() <= end
+ && (tr1.getFrom()->getRawOffset() + tr1.getFrom()->getDSTSavings()
+ == tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings())
+ && (tr1.getFrom()->getDSTSavings() != 0 && tr1.getTo()->getDSTSavings() != 0)) {
+ tz1.getNextTransition(tr1.getTime(), FALSE, tr1);
+ } else {
+ break;
+ }
+ }
+ while (TRUE) {
+ if (avail2
+ && tr2.getTime() <= end
+ && (tr2.getFrom()->getRawOffset() + tr2.getFrom()->getDSTSavings()
+ == tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings())
+ && (tr2.getFrom()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() != 0)) {
+ tz2.getNextTransition(tr2.getTime(), FALSE, tr2);
+ } else {
+ break;
+ }
+ }
+ }
+
+ UBool inRange1 = (avail1 && tr1.getTime() <= end);
+ UBool inRange2 = (avail2 && tr2.getTime() <= end);
+ if (!inRange1 && !inRange2) {
+ // No more transition in the range
+ break;
+ }
+ if (!inRange1 || !inRange2) {
+ return FALSE;
+ }
+ double delta = tr1.getTime() >= tr2.getTime() ? tr1.getTime() - tr2.getTime() : tr2.getTime() - tr1.getTime();
+ if (delta > (double)maxTransitionTimeDelta) {
+ return FALSE;
+ }
+ if (ignoreDstAmount) {
+ if (tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings()
+ != tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings()
+ || (tr1.getTo()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() == 0)
+ || (tr1.getTo()->getDSTSavings() == 0 && tr2.getTo()->getDSTSavings() != 0)) {
+ return FALSE;
+ }
+ } else {
+ if (tr1.getTo()->getRawOffset() != tr2.getTo()->getRawOffset() ||
+ tr1.getTo()->getDSTSavings() != tr2.getTo()->getDSTSavings()) {
+ return FALSE;
+ }
+ }
+ time = tr1.getTime() > tr2.getTime() ? tr1.getTime() : tr2.getTime();
+ }
+ return TRUE;
+}
+
+// Test case for ticket#8943
+// RuleBasedTimeZone#getOffsets throws NPE
+void
+TimeZoneRuleTest::TestT8943(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString id("Ekaterinburg Time");
+ UnicodeString stdName("Ekaterinburg Standard Time");
+ UnicodeString dstName("Ekaterinburg Daylight Time");
+
+ InitialTimeZoneRule *initialRule = new InitialTimeZoneRule(stdName, 18000000, 0);
+ RuleBasedTimeZone *rbtz = new RuleBasedTimeZone(id, initialRule);
+
+ DateTimeRule *dtRule = new DateTimeRule(UCAL_OCTOBER, -1, UCAL_SUNDAY, 10800000, DateTimeRule::WALL_TIME);
+ AnnualTimeZoneRule *atzRule = new AnnualTimeZoneRule(stdName, 18000000, 0, dtRule, 2000, 2010);
+ rbtz->addTransitionRule(atzRule, status);
+
+ dtRule = new DateTimeRule(UCAL_MARCH, -1, UCAL_SUNDAY, 7200000, DateTimeRule::WALL_TIME);
+ atzRule = new AnnualTimeZoneRule(dstName, 18000000, 3600000, dtRule, 2000, 2010);
+ rbtz->addTransitionRule(atzRule, status);
+
+ dtRule = new DateTimeRule(UCAL_JANUARY, 1, 0, DateTimeRule::WALL_TIME);
+ atzRule = new AnnualTimeZoneRule(stdName, 21600000, 0, dtRule, 2011, AnnualTimeZoneRule::MAX_YEAR);
+ rbtz->addTransitionRule(atzRule, status);
+
+ dtRule = new DateTimeRule(UCAL_JANUARY, 1, 1, DateTimeRule::WALL_TIME);
+ atzRule = new AnnualTimeZoneRule(dstName, 21600000, 0, dtRule, 2011, AnnualTimeZoneRule::MAX_YEAR);
+ rbtz->addTransitionRule(atzRule, status);
+ rbtz->complete(status);
+
+ if (U_FAILURE(status)) {
+ errln("Failed to construct a RuleBasedTimeZone");
+ } else {
+ int32_t raw, dst;
+ rbtz->getOffset(1293822000000.0 /* 2010-12-31 19:00:00 UTC */, FALSE, raw, dst, status);
+ if (U_FAILURE(status)) {
+ errln("Error invoking getOffset");
+ } else if (raw != 21600000 || dst != 0) {
+ errln(UnicodeString("Fail: Wrong offsets: ") + raw + "/" + dst + " Expected: 21600000/0");
+ }
+ }
+
+ delete rbtz;
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */
//eof