ICU-8943 RBTZ fix in ICU4C and its test case

X-SVN-Rev: 31009
This commit is contained in:
Yoshito Umaoka 2011-12-02 07:02:54 +00:00
parent f45fb4a410
commit 4334ee838f
3 changed files with 62 additions and 10 deletions

View File

@ -1,6 +1,6 @@
/* /*
******************************************************************************* *******************************************************************************
* Copyright (C) 2007-2010, International Business Machines Corporation and * Copyright (C) 2007-2011, International Business Machines Corporation and
* others. All Rights Reserved. * others. All Rights Reserved.
******************************************************************************* *******************************************************************************
*/ */
@ -428,8 +428,10 @@ RuleBasedTimeZone::getOffsetInternal(UDate date, UBool local,
if (date > tend) { if (date > tend) {
if (fFinalRules != NULL) { if (fFinalRules != NULL) {
rule = findRuleInFinal(date, local, NonExistingTimeOpt, DuplicatedTimeOpt); rule = findRuleInFinal(date, local, NonExistingTimeOpt, DuplicatedTimeOpt);
} else { }
// no final rule, use the last rule if (rule == NULL) {
// no final rules or the given time is before the first transition
// specified by the final rules -> use the last rule
rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to; rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to;
} }
} else { } else {
@ -701,12 +703,17 @@ RuleBasedTimeZone::findRuleInFinal(UDate date, UBool local,
} }
UBool avail1 = fr1->getPreviousStart(base, fr0->getRawOffset(), fr0->getDSTSavings(), TRUE, start1); UBool avail1 = fr1->getPreviousStart(base, fr0->getRawOffset(), fr0->getDSTSavings(), TRUE, start1);
if (avail0 && (!avail1 || start0 > start1)) { if (!avail0 || !avail1) {
return fr0; if (avail0) {
} else if (avail1) { return fr0;
return fr1; } else if (avail1) {
return fr1;
}
// Both rules take effect after the given time
return NULL;
} }
return NULL;
return (start0 > start1) ? fr0 : fr1;
} }
UBool UBool

View File

@ -1,6 +1,6 @@
/* /*
******************************************************************************* *******************************************************************************
* Copyright (C) 2007-2010, International Business Machines Corporation and * * Copyright (C) 2007-2011, International Business Machines Corporation and *
* others. All Rights Reserved. * * others. All Rights Reserved. *
******************************************************************************* *******************************************************************************
*/ */
@ -140,6 +140,7 @@ void TimeZoneRuleTest::runIndexedTest( int32_t index, UBool exec, const char* &n
CASE(14, TestT6216); CASE(14, TestT6216);
CASE(15, TestT6669); CASE(15, TestT6669);
CASE(16, TestVTimeZoneWrapper); CASE(16, TestVTimeZoneWrapper);
CASE(17, TestT8943);
default: name = ""; break; default: name = ""; break;
} }
} }
@ -2616,6 +2617,49 @@ static UBool hasEquivalentTransitions(/*const*/ BasicTimeZone& tz1, /*const*/Bas
return TRUE; 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 {
int 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 */ #endif /* #if !UCONFIG_NO_FORMATTING */

View File

@ -1,6 +1,6 @@
/* /*
******************************************************************************* *******************************************************************************
* Copyright (C) 2007-2009, International Business Machines Corporation and * * Copyright (C) 2007-2011, International Business Machines Corporation and *
* others. All Rights Reserved. * * others. All Rights Reserved. *
******************************************************************************* *******************************************************************************
*/ */
@ -37,6 +37,7 @@ public:
void TestT6216(void); void TestT6216(void);
void TestT6669(void); void TestT6669(void);
void TestVTimeZoneWrapper(void); void TestVTimeZoneWrapper(void);
void TestT8943(void);
private: private:
void verifyTransitions(BasicTimeZone& icutz, UDate start, UDate end); void verifyTransitions(BasicTimeZone& icutz, UDate start, UDate end);