ICU-5454 Ported additional time zone test cases from ICU4J. Also fixed some bugs found by the new test cases.

X-SVN-Rev: 22311
This commit is contained in:
Yoshito Umaoka 2007-08-08 00:57:05 +00:00
parent 35a19cf658
commit 0de5cefde3
8 changed files with 892 additions and 62 deletions

View file

@ -39,7 +39,7 @@ static UBool compareRules(UVector* rules1, UVector* rules2) {
for (int32_t i = 0; i < size; i++) {
TimeZoneRule *r1 = (TimeZoneRule*)rules1->elementAt(i);
TimeZoneRule *r2 = (TimeZoneRule*)rules2->elementAt(i);
if (r1 != r2) {
if (*r1 != *r2) {
return FALSE;
}
}
@ -63,7 +63,13 @@ RuleBasedTimeZone::RuleBasedTimeZone(const UnicodeString& id, InitialTimeZoneRul
RuleBasedTimeZone::RuleBasedTimeZone(const RuleBasedTimeZone& source)
: BasicTimeZone(source), fInitialRule(source.fInitialRule->clone()),
fHistoricRules(NULL), fFinalRules(NULL), fHistoricTransitions(NULL), fUpToDate(FALSE) {
fHistoricTransitions(NULL), fUpToDate(FALSE) {
fHistoricRules = copyRules(source.fHistoricRules);
fFinalRules = copyRules(source.fFinalRules);
if (source.fUpToDate) {
UErrorCode status = U_ZERO_ERROR;
complete(status);
}
}
RuleBasedTimeZone::~RuleBasedTimeZone() {
@ -568,14 +574,14 @@ RuleBasedTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial,
int32_t historicCount = fHistoricRules->size();
idx = 0;
while (cnt < trscount && idx < historicCount) {
trsrules[cnt++] = (const TimeZoneRule*)fHistoricRules->elementAt(idx);
trsrules[cnt++] = (const TimeZoneRule*)fHistoricRules->elementAt(idx++);
}
}
if (fFinalRules != NULL && cnt < trscount) {
int32_t finalCount = fFinalRules->size();
idx = 0;
while (cnt < trscount && idx < finalCount) {
trsrules[cnt++] = (const TimeZoneRule*)fFinalRules->elementAt(idx);
trsrules[cnt++] = (const TimeZoneRule*)fFinalRules->elementAt(idx++);
}
}
// Set the result length
@ -741,9 +747,13 @@ RuleBasedTimeZone::findNext(UDate base, UBool inclusive, UDate& transitionTime,
// For now, this implementation ignore transitions with only zone name changes.
if (result.from->getRawOffset() == result.to->getRawOffset()
&& result.from->getDSTSavings() == result.to->getDSTSavings()) {
// No offset changes. Try next one if not final
return findNext(result.time, FALSE /* always exclusive */,
transitionTime, fromRule, toRule);
if (isFinal) {
return FALSE;
} else {
// No offset changes. Try next one if not final
return findNext(result.time, FALSE /* always exclusive */,
transitionTime, fromRule, toRule);
}
}
transitionTime = result.time;
fromRule = result.from;

View file

@ -1106,13 +1106,15 @@ SimpleTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial,
if (U_FAILURE(status)) {
return;
}
int32_t cnt = 0;
initial = initialRule;
if (trscount > 0) {
trsrules[cnt++] = stdRule;
}
if (trscount > 1) {
trsrules[cnt++] = dstRule;
int32_t cnt = 0;
if (stdRule != NULL) {
if (cnt < trscount) {
trsrules[cnt++] = stdRule;
}
if (cnt < trscount) {
trsrules[cnt++] = dstRule;
}
}
trscount = cnt;
}

View file

@ -314,7 +314,7 @@ AnnualTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const {
return FALSE;
}
AnnualTimeZoneRule* that = (AnnualTimeZoneRule*)&other;
return (fDateTimeRule == that->fDateTimeRule &&
return (*fDateTimeRule == *(that->fDateTimeRule) &&
fStartYear == that->fStartYear &&
fEndYear == that->fEndYear);
}

View file

@ -65,9 +65,9 @@ TimeZoneTransition::operator==(const TimeZoneTransition& that) const {
return FALSE;
}
if (fFrom == NULL && that.fFrom == NULL
|| fFrom != NULL && that.fFrom != NULL && fFrom == that.fFrom) {
|| fFrom != NULL && that.fFrom != NULL && *fFrom == *(that.fFrom)) {
if (fTo == NULL && that.fTo == NULL
|| fTo != NULL && that.fTo != NULL && fTo == that.fTo) {
|| fTo != NULL && that.fTo != NULL && *fTo == *(that.fTo)) {
return TRUE;
}
}

View file

@ -369,7 +369,8 @@ private:
void writeFooter(VTZWriter& writer, UErrorCode& status) const;
void writeZonePropsByTime(VTZWriter& writer, UBool isDst, const UnicodeString& tzname,
int32_t fromOffset, int32_t toOffset, UDate time, UErrorCode& status) const;
int32_t fromOffset, int32_t toOffset, UDate time, UBool withRDATE,
UErrorCode& status) const;
void writeZonePropsByDOM(VTZWriter& writer, UBool isDst, const UnicodeString& tzname,
int32_t fromOffset, int32_t toOffset,
int32_t month, int32_t dayOfMonth, UDate startTime, UDate untilTime,

View file

@ -302,7 +302,9 @@ static int32_t offsetStrToMillis(const UnicodeString& str, UErrorCode& status) {
}
hour = parseAsciiDigits(str, 1, 2, status);
min = parseAsciiDigits(str, 3, 2, status);
sec = parseAsciiDigits(str, 5, 2, status);
if (length == 7) {
sec = parseAsciiDigits(str, 5, 2, status);
}
if (U_FAILURE(status)) {
break;
}
@ -697,7 +699,7 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& tzname, int rawOffse
} else if (dayOfWeek != 0 && nthDayOfWeek == 0 && dayOfMonth != 0) {
// First day of week after day of month rule, for example,
// first Sunday after 15th day in the month
adtr = new DateTimeRule(month, dayOfMonth, dayOfWeek, true, startMID, DateTimeRule::WALL_TIME);
adtr = new DateTimeRule(month, dayOfMonth, dayOfWeek, TRUE, startMID, DateTimeRule::WALL_TIME);
}
if (adtr == NULL) {
goto unsupportedRRule;
@ -713,33 +715,36 @@ unsupportedRRule:
* Create a TimeZoneRule by the RDATE definition
*/
static TimeZoneRule* createRuleByRDATE(const UnicodeString& tzname, int32_t rawOffset, int32_t dstSavings,
UDate /*start*/, UVector* dates, int32_t fromOffset, UErrorCode& status) {
UDate start, UVector* dates, int32_t fromOffset, UErrorCode& status) {
if (U_FAILURE(status)) {
return NULL;
}
TimeArrayTimeZoneRule *retVal = NULL;
if (dates == NULL || dates->size() == 0) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
// Create an array of transition times
int32_t size = dates->size();
UDate* times = (UDate*)uprv_malloc(sizeof(UDate) * size);
if (times == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
for (int32_t i = 0; i < size; i++) {
UnicodeString *datestr = (UnicodeString*)dates->elementAt(i);
times[i] = parseDateTimeString(*datestr, fromOffset, status);
if (U_FAILURE(status)) {
uprv_free(times);
// When no RDATE line is provided, use start (DTSTART)
// as the transition time
retVal = new TimeArrayTimeZoneRule(tzname, rawOffset, dstSavings,
&start, 1, DateTimeRule::UTC_TIME);
} else {
// Create an array of transition times
int32_t size = dates->size();
UDate* times = (UDate*)uprv_malloc(sizeof(UDate) * size);
if (times == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
for (int32_t i = 0; i < size; i++) {
UnicodeString *datestr = (UnicodeString*)dates->elementAt(i);
times[i] = parseDateTimeString(*datestr, fromOffset, status);
if (U_FAILURE(status)) {
uprv_free(times);
return NULL;
}
}
retVal = new TimeArrayTimeZoneRule(tzname, rawOffset, dstSavings,
times, size, DateTimeRule::UTC_TIME);
uprv_free(times);
}
TimeArrayTimeZoneRule *retVal = new TimeArrayTimeZoneRule(tzname, rawOffset, dstSavings,
times, size, DateTimeRule::UTC_TIME);
uprv_free(times);
return retVal;
}
@ -1257,6 +1262,9 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) {
}
}
if (!success) {
if (U_SUCCESS(status)) {
status = U_INVALID_STATE_ERROR;
}
goto cleanupVtzlines;
}
parse(status);
@ -1415,7 +1423,7 @@ VTimeZone::parse(UErrorCode& status) {
}
} else if (name.compare(ICAL_END) == 0) {
// Mandatory properties
if (dtstart.length() == 0 || from.length() == 0 || to.length() == 0 || dates == NULL) {
if (dtstart.length() == 0 || from.length() == 0 || to.length() == 0) {
goto cleanupParse;
}
// if tzname is not available, create one from tzid
@ -1526,6 +1534,7 @@ VTimeZone::parse(UErrorCode& status) {
delete dates;
tz = rbtz;
setID(tzid);
return;
cleanupParse:
@ -1809,7 +1818,8 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz,
}
if (!sameRule) {
if (dstCount == 1) {
writeZonePropsByTime(w, TRUE, dstName, dstFromOffset, dstToOffset, dstStartTime, status);
writeZonePropsByTime(w, TRUE, dstName, dstFromOffset, dstToOffset, dstStartTime,
TRUE, status);
} else {
writeZonePropsByDOW(w, TRUE, dstName, dstFromOffset, dstToOffset,
dstMonth, dstWeekInMonth, dstDayOfWeek, dstStartTime, dstUntilTime, status);
@ -1859,7 +1869,8 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz,
}
if (!sameRule) {
if (stdCount == 1) {
writeZonePropsByTime(w, FALSE, stdName, stdFromOffset, stdToOffset, stdStartTime, status);
writeZonePropsByTime(w, FALSE, stdName, stdFromOffset, stdToOffset, stdStartTime,
TRUE, status);
} else {
writeZonePropsByDOW(w, FALSE, stdName, stdFromOffset, stdToOffset,
stdMonth, stdWeekInMonth, stdDayOfWeek, stdStartTime, stdUntilTime, status);
@ -1901,7 +1912,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz,
basictz.getID(tzid);
getDefaultTZName(tzid, isDst, name);
writeZonePropsByTime(w, isDst, name,
offset, offset, DEF_TZSTARTTIME - offset, status);
offset, offset, DEF_TZSTARTTIME - offset, FALSE, status);
if (U_FAILURE(status)) {
goto cleanupWriteZone;
}
@ -1909,7 +1920,8 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz,
if (dstCount > 0) {
if (finalDstRule == NULL) {
if (dstCount == 1) {
writeZonePropsByTime(w, TRUE, dstName, dstFromOffset, dstToOffset, dstStartTime, status);
writeZonePropsByTime(w, TRUE, dstName, dstFromOffset, dstToOffset, dstStartTime,
TRUE, status);
} else {
writeZonePropsByDOW(w, TRUE, dstName, dstFromOffset, dstToOffset,
dstMonth, dstWeekInMonth, dstDayOfWeek, dstStartTime, dstUntilTime, status);
@ -1945,7 +1957,8 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz,
if (stdCount > 0) {
if (finalStdRule == NULL) {
if (stdCount == 1) {
writeZonePropsByTime(w, FALSE, stdName, stdFromOffset, stdToOffset, stdStartTime, status);
writeZonePropsByTime(w, FALSE, stdName, stdFromOffset, stdToOffset, stdStartTime,
TRUE, status);
} else {
writeZonePropsByDOW(w, FALSE, stdName, stdFromOffset, stdToOffset,
stdMonth, stdWeekInMonth, stdDayOfWeek, stdStartTime, stdUntilTime, status);
@ -2037,11 +2050,12 @@ VTimeZone::writeFooter(VTZWriter& writer, UErrorCode& status) const {
}
/*
* Write a single start time using VTIMEZONE RDATE
* Write a single start time
*/
void
VTimeZone::writeZonePropsByTime(VTZWriter& writer, UBool isDst, const UnicodeString& tzname,
int32_t fromOffset, int32_t toOffset, UDate time, UErrorCode& status) const {
int32_t fromOffset, int32_t toOffset, UDate time, UBool withRDATE,
UErrorCode& status) const {
if (U_FAILURE(status)) {
return;
}
@ -2049,11 +2063,13 @@ VTimeZone::writeZonePropsByTime(VTZWriter& writer, UBool isDst, const UnicodeStr
if (U_FAILURE(status)) {
return;
}
writer.write(ICAL_RDATE);
writer.write(COLON);
UnicodeString timestr;
writer.write(getDateTimeString(time + fromOffset, timestr));
writer.write(ICAL_NEWLINE);
if (withRDATE) {
writer.write(ICAL_RDATE);
writer.write(COLON);
UnicodeString timestr;
writer.write(getDateTimeString(time + fromOffset, timestr));
writer.write(ICAL_NEWLINE);
}
endZoneProps(writer, isDst, status);
if (U_FAILURE(status)) {
return;

View file

@ -15,6 +15,7 @@
#include "unicode/simpletz.h"
#include "unicode/tzrule.h"
#include "unicode/calendar.h"
#include "unicode/gregocal.h"
#include "unicode/ucal.h"
#include "unicode/unistr.h"
#include "unicode/tztrans.h"
@ -120,6 +121,10 @@ void TimeZoneRuleTest::runIndexedTest( int32_t index, UBool exec, const char* &n
CASE(7, TestVTimeZoneSimpleWrite);
CASE(8, TestVTimeZoneHeaderProps);
CASE(9, TestGetSimpleRules);
CASE(10, TestTimeZoneRuleCoverage);
CASE(11, TestSimpleTimeZoneCoverage);
CASE(12, TestVTimeZoneCoverage);
CASE(13, TestVTimeZoneParse);
default: name = ""; break;
}
}
@ -237,10 +242,134 @@ TimeZoneRuleTest::TestSimpleRuleBasedTimeZone(void) {
errln("FAIL: error returned from hasEquivalentTransitions");
}
// hasSameRules
if (rbtz1->hasSameRules(*rbtz2)) {
errln("FAIL: rbtz1 and rbtz2 have different rules, but returned true.");
}
if (rbtz1->hasSameRules(*rbtz3)) {
errln("FAIL: rbtz1 and rbtz3 have different rules, but returned true.");
}
RuleBasedTimeZone *rbtz1c = (RuleBasedTimeZone*)rbtz1->clone();
if (!rbtz1->hasSameRules(*rbtz1c)) {
errln("FAIL: Cloned RuleBasedTimeZone must have the same rules with the original.");
}
// getOffset
int32_t era, year, month, dayOfMonth, dayOfWeek, millisInDay;
UDate time;
int32_t offset, dstSavings;
UBool dst;
GregorianCalendar *cal = new GregorianCalendar(status);
if (U_FAILURE(status)) {
errln("FAIL: Could not create a Gregorian calendar instance.");
}
cal->setTimeZone(*rbtz1);
cal->clear();
// Jan 1, 1000 BC
cal->set(UCAL_ERA, GregorianCalendar::BC);
cal->set(1000, UCAL_JANUARY, 1);
era = cal->get(UCAL_ERA, status);
year = cal->get(UCAL_YEAR, status);
month = cal->get(UCAL_MONTH, status);
dayOfMonth = cal->get(UCAL_DAY_OF_MONTH, status);
dayOfWeek = cal->get(UCAL_DAY_OF_WEEK, status);
millisInDay = cal->get(UCAL_MILLISECONDS_IN_DAY, status);
time = cal->getTime(status);
if (U_FAILURE(status)) {
errln("FAIL: Could not get calendar field values.");
}
offset = rbtz1->getOffset(era, year, month, dayOfMonth, dayOfWeek, millisInDay, status);
if (U_FAILURE(status)) {
errln("FAIL: getOffset(7 args) failed.");
}
if (offset != 0) {
errln(UnicodeString("FAIL: Invalid time zone offset: ") + offset + " /expected: 0");
}
dst = rbtz1->inDaylightTime(time, status);
if (U_FAILURE(status)) {
errln("FAIL: inDaylightTime failed.");
}
if (!dst) {
errln("FAIL: Invalid daylight saving time");
}
rbtz1->getOffset(time, TRUE, offset, dstSavings, status);
if (U_FAILURE(status)) {
errln("FAIL: getOffset(5 args) failed.");
}
if (offset != -3600000) {
errln(UnicodeString("FAIL: Invalid time zone raw offset: ") + offset + " /expected: -3600000");
}
if (dstSavings != 3600000) {
errln(UnicodeString("FAIL: Invalid DST amount: ") + dstSavings + " /expected: 3600000");
}
// July 1, 2000, AD
cal->set(UCAL_ERA, GregorianCalendar::AD);
cal->set(2000, UCAL_JULY, 1);
era = cal->get(UCAL_ERA, status);
year = cal->get(UCAL_YEAR, status);
month = cal->get(UCAL_MONTH, status);
dayOfMonth = cal->get(UCAL_DAY_OF_MONTH, status);
dayOfWeek = cal->get(UCAL_DAY_OF_WEEK, status);
millisInDay = cal->get(UCAL_MILLISECONDS_IN_DAY, status);
time = cal->getTime(status);
if (U_FAILURE(status)) {
errln("FAIL: Could not get calendar field values.");
}
offset = rbtz1->getOffset(era, year, month, dayOfMonth, dayOfWeek, millisInDay, status);
if (U_FAILURE(status)) {
errln("FAIL: getOffset(7 args) failed.");
}
if (offset != -3600000) {
errln(UnicodeString("FAIL: Invalid time zone offset: ") + offset + " /expected: -3600000");
}
dst = rbtz1->inDaylightTime(time, status);
if (U_FAILURE(status)) {
errln("FAIL: inDaylightTime failed.");
}
if (dst) {
errln("FAIL: Invalid daylight saving time");
}
rbtz1->getOffset(time, TRUE, offset, dstSavings, status);
if (U_FAILURE(status)) {
errln("FAIL: getOffset(5 args) failed.");
}
if (offset != -3600000) {
errln(UnicodeString("FAIL: Invalid time zone raw offset: ") + offset + " /expected: -3600000");
}
if (dstSavings != 0) {
errln(UnicodeString("FAIL: Invalid DST amount: ") + dstSavings + " /expected: 0");
}
// Try to add 3rd final rule
dtr = new DateTimeRule(UCAL_OCTOBER, 15, 1*HOUR, DateTimeRule::WALL_TIME);
atzr = new AnnualTimeZoneRule("3RD_ATZ", -1*HOUR, 2*HOUR, dtr, STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
rbtz1->addTransitionRule(atzr, status);
if (U_SUCCESS(status)) {
errln("FAIL: 3rd final rule must be rejected");
} else {
delete atzr;
}
// Try to add an initial rule
InitialTimeZoneRule *ir1 = new InitialTimeZoneRule("Test Initial", 2*HOUR, 0);
rbtz1->addTransitionRule(ir1, status);
if (U_SUCCESS(status)) {
errln("FAIL: InitialTimeZoneRule must be rejected");
} else {
delete ir1;
}
delete ir;
delete rbtz1;
delete rbtz2;
delete rbtz3;
delete rbtz1c;
delete cal;
}
/*
@ -341,13 +470,13 @@ TimeZoneRuleTest::TestHistoricalRuleBasedTimeZone(void) {
errln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010");
}
if (U_FAILURE(status)) {
errln("FAIL: error returned from hasEquivalentTransitions");
errln("FAIL: error returned from hasEquivalentTransitions for ny/rbtz 1967-2010");
}
if (ny->hasEquivalentTransitions(*rbtz, jan1_1950, jan1_2010, TRUE, status)) {
errln("FAIL: The RBTZ must not be equivalent to America/New_York between 1950 and 2010");
}
if (U_FAILURE(status)) {
errln("FAIL: error returned from hasEquivalentTransitions");
errln("FAIL: error returned from hasEquivalentTransitions for ny/rbtz 1950-2010");
}
// Same with above, but calling RBTZ#hasEquivalentTransitions against OlsonTimeZone
@ -355,17 +484,65 @@ TimeZoneRuleTest::TestHistoricalRuleBasedTimeZone(void) {
errln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010");
}
if (U_FAILURE(status)) {
errln("FAIL: error returned from hasEquivalentTransitions");
errln("FAIL: error returned from hasEquivalentTransitions for rbtz/ny 1967-2010");
}
if (rbtz->hasEquivalentTransitions(*ny, jan1_1950, jan1_2010, TRUE, status)) {
errln("FAIL: The RBTZ must not be equivalent to America/New_York between 1950 and 2010");
}
if (U_FAILURE(status)) {
errln("FAIL: error returned from hasEquivalentTransitions");
errln("FAIL: error returned from hasEquivalentTransitions for rbtz/ny 1950-2010");
}
// TimeZone APIs
if (ny->hasSameRules(*rbtz) || rbtz->hasSameRules(*ny)) {
errln("FAIL: hasSameRules must return false");
}
RuleBasedTimeZone *rbtzc = (RuleBasedTimeZone*)rbtz->clone();
if (!rbtz->hasSameRules(*rbtzc) || !rbtz->hasEquivalentTransitions(*rbtzc, jan1_1950, jan1_2010, TRUE, status)) {
errln("FAIL: hasSameRules/hasEquivalentTransitions must return true for cloned RBTZs");
}
if (U_FAILURE(status)) {
errln("FAIL: error returned from hasEquivalentTransitions for rbtz/rbtzc 1950-2010");
}
UDate times[] = {
getUTCMillis(2006, UCAL_MARCH, 15),
getUTCMillis(2006, UCAL_NOVEMBER, 1),
getUTCMillis(2007, UCAL_MARCH, 15),
getUTCMillis(2007, UCAL_NOVEMBER, 1),
getUTCMillis(2008, UCAL_MARCH, 15),
getUTCMillis(2008, UCAL_NOVEMBER, 1),
0
};
int32_t offset1, dst1;
int32_t offset2, dst2;
for (int i = 0; times[i] != 0; i++) {
// Check getOffset - must return the same results for these time data
rbtz->getOffset(times[i], FALSE, offset1, dst1, status);
if (U_FAILURE(status)) {
errln("FAIL: rbtz->getOffset failed");
}
ny->getOffset(times[i], FALSE, offset2, dst2, status);
if (U_FAILURE(status)) {
errln("FAIL: ny->getOffset failed");
}
if (offset1 != offset2 || dst1 != dst2) {
errln("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");
}
if (U_FAILURE(status)) {
errln("FAIL: inDaylightTime failed");
}
}
delete ny;
delete rbtz;
delete rbtzc;
}
/*
@ -513,9 +690,36 @@ TimeZoneRuleTest::TestHasEquivalentTransitions(void) {
errln("FAIL: error status is returned from hasEquivalentTransition");
}
// Cloned TimeZone
BasicTimeZone *newyork2 = (BasicTimeZone*)newyork->clone();
if (!newyork->hasEquivalentTransitions(*newyork2, jan1_1971, jan1_2011, FALSE, status)) {
errln("FAIL: Cloned TimeZone must have the same transitions");
}
if (U_FAILURE(status)) {
errln("FAIL: error status is returned from hasEquivalentTransition for newyork/newyork2");
}
if (!newyork->hasEquivalentTransitions(*newyork2, jan1_1971, jan1_2011, TRUE, status)) {
errln("FAIL: Cloned TimeZone must have the same transitions");
}
if (U_FAILURE(status)) {
errln("FAIL: error status is returned from hasEquivalentTransition for newyork/newyork2");
}
// America/New_York and America/Los_Angeles has same DST start rules, but
// 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");
}
if (U_FAILURE(status)) {
errln("FAIL: error status is returned from hasEquivalentTransition for newyork/losangeles");
}
delete newyork;
delete newyork2;
delete indianapolis;
delete gmt_5;
delete losangeles;
}
/*
@ -540,6 +744,8 @@ TimeZoneRuleTest::TestVTimeZoneRoundTrip(void) {
}
BasicTimeZone *tz = (BasicTimeZone*)TimeZone::createTimeZone(*tzid);
VTimeZone *vtz_org = VTimeZone::createVTimeZoneByID(*tzid);
vtz_org->setTZURL("http://source.icu-project.org/timezone");
vtz_org->setLastModified(Calendar::getNow());
VTimeZone *vtz_new = NULL;
UnicodeString vtzdata;
// Write out VTIMEZONE data
@ -553,6 +759,18 @@ TimeZoneRuleTest::TestVTimeZoneRoundTrip(void) {
if (U_FAILURE(status)) {
errln((UnicodeString)"FAIL: error returned while reading VTIMEZONE data for " + *tzid);
} else {
// Write out VTIMEZONE one more time
UnicodeString vtzdata1;
vtz_new->write(vtzdata1, status);
if (U_FAILURE(status)) {
errln((UnicodeString)"FAIL: error returned while writing time zone rules for " +
*tzid + "(vtz_new) into VTIMEZONE format.");
} else {
// Make sure VTIMEZONE data is exactly same with the first one
if (vtzdata != vtzdata1) {
errln((UnicodeString)"FAIL: different VTIMEZONE data after round trip for " + *tzid);
}
}
// Check equivalency after the first transition.
// The DST information before the first transition might be lost
// because there is no good way to represent the initial time with
@ -582,7 +800,10 @@ TimeZoneRuleTest::TestVTimeZoneRoundTrip(void) {
}
}
}
delete vtz_new;
if (vtz_new != NULL) {
delete vtz_new;
vtz_new = NULL;
}
}
delete tz;
delete vtz_org;
@ -595,7 +816,7 @@ TimeZoneRuleTest::TestVTimeZoneRoundTrip(void) {
*/
void
TimeZoneRuleTest::TestVTimeZoneRoundTripPartial(void) {
const int32_t CUTOVERYEARS[] = {
const int32_t STARTYEARS[] = {
1900,
1950,
2020,
@ -619,8 +840,9 @@ TimeZoneRuleTest::TestVTimeZoneRoundTripPartial(void) {
VTimeZone *vtz_new = NULL;
UnicodeString vtzdata;
for (int32_t i = 0; CUTOVERYEARS[i] != 0; i++) {
UDate startTime = getUTCMillis(CUTOVERYEARS[i], UCAL_JANUARY, 1);
for (int32_t i = 0; STARTYEARS[i] != 0; i++) {
// Write out VTIMEZONE
UDate startTime = getUTCMillis(STARTYEARS[i], UCAL_JANUARY, 1);
vtz_org->write(startTime, vtzdata, status);
if (U_FAILURE(status)) {
errln((UnicodeString)"FAIL: error returned while writing time zone rules for " +
@ -706,6 +928,7 @@ TimeZoneRuleTest::TestVTimeZoneSimpleWrite(void) {
UnicodeString vtzdata;
for (int32_t i = 0; TESTDATES[i][0] != 0; i++) {
// Write out VTIMEZONE
UDate time = getUTCMillis(TESTDATES[i][0], TESTDATES[i][1], TESTDATES[i][2]);
vtz_org->writeSimple(time, vtzdata, status);
if (U_FAILURE(status)) {
@ -718,6 +941,7 @@ TimeZoneRuleTest::TestVTimeZoneSimpleWrite(void) {
errln((UnicodeString)"FAIL: error returned while reading simple VTIMEZONE data for " + *tzid
+ " at " + dateToString(time));
} else {
// Check equivalency
int32_t raw0, dst0;
int32_t raw1, dst1;
vtz_org->getOffset(time, FALSE, raw0, dst0, status);
@ -772,7 +996,7 @@ TimeZoneRuleTest::TestVTimeZoneHeaderProps(void) {
} else {
// Check if TZURL and LAST-MODIFIED properties are preserved
newvtz1->getTZURL(tzurl);
if (tzurl.compare(TESTURL1) != 0) {
if (tzurl != TESTURL1) {
errln("FAIL: TZURL 1 was not preserved");
}
vtz->getLastModified(lmod);
@ -797,7 +1021,7 @@ TimeZoneRuleTest::TestVTimeZoneHeaderProps(void) {
} else {
// Check if TZURL and LAST-MODIFIED properties are preserved
newvtz2->getTZURL(tzurl);
if (tzurl.compare(TESTURL2) != 0) {
if (tzurl != TESTURL2) {
errln("FAIL: TZURL was not preserved in the second roundtrip");
}
vtz->getLastModified(lmod);
@ -812,6 +1036,10 @@ TimeZoneRuleTest::TestVTimeZoneHeaderProps(void) {
delete vtz;
}
/*
* Extract simple rules from an OlsonTimeZone and make sure the rule format matches
* the expected format.
*/
void
TimeZoneRuleTest::TestGetSimpleRules(void) {
UDate testTimes[] = {
@ -905,6 +1133,575 @@ TimeZoneRuleTest::TestGetSimpleRules(void) {
}
}
/*
* API coverage tests for TimeZoneRule
*/
void
TimeZoneRuleTest::TestTimeZoneRuleCoverage(void) {
UDate time1 = getUTCMillis(2005, UCAL_JULY, 4);
UDate time2 = getUTCMillis(2015, UCAL_JULY, 4);
UDate time3 = getUTCMillis(1950, UCAL_JULY, 4);
DateTimeRule *dtr1 = new DateTimeRule(UCAL_FEBRUARY, 29, UCAL_SUNDAY, FALSE,
3*HOUR, DateTimeRule::WALL_TIME); // Last Sunday on or before Feb 29, at 3 AM, wall time
DateTimeRule *dtr2 = new DateTimeRule(UCAL_MARCH, 11, 2*HOUR,
DateTimeRule::STANDARD_TIME); // Mar 11, at 2 AM, standard time
DateTimeRule *dtr3 = new DateTimeRule(UCAL_OCTOBER, -1, UCAL_SATURDAY,
6*HOUR, DateTimeRule::UTC_TIME); //Last Saturday in Oct, at 6 AM, UTC
DateTimeRule *dtr4 = new DateTimeRule(UCAL_MARCH, 8, UCAL_SUNDAY, TRUE,
2*HOUR, DateTimeRule::WALL_TIME); // First Sunday on or after Mar 8, at 2 AM, wall time
AnnualTimeZoneRule *a1 = new AnnualTimeZoneRule("a1", -3*HOUR, 1*HOUR, *dtr1,
2000, AnnualTimeZoneRule::MAX_YEAR);
AnnualTimeZoneRule *a2 = new AnnualTimeZoneRule("a2", -3*HOUR, 1*HOUR, *dtr1,
2000, AnnualTimeZoneRule::MAX_YEAR);
AnnualTimeZoneRule *a3 = new AnnualTimeZoneRule("a3", -3*HOUR, 1*HOUR, *dtr1,
2000, 2010);
InitialTimeZoneRule *i1 = new InitialTimeZoneRule("i1", -3*HOUR, 0);
InitialTimeZoneRule *i2 = new InitialTimeZoneRule("i2", -3*HOUR, 0);
InitialTimeZoneRule *i3 = new InitialTimeZoneRule("i3", -3*HOUR, 1*HOUR);
UDate trtimes1[] = {0.0};
UDate trtimes2[] = {0.0, 10000000.0};
TimeArrayTimeZoneRule *t1 = new TimeArrayTimeZoneRule("t1", -3*HOUR, 0, trtimes1, 1, DateTimeRule::UTC_TIME);
TimeArrayTimeZoneRule *t2 = new TimeArrayTimeZoneRule("t2", -3*HOUR, 0, trtimes1, 1, DateTimeRule::UTC_TIME);
TimeArrayTimeZoneRule *t3 = new TimeArrayTimeZoneRule("t3", -3*HOUR, 0, trtimes2, 2, DateTimeRule::UTC_TIME);
TimeArrayTimeZoneRule *t4 = new TimeArrayTimeZoneRule("t4", -3*HOUR, 0, trtimes1, 1, DateTimeRule::STANDARD_TIME);
TimeArrayTimeZoneRule *t5 = new TimeArrayTimeZoneRule("t5", -4*HOUR, 1*HOUR, trtimes1, 1, DateTimeRule::WALL_TIME);
// AnnualTimeZoneRule::getRule
if (*(a1->getRule()) != *(a2->getRule())) {
errln("FAIL: The same DateTimeRule must be returned from AnnualTimeZoneRule a1 and a2");
}
// AnnualTimeZoneRule::getStartYear
int32_t startYear = a1->getStartYear();
if (startYear != 2000) {
errln((UnicodeString)"FAIL: The start year of AnnualTimeZoneRule a1 must be 2000 - returned: " + startYear);
}
// AnnualTimeZoneRule::getEndYear
int32_t endYear = a1->getEndYear();
if (endYear != AnnualTimeZoneRule::MAX_YEAR) {
errln((UnicodeString)"FAIL: The start year of AnnualTimeZoneRule a1 must be MAX_YEAR - returned: " + endYear);
}
endYear = a3->getEndYear();
if (endYear != 2010) {
errln((UnicodeString)"FAIL: The start year of AnnualTimeZoneRule a3 must be 2010 - returned: " + endYear);
}
// AnnualTimeZone::getStartInYear
UBool b1, b2;
UDate d1, d2;
b1 = a1->getStartInYear(2005, -3*HOUR, 0, d1);
b2 = a3->getStartInYear(2005, -3*HOUR, 0, d2);
if (!b1 || !b2 || d1 != d2) {
errln("FAIL: AnnualTimeZoneRule::getStartInYear did not work as expected");
}
b2 = a3->getStartInYear(2015, -3*HOUR, 0, d2);
if (b2) {
errln("FAIL: AnnualTimeZoneRule::getStartInYear returned TRUE for 2015 which is out of rule range");
}
// AnnualTimeZone::getFirstStart
b1 = a1->getFirstStart(-3*HOUR, 0, d1);
b2 = a1->getFirstStart(-4*HOUR, 1*HOUR, d2);
if (!b1 || !b2 || d1 != d2) {
errln("FAIL: The same start time should be returned by getFirstStart");
}
// AnnualTimeZone::getFinalStart
b1 = a1->getFinalStart(-3*HOUR, 0, d1);
if (b1) {
errln("FAIL: getFinalStart returned TRUE for a1");
}
b1 = a1->getStartInYear(2010, -3*HOUR, 0, d1);
b2 = a3->getFinalStart(-3*HOUR, 0, d2);
if (!b1 || !b2 || d1 != d2) {
errln("FAIL: Bad date is returned by getFinalStart");
}
// AnnualTimeZone::getNextStart / getPreviousStart
b1 = a1->getNextStart(time1, -3*HOUR, 0, FALSE, d1);
if (!b1) {
errln("FAIL: getNextStart returned FALSE for ai");
} else {
b2 = a1->getPreviousStart(d1, -3*HOUR, 0, TRUE, d2);
if (!b2 || d1 != d2) {
errln("FAIL: Bad Date is returned by getPreviousStart");
}
}
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");
}
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");
}
// AnnualTimeZone::isEquavalentTo
if (!a1->isEquivalentTo(*a2)) {
errln("FAIL: AnnualTimeZoneRule a1 is equivalent to a2, but returned FALSE");
}
if (a1->isEquivalentTo(*a3)) {
errln("FAIL: AnnualTimeZoneRule a1 is not equivalent to a3, but returned TRUE");
}
if (!a1->isEquivalentTo(*a1)) {
errln("FAIL: AnnualTimeZoneRule a1 is equivalent to itself, but returned FALSE");
}
if (a1->isEquivalentTo(*t1)) {
errln("FAIL: AnnualTimeZoneRule is not equivalent to TimeArrayTimeZoneRule, but returned TRUE");
}
// InitialTimeZoneRule::isEquivalentRule
if (!i1->isEquivalentTo(*i2)) {
errln("FAIL: InitialTimeZoneRule i1 is equivalent to i2, but returned FALSE");
}
if (i1->isEquivalentTo(*i3)) {
errln("FAIL: InitialTimeZoneRule i1 is not equivalent to i3, but returned TRUE");
}
if (i1->isEquivalentTo(*a1)) {
errln("FAIL: An InitialTimeZoneRule is not equivalent to an AnnualTimeZoneRule, but returned TRUE");
}
// InitialTimeZoneRule::getFirstStart/getFinalStart/getNextStart/getPreviousStart
b1 = i1->getFirstStart(0, 0, d1);
if (b1) {
errln("FAIL: InitialTimeZone::getFirstStart returned TRUE");
}
b1 = i1->getFinalStart(0, 0, d1);
if (b1) {
errln("FAIL: InitialTimeZone::getFinalStart returned TRUE");
}
b1 = i1->getNextStart(time1, 0, 0, FALSE, d1);
if (b1) {
errln("FAIL: InitialTimeZone::getNextStart returned TRUE");
}
b1 = i1->getPreviousStart(time1, 0, 0, FALSE, d1);
if (b1) {
errln("FAIL: InitialTimeZone::getPreviousStart returned TRUE");
}
// TimeArrayTimeZoneRule::countStartTimes
if (t1->countStartTimes() != 1) {
errln("FAIL: Bad start time count is returned by TimeArrayTimeZoneRule::countStartTimes");
}
// TimeArrayTimeZoneRule::getStartTimeAt
b1 = t1->getStartTimeAt(-1, d1);
if (b1) {
errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned TRUE for index -1");
}
b1 = t1->getStartTimeAt(0, d1);
if (!b1 || d1 != trtimes1[0]) {
errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned incorrect result for index 0");
}
b1 = t1->getStartTimeAt(1, d1);
if (b1) {
errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned TRUE for index 1");
}
// TimeArrayTimeZoneRule::getTimeType
if (t1->getTimeType() != DateTimeRule::UTC_TIME) {
errln("FAIL: TimeArrayTimeZoneRule t1 uses UTC_TIME, but different type is returned");
}
if (t4->getTimeType() != DateTimeRule::STANDARD_TIME) {
errln("FAIL: TimeArrayTimeZoneRule t4 uses STANDARD_TIME, but different type is returned");
}
if (t5->getTimeType() != DateTimeRule::WALL_TIME) {
errln("FAIL: TimeArrayTimeZoneRule t5 uses WALL_TIME, but different type is returned");
}
// TimeArrayTimeZoneRule::getFirstStart/getFinalStart
b1 = t1->getFirstStart(0, 0, d1);
if (!b1 || d1 != trtimes1[0]) {
errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t1");
}
b1 = t1->getFinalStart(0, 0, d1);
if (!b1 || d1 != trtimes1[0]) {
errln("FAIL: Bad final start time returned from TimeArrayTimeZoneRule t1");
}
b1 = t4->getFirstStart(-4*HOUR, 1*HOUR, d1);
if (!b1 || d1 != (trtimes1[0] + 4*HOUR)) {
errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t4");
}
b1 = t5->getFirstStart(-4*HOUR, 1*HOUR, d1);
if (!b1 || d1 != (trtimes1[0] + 3*HOUR)) {
errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t5");
}
// 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");
}
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");
} else {
b2 = t3->getPreviousStart(d1, -3*HOUR, 1*HOUR, FALSE, d2);
if (!b2 || d2 != trtimes2[0]) {
errln("FAIL: Bad start time returned by getPreviousStart for t3");
}
}
b1 = t3->getPreviousStart(time3, -3*HOUR, 1*HOUR, FALSE, d1); //time3 - year 1950, no result expected
if (b1) {
errln("FAIL: getPreviousStart returned TRUE before the first transition for t3");
}
// TimeArrayTimeZoneRule::isEquivalentTo
if (!t1->isEquivalentTo(*t2)) {
errln("FAIL: TimeArrayTimeZoneRule t1 is equivalent to t2, but returned FALSE");
}
if (t1->isEquivalentTo(*t3)) {
errln("FAIL: TimeArrayTimeZoneRule t1 is not equivalent to t3, but returned TRUE");
}
if (t1->isEquivalentTo(*t4)) {
errln("FAIL: TimeArrayTimeZoneRule t1 is not equivalent to t4, but returned TRUE");
}
if (t1->isEquivalentTo(*a1)) {
errln("FAIL: TimeArrayTimeZoneRule is not equivalent to AnnualTimeZoneRule, but returned TRUE");
}
delete dtr1;
delete dtr2;
delete dtr3;
delete dtr4;
delete a1;
delete a2;
delete a3;
delete i1;
delete i2;
delete i3;
delete t1;
delete t2;
delete t3;
delete t4;
}
/*
* API coverage test for BasicTimeZone APIs in SimpleTimeZone
*/
void
TimeZoneRuleTest::TestSimpleTimeZoneCoverage(void) {
UDate time1 = getUTCMillis(1990, UCAL_JUNE, 1);
UDate time2 = getUTCMillis(2000, UCAL_JUNE, 1);
TimeZoneTransition tzt1, tzt2;
UBool avail1, avail2;
UErrorCode status = U_ZERO_ERROR;
const TimeZoneRule *trrules[2];
const InitialTimeZoneRule *ir = NULL;
int32_t numTzRules;
// BasicTimeZone API implementation in SimpleTimeZone
SimpleTimeZone *stz1 = new SimpleTimeZone(-5*HOUR, "GMT-5");
avail1 = stz1->getNextTransition(time1, FALSE, tzt1);
if (avail1) {
errln("FAIL: No transition must be returned by getNextTranstion for SimpleTimeZone with no DST rule");
}
avail1 = stz1->getPreviousTransition(time1, FALSE, tzt1);
if (avail1) {
errln("FAIL: No transition must be returned by getPreviousTransition for SimpleTimeZone with no DST rule");
}
numTzRules = stz1->countTransitionRules(status);
if (U_FAILURE(status)) {
errln("FAIL: countTransitionRules failed");
}
if (numTzRules != 0) {
errln((UnicodeString)"FAIL: countTransitionRules returned " + numTzRules);
}
numTzRules = 2;
stz1->getTimeZoneRules(ir, trrules, numTzRules, status);
if (U_FAILURE(status)) {
errln("FAIL: getTimeZoneRules failed");
}
if (numTzRules != 0) {
errln("FAIL: Incorrect transition rule count");
}
if (ir == NULL || ir->getRawOffset() != stz1->getRawOffset()) {
errln("FAIL: Bad initial time zone rule");
}
// Set DST rule
stz1->setStartRule(UCAL_MARCH, 11, 2*HOUR, status); // March 11
stz1->setEndRule(UCAL_NOVEMBER, 1, UCAL_SUNDAY, 2*HOUR, status); // First Sunday in November
if (U_FAILURE(status)) {
errln("FAIL: Failed to set DST rules in a SimpleTimeZone");
}
avail1 = stz1->getNextTransition(time1, FALSE, tzt1);
if (!avail1) {
errln("FAIL: Non-null transition must be returned by getNextTranstion for SimpleTimeZone with a DST rule");
}
avail1 = stz1->getPreviousTransition(time1, FALSE, tzt1);
if (!avail1) {
errln("FAIL: Non-null transition must be returned by getPreviousTransition for SimpleTimeZone with a DST rule");
}
numTzRules = stz1->countTransitionRules(status);
if (U_FAILURE(status)) {
errln("FAIL: countTransitionRules failed");
}
if (numTzRules != 2) {
errln((UnicodeString)"FAIL: countTransitionRules returned " + numTzRules);
}
numTzRules = 2;
trrules[0] = NULL;
trrules[1] = NULL;
stz1->getTimeZoneRules(ir, trrules, numTzRules, status);
if (U_FAILURE(status)) {
errln("FAIL: getTimeZoneRules failed");
}
if (numTzRules != 2) {
errln("FAIL: Incorrect transition rule count");
}
if (ir == NULL || ir->getRawOffset() != stz1->getRawOffset()) {
errln("FAIL: Bad initial time zone rule");
}
if (trrules[0] == NULL || trrules[0]->getRawOffset() != stz1->getRawOffset()) {
errln("FAIL: Bad transition rule 0");
}
if (trrules[1] == NULL || trrules[1]->getRawOffset() != stz1->getRawOffset()) {
errln("FAIL: Bad transition rule 1");
}
// Set DST start year
stz1->setStartYear(2007);
avail1 = stz1->getPreviousTransition(time1, FALSE, tzt1);
if (avail1) {
errln("FAIL: No transition must be returned before 1990");
}
avail1 = stz1->getNextTransition(time1, FALSE, tzt1); // transition after 1990-06-01
avail2 = stz1->getNextTransition(time2, FALSE, tzt2); // transition after 2000-06-01
if (!avail1 || !avail2 || tzt1 != tzt2) {
errln("FAIL: Bad transition returned by SimpleTimeZone::getNextTransition");
}
}
/*
* API coverage test for VTimeZone
*/
void
TimeZoneRuleTest::TestVTimeZoneCoverage(void) {
UErrorCode status = U_ZERO_ERROR;
UnicodeString TZID("Europe/Moscow");
BasicTimeZone *otz = (BasicTimeZone*)TimeZone::createTimeZone(TZID);
VTimeZone *vtz = VTimeZone::createVTimeZoneByID(TZID);
// getOffset(era, year, month, day, dayOfWeek, milliseconds, ec)
int32_t offset1 = otz->getOffset(GregorianCalendar::AD, 2007, UCAL_JULY, 1, UCAL_SUNDAY, 0, status);
if (U_FAILURE(status)) {
errln("FAIL: getOffset(7 args) failed for otz");
}
int32_t offset2 = vtz->getOffset(GregorianCalendar::AD, 2007, UCAL_JULY, 1, UCAL_SUNDAY, 0, status);
if (U_FAILURE(status)) {
errln("FAIL: getOffset(7 args) failed for vtz");
}
if (offset1 != offset2) {
errln("FAIL: getOffset(7 args) returned different results in VTimeZone and OlsonTimeZone");
}
// getOffset(date, local, rawOffset, dstOffset, ec)
UDate t = Calendar::getNow();
int32_t rawOffset1, dstSavings1;
int32_t rawOffset2, dstSavings2;
otz->getOffset(t, FALSE, rawOffset1, dstSavings1, status);
if (U_FAILURE(status)) {
errln("FAIL: getOffset(5 args) failed for otz");
}
vtz->getOffset(t, FALSE, rawOffset2, dstSavings2, status);
if (U_FAILURE(status)) {
errln("FAIL: getOffset(5 args) failed for vtz");
}
if (rawOffset1 != rawOffset2 || dstSavings1 != dstSavings2) {
errln("FAIL: getOffset(long,boolean,int[]) returned different results in VTimeZone and OlsonTimeZone");
}
// getRawOffset
if (otz->getRawOffset() != vtz->getRawOffset()) {
errln("FAIL: getRawOffset returned different results in VTimeZone and OlsonTimeZone");
}
// inDaylightTime
UBool inDst1, inDst2;
inDst1 = otz->inDaylightTime(t, status);
if (U_FAILURE(status)) {
errln("FAIL: inDaylightTime failed for otz");
}
inDst2 = vtz->inDaylightTime(t, status);
if (U_FAILURE(status)) {
errln("FAIL: inDaylightTime failed for vtz");
}
if (inDst1 != inDst2) {
errln("FAIL: inDaylightTime returned different results in VTimeZone and OlsonTimeZone");
}
// useDaylightTime
if (otz->useDaylightTime() != vtz->useDaylightTime()) {
errln("FAIL: useDaylightTime returned different results in VTimeZone and OlsonTimeZone");
}
// setRawOffset
const int32_t RAW = -10*HOUR;
VTimeZone *tmpvtz = (VTimeZone*)vtz->clone();
tmpvtz->setRawOffset(RAW);
if (tmpvtz->getRawOffset() != RAW) {
logln("setRawOffset is implemented in VTimeZone");
}
// hasSameRules
UBool bSame = otz->hasSameRules(*vtz);
logln((UnicodeString)"OlsonTimeZone::hasSameRules(VTimeZone) should return FALSE always for now - actual: " + bSame);
// getTZURL/setTZURL
UnicodeString TZURL("http://icu-project.org/timezone");
UnicodeString url;
if (vtz->getTZURL(url)) {
errln("FAIL: getTZURL returned TRUE");
}
vtz->setTZURL(TZURL);
if (!vtz->getTZURL(url) || url != TZURL) {
errln("FAIL: URL returned by getTZURL does not match the one set by setTZURL");
}
// getLastModified/setLastModified
UDate lastmod;
if (vtz->getLastModified(lastmod)) {
errln("FAIL: getLastModified returned TRUE");
}
vtz->setLastModified(t);
if (!vtz->getLastModified(lastmod) || lastmod != t) {
errln("FAIL: Date returned by getLastModified does not match the one set by setLastModified");
}
// getNextTransition/getPreviousTransition
UDate base = getUTCMillis(2007, UCAL_JULY, 1);
TimeZoneTransition tzt1, tzt2;
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");
}
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");
}
// hasEquivalentTransitions
UDate time1 = getUTCMillis(1950, UCAL_JANUARY, 1);
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");
}
if (!equiv) {
errln("FAIL: hasEquivalentTransitons returned false for the same time zone");
}
delete otz;
delete vtz;
delete tmpvtz;
}
void
TimeZoneRuleTest::TestVTimeZoneParse(void) {
UErrorCode status = U_ZERO_ERROR;
// Trying to create VTimeZone from empty data
UnicodeString emptyData;
VTimeZone *empty = VTimeZone::createVTimeZone(emptyData, status);
if (U_SUCCESS(status) || empty != NULL) {
delete empty;
errln("FAIL: Non-null VTimeZone is returned for empty VTIMEZONE data");
}
status = U_ZERO_ERROR;
// Create VTimeZone for Asia/Tokyo
UnicodeString asiaTokyoID("Asia/Tokyo");
UnicodeString asiaTokyo(
"BEGIN:VTIMEZONE\x0D\x0A"
"TZID:Asia\x0D\x0A"
"\x09/Tokyo\x0D\x0A"
"BEGIN:STANDARD\x0D\x0A"
"TZOFFSETFROM:+0900\x0D\x0A"
"TZOFFSETTO:+0900\x0D\x0A"
"TZNAME:JST\x0D\x0A"
"DTSTART:19700101\x0D\x0A"
" T000000\x0D\x0A"
"END:STANDARD\x0D\x0A"
"END:VTIMEZONE");
VTimeZone *tokyo = VTimeZone::createVTimeZone(asiaTokyo, status);
if (U_FAILURE(status) || tokyo == NULL) {
errln("FAIL: Failed to create a VTimeZone tokyo");
} else {
// Check ID
UnicodeString tzid;
tokyo->getID(tzid);
if (tzid != asiaTokyoID) {
errln((UnicodeString)"FAIL: Invalid TZID: " + tzid);
}
// Make sure offsets are correct
int32_t rawOffset, dstSavings;
tokyo->getOffset(Calendar::getNow(), FALSE, rawOffset, dstSavings, status);
if (U_FAILURE(status)) {
errln("FAIL: getOffset failed for tokyo");
}
if (rawOffset != 9*HOUR || dstSavings != 0) {
errln("FAIL: Bad offsets returned by a VTimeZone created for Tokyo");
}
}
delete tokyo;
// Create VTimeZone from VTIMEZONE data
UnicodeString fooData(
"BEGIN:VCALENDAR\x0D\x0A"
"BEGIN:VTIMEZONE\x0D\x0A"
"TZID:FOO\x0D\x0A"
"BEGIN:STANDARD\x0D\x0A"
"TZOFFSETFROM:-0700\x0D\x0A"
"TZOFFSETTO:-0800\x0D\x0A"
"TZNAME:FST\x0D\x0A"
"DTSTART:20071010T010000\x0D\x0A"
"RRULE:FREQ=YEARLY;BYDAY=WE;BYMONTHDAY=10,11,12,13,14,15,16;BYMONTH=10\x0D\x0A"
"END:STANDARD\x0D\x0A"
"BEGIN:DAYLIGHT\x0D\x0A"
"TZOFFSETFROM:-0800\x0D\x0A"
"TZOFFSETTO:-0700\x0D\x0A"
"TZNAME:FDT\x0D\x0A"
"DTSTART:20070415T010000\x0D\x0A"
"RRULE:FREQ=YEARLY;BYMONTHDAY=15;BYMONTH=4\x0D\x0A"
"END:DAYLIGHT\x0D\x0A"
"END:VTIMEZONE\x0D\x0A"
"END:VCALENDAR");
VTimeZone *foo = VTimeZone::createVTimeZone(fooData, status);
if (U_FAILURE(status) || foo == NULL) {
errln("FAIL: Failed to create a VTimeZone foo");
} else {
// Write VTIMEZONE data
UnicodeString fooData2;
foo->write(getUTCMillis(2005, UCAL_JANUARY, 1), fooData2, status);
if (U_FAILURE(status)) {
errln("FAIL: Failed to write VTIMEZONE data for foo");
}
logln(fooData2);
}
delete foo;
}
//----------- private test helpers -------------------------------------------------
UDate
TimeZoneRuleTest::getUTCMillis(int32_t y, int32_t m, int32_t d,

View file

@ -30,6 +30,10 @@ public:
void TestVTimeZoneSimpleWrite(void);
void TestVTimeZoneHeaderProps(void);
void TestGetSimpleRules(void);
void TestTimeZoneRuleCoverage(void);
void TestSimpleTimeZoneCoverage(void);
void TestVTimeZoneCoverage(void);
void TestVTimeZoneParse(void);
private:
void verifyTransitions(BasicTimeZone& icutz, UDate start, UDate end);