diff --git a/icu4c/source/i18n/unicode/tzrule.h b/icu4c/source/i18n/unicode/tzrule.h
index a0576ca87a3..5785b161c4c 100644
--- a/icu4c/source/i18n/unicode/tzrule.h
+++ b/icu4c/source/i18n/unicode/tzrule.h
@@ -1,6 +1,6 @@
/*
*******************************************************************************
-* Copyright (C) 2007, International Business Machines Corporation and *
+* Copyright (C) 2007-2008, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -629,7 +629,7 @@ public:
* @param numStartTimes The number of elements in the parameter "startTimes"
* @param timeRuleType The time type of the start times, which is one of
* DataTimeRule::WALL_TIME
, STANDARD_TIME
- * and UNIVERSAL_TIME
.
+ * and UTC_TIME
.
* @draft ICU 3.8
*/
TimeArrayTimeZoneRule(const UnicodeString& name, int32_t rawOffset, int32_t dstSavings,
@@ -684,7 +684,7 @@ public:
/**
* Gets the time type of the start times used by this rule. The return value
* is either DateTimeRule::WALL_TIME
or STANDARD_TIME
- * or UNIVERSAL_TIME
.
+ * or UTC_TIME
.
*
* @return The time type used of the start times used by this rule.
* @draft ICU 3.8
diff --git a/icu4c/source/i18n/vtzone.cpp b/icu4c/source/i18n/vtzone.cpp
index 933376e4df7..5d65a3131b7 100644
--- a/icu4c/source/i18n/vtzone.cpp
+++ b/icu4c/source/i18n/vtzone.cpp
@@ -1328,6 +1328,9 @@ VTimeZone::parse(UErrorCode& status) {
UVector *dates = NULL; // list of RDATE or RRULE strings
UVector *rules = NULL; // list of TimeZoneRule instances
+ int32_t finalRuleIdx = -1;
+ int32_t finalRuleCount = 0;
+
rules = new UVector(status);
if (U_FAILURE(status)) {
goto cleanupParse;
@@ -1545,6 +1548,91 @@ VTimeZone::parse(UErrorCode& status) {
status = U_MEMORY_ALLOCATION_ERROR;
goto cleanupParse;
}
+ initialRule = NULL; // already adopted by RBTZ, no need to delete
+
+ for (n = 0; n < rules->size(); n++) {
+ TimeZoneRule *r = (TimeZoneRule*)rules->elementAt(n);
+ if (r->getDynamicClassID() == AnnualTimeZoneRule::getStaticClassID()) {
+ if (((AnnualTimeZoneRule*)r)->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) {
+ finalRuleCount++;
+ finalRuleIdx = n;
+ }
+ }
+ }
+ if (finalRuleCount > 2) {
+ // Too many final rules
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ goto cleanupParse;
+ }
+
+ if (finalRuleCount == 1) {
+ if (rules->size() == 1) {
+ // Only one final rule, only governs the initial rule,
+ // which is already initialized, thus, we do not need to
+ // add this transition rule
+ rules->removeAllElements();
+ } else {
+ // Normalize the final rule
+ AnnualTimeZoneRule *finalRule = (AnnualTimeZoneRule*)rules->elementAt(finalRuleIdx);
+ int32_t tmpRaw = finalRule->getRawOffset();
+ int32_t tmpDST = finalRule->getDSTSavings();
+
+ // Find the last non-final rule
+ UDate finalStart, start;
+ finalRule->getFirstStart(initialRawOffset, initialDSTSavings, finalStart);
+ start = finalStart;
+ for (n = 0; n < rules->size(); n++) {
+ if (finalRuleIdx == n) {
+ continue;
+ }
+ TimeZoneRule *r = (TimeZoneRule*)rules->elementAt(n);
+ UDate lastStart;
+ r->getFinalStart(tmpRaw, tmpDST, lastStart);
+ if (lastStart > start) {
+ finalRule->getNextStart(lastStart,
+ r->getRawOffset(),
+ r->getDSTSavings(),
+ FALSE,
+ start);
+ }
+ }
+
+ TimeZoneRule *newRule;
+ UnicodeString tznam;
+ if (start == finalStart) {
+ // Transform this into a single transition
+ newRule = new TimeArrayTimeZoneRule(
+ finalRule->getName(tznam),
+ finalRule->getRawOffset(),
+ finalRule->getDSTSavings(),
+ &finalStart,
+ 1,
+ DateTimeRule::UTC_TIME);
+ } else {
+ // Update the end year
+ int32_t y, m, d, dow, doy, mid;
+ Grego::timeToFields(start, y, m, d, dow, doy, mid);
+ newRule = new AnnualTimeZoneRule(
+ finalRule->getName(tznam),
+ finalRule->getRawOffset(),
+ finalRule->getDSTSavings(),
+ *(finalRule->getRule()),
+ finalRule->getStartYear(),
+ y);
+ }
+ if (newRule == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ goto cleanupParse;
+ }
+ rules->removeElementAt(finalRuleIdx);
+ rules->addElement(newRule, status);
+ if (U_FAILURE(status)) {
+ delete newRule;
+ goto cleanupParse;
+ }
+ }
+ }
+
while (!rules->isEmpty()) {
TimeZoneRule *tzr = (TimeZoneRule*)rules->orphanElementAt(0);
rbtz->addTransitionRule(tzr, status);
diff --git a/icu4c/source/test/intltest/tzrulets.cpp b/icu4c/source/test/intltest/tzrulets.cpp
index 702b502ea2c..1e3d52e044e 100644
--- a/icu4c/source/test/intltest/tzrulets.cpp
+++ b/icu4c/source/test/intltest/tzrulets.cpp
@@ -1,6 +1,6 @@
/*
*******************************************************************************
-* Copyright (C) 2007, International Business Machines Corporation and *
+* Copyright (C) 2007-2008, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -125,6 +125,7 @@ void TimeZoneRuleTest::runIndexedTest( int32_t index, UBool exec, const char* &n
CASE(11, TestSimpleTimeZoneCoverage);
CASE(12, TestVTimeZoneCoverage);
CASE(13, TestVTimeZoneParse);
+ CASE(14, TestT6216);
default: name = ""; break;
}
}
@@ -1862,6 +1863,211 @@ TimeZoneRuleTest::TestVTimeZoneParse(void) {
delete foo;
}
+void
+TimeZoneRuleTest::TestT6216(void) {
+ // Test case in #6216
+ static const UChar tokyoTZ[] = {
+ /* "BEGIN:VCALENDAR\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
+ /* "VERSION:2.0\r\n" */
+ 0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x3a,0x32,0x2e,0x30,0x0d,0x0a,
+ /* "PRODID:-//PYVOBJECT//NONSGML Version 1//EN\r\n" */
+ 0x50,0x52,0x4f,0x44,0x49,0x44,0x3a,0x2d,0x2f,0x2f,0x50,0x59,0x56,0x4f,0x42,0x4a,0x45,0x43,0x54,0x2f,0x2f,0x4e,0x4f,0x4e,0x53,0x47,0x4d,0x4c,0x20,0x56,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x31,0x2f,0x2f,0x45,0x4e,0x0d,0x0a,
+ /* "BEGIN:VTIMEZONE\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
+ /* "TZID:Asia/Tokyo\r\n" */
+ 0x54,0x5a,0x49,0x44,0x3a,0x41,0x73,0x69,0x61,0x2f,0x54,0x6f,0x6b,0x79,0x6f,0x0d,0x0a,
+ /* "BEGIN:STANDARD\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
+ /* "DTSTART:20000101T000000\r\n" */
+ 0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x30,0x30,0x31,0x30,0x31,0x54,0x30,0x30,0x30,0x30,0x30,0x30,0x0d,0x0a,
+ /* "RRULE:FREQ=YEARLY;BYMONTH=1\r\n" */
+ 0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x0d,0x0a,
+ /* "TZNAME:Asia/Tokyo\r\n" */
+ 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x41,0x73,0x69,0x61,0x2f,0x54,0x6f,0x6b,0x79,0x6f,0x0d,0x0a,
+ /* "TZOFFSETFROM:+0900\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2b,0x30,0x39,0x30,0x30,0x0d,0x0a,
+ /* "TZOFFSETTO:+0900\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2b,0x30,0x39,0x30,0x30,0x0d,0x0a,
+ /* "END:STANDARD\r\n" */
+ 0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
+ /* "END:VTIMEZONE\r\n" */
+ 0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
+ /* "END:VCALENDAR" */
+ 0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
+ 0
+ };
+ // Single final rule, overlapping with another
+ static const UChar finalOverlap[] = {
+ /* "BEGIN:VCALENDAR\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
+ /* "BEGIN:VTIMEZONE\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
+ /* "TZID:FinalOverlap\r\n" */
+ 0x54,0x5a,0x49,0x44,0x3a,0x46,0x69,0x6e,0x61,0x6c,0x4f,0x76,0x65,0x72,0x6c,0x61,0x70,0x0d,0x0a,
+ /* "BEGIN:STANDARD\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
+ /* "TZOFFSETFROM:-0200\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
+ /* "TZOFFSETTO:-0300\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
+ /* "TZNAME:STD\r\n" */
+ 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x0d,0x0a,
+ /* "DTSTART:20001029T020000\r\n" */
+ 0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x30,0x31,0x30,0x32,0x39,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
+ /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\r\n" */
+ 0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x2d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x30,0x0d,0x0a,
+ /* "END:STANDARD\r\n" */
+ 0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
+ /* "BEGIN:DAYLIGHT\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
+ /* "TZOFFSETFROM:-0300\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
+ /* "TZOFFSETTO:-0200\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
+ /* "TZNAME:DST\r\n" */
+ 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x44,0x53,0x54,0x0d,0x0a,
+ /* "DTSTART:19990404T020000\r\n" */
+ 0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x31,0x39,0x39,0x39,0x30,0x34,0x30,0x34,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
+ /* "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=20050403T040000Z\r\n" */
+ 0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x34,0x3b,0x55,0x4e,0x54,0x49,0x4c,0x3d,0x32,0x30,0x30,0x35,0x30,0x34,0x30,0x33,0x54,0x30,0x34,0x30,0x30,0x30,0x30,0x5a,0x0d,0x0a,
+ /* "END:DAYLIGHT\r\n" */
+ 0x45,0x4e,0x44,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
+ /* "END:VTIMEZONE\r\n" */
+ 0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
+ /* "END:VCALENDAR" */
+ 0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
+ 0
+ };
+ // Single final rule, no overlapping with another
+ static const UChar finalNonOverlap[] = {
+ /* "BEGIN:VCALENDAR\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
+ /* "BEGIN:VTIMEZONE\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
+ /* "TZID:FinalNonOverlap\r\n" */
+ 0x54,0x5a,0x49,0x44,0x3a,0x46,0x69,0x6e,0x61,0x6c,0x4e,0x6f,0x6e,0x4f,0x76,0x65,0x72,0x6c,0x61,0x70,0x0d,0x0a,
+ /* "BEGIN:STANDARD\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
+ /* "TZOFFSETFROM:-0200\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
+ /* "TZOFFSETTO:-0300\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
+ /* "TZNAME:STD\r\n" */
+ 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x0d,0x0a,
+ /* "DTSTART:20001029T020000\r\n" */
+ 0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x30,0x31,0x30,0x32,0x39,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
+ /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10;UNTIL=20041031T040000Z\r\n" */
+ 0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x2d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x30,0x3b,0x55,0x4e,0x54,0x49,0x4c,0x3d,0x32,0x30,0x30,0x34,0x31,0x30,0x33,0x31,0x54,0x30,0x34,0x30,0x30,0x30,0x30,0x5a,0x0d,0x0a,
+ /* "END:STANDARD\r\n" */
+ 0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
+ /* "BEGIN:DAYLIGHT\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
+ /* "TZOFFSETFROM:-0300\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
+ /* "TZOFFSETTO:-0200\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
+ /* "TZNAME:DST\r\n" */
+ 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x44,0x53,0x54,0x0d,0x0a,
+ /* "DTSTART:19990404T020000\r\n" */
+ 0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x31,0x39,0x39,0x39,0x30,0x34,0x30,0x34,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
+ /* "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=20050403T040000Z\r\n" */
+ 0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x34,0x3b,0x55,0x4e,0x54,0x49,0x4c,0x3d,0x32,0x30,0x30,0x35,0x30,0x34,0x30,0x33,0x54,0x30,0x34,0x30,0x30,0x30,0x30,0x5a,0x0d,0x0a,
+ /* "END:DAYLIGHT\r\n" */
+ 0x45,0x4e,0x44,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
+ /* "BEGIN:STANDARD\r\n" */
+ 0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
+ /* "TZOFFSETFROM:-0200\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
+ /* "TZOFFSETTO:-0300\r\n" */
+ 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
+ /* "TZNAME:STDFINAL\r\n" */
+ 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x46,0x49,0x4e,0x41,0x4c,0x0d,0x0a,
+ /* "DTSTART:20071028T020000\r\n" */
+ 0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x37,0x31,0x30,0x32,0x38,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
+ /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\r\n" */
+ 0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x2d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x30,0x0d,0x0a,
+ /* "END:STANDARD\r\n" */
+ 0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
+ /* "END:VTIMEZONE\r\n" */
+ 0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
+ /* "END:VCALENDAR" */
+ 0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
+ 0
+ };
+
+ static const int32_t TestDates[][3] = {
+ {1995, UCAL_JANUARY, 1},
+ {1995, UCAL_JULY, 1},
+ {2000, UCAL_JANUARY, 1},
+ {2000, UCAL_JULY, 1},
+ {2005, UCAL_JANUARY, 1},
+ {2005, UCAL_JULY, 1},
+ {2010, UCAL_JANUARY, 1},
+ {2010, UCAL_JULY, 1},
+ {0, 0, 0}
+ };
+
+ static const UnicodeString TestZones[] = {
+ UnicodeString(tokyoTZ),
+ UnicodeString(finalOverlap),
+ UnicodeString(finalNonOverlap),
+ UnicodeString()
+ };
+
+ int32_t Expected[][8] = {
+ // JAN90 JUL90 JAN00 JUL00 JAN05 JUL05 JAN10 JUL10
+ { 32400000, 32400000, 32400000, 32400000, 32400000, 32400000, 32400000, 32400000},
+ {-10800000, -10800000, -7200000, -7200000, -10800000, -7200000, -10800000, -10800000},
+ {-10800000, -10800000, -7200000, -7200000, -10800000, -7200000, -10800000, -10800000}
+ };
+
+ int32_t i, j;
+
+ // Get test times
+ UDate times[sizeof(TestDates) / (3 * sizeof(int32_t))];
+ int32_t numTimes;
+
+ UErrorCode status = U_ZERO_ERROR;
+ TimeZone *utc = TimeZone::createTimeZone("Etc/GMT");
+ GregorianCalendar cal(utc, status);
+ if (U_FAILURE(status)) {
+ errln("FAIL: Failed to creat a GregorianCalendar");
+ return;
+ }
+ for (i = 0; TestDates[i][2] != 0; i++) {
+ cal.clear();
+ cal.set(TestDates[i][0], TestDates[i][1], TestDates[i][2]);
+ times[i] = cal.getTime(status);
+ if (U_FAILURE(status)) {
+ errln("FAIL: getTime failed");
+ return;
+ }
+ }
+ numTimes = i;
+
+ // Test offset
+ for (i = 0; !TestZones[i].isEmpty(); i++) {
+ VTimeZone *vtz = VTimeZone::createVTimeZone(TestZones[i], status);
+ if (U_FAILURE(status)) {
+ errln("FAIL: failed to create VTimeZone");
+ continue;
+ }
+ for (j = 0; j < numTimes; j++) {
+ int32_t raw, dst;
+ status = U_ZERO_ERROR;
+ vtz->getOffset(times[j], FALSE, raw, dst, status);
+ if (U_FAILURE(status)) {
+ errln((UnicodeString)"FAIL: getOffset failed for time zone " + i + " at " + times[j]);
+ }
+ int32_t offset = raw + dst;
+ if (offset != Expected[i][j]) {
+ errln((UnicodeString)"FAIL: Invalid offset at time(" + times[j] + "):" + offset + " Expected:" + Expected[i][j]);
+ }
+ }
+ }
+}
+
//----------- private test helpers -------------------------------------------------
UDate
diff --git a/icu4c/source/test/intltest/tzrulets.h b/icu4c/source/test/intltest/tzrulets.h
index 643d2719d83..9c6cf96dd2f 100644
--- a/icu4c/source/test/intltest/tzrulets.h
+++ b/icu4c/source/test/intltest/tzrulets.h
@@ -1,6 +1,6 @@
/*
*******************************************************************************
-* Copyright (C) 2007, International Business Machines Corporation and *
+* Copyright (C) 2007-2008, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -34,6 +34,7 @@ public:
void TestSimpleTimeZoneCoverage(void);
void TestVTimeZoneCoverage(void);
void TestVTimeZoneParse(void);
+ void TestT6216(void);
private:
void verifyTransitions(BasicTimeZone& icutz, UDate start, UDate end);