mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
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:
parent
35a19cf658
commit
0de5cefde3
8 changed files with 892 additions and 62 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue