From a55d75d400d1ec71c9443fafc6721f893ee440b4 Mon Sep 17 00:00:00 2001 From: Yoshito Umaoka Date: Thu, 10 Apr 2008 03:41:22 +0000 Subject: [PATCH] ICU-6216 Fixed a VTIMEZONE parsing problem in ICU4C. X-SVN-Rev: 23780 --- icu4c/source/i18n/unicode/tzrule.h | 6 +- icu4c/source/i18n/vtzone.cpp | 88 ++++++++++ icu4c/source/test/intltest/tzrulets.cpp | 208 +++++++++++++++++++++++- icu4c/source/test/intltest/tzrulets.h | 3 +- 4 files changed, 300 insertions(+), 5 deletions(-) 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);