diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp
index ecb7d0ce895..f694789ff64 100644
--- a/icu4c/source/i18n/dtfmtsym.cpp
+++ b/icu4c/source/i18n/dtfmtsym.cpp
@@ -1765,6 +1765,8 @@ DateFormatSymbols::getZoneID(const UnicodeString& zid, UnicodeString& result, UE
}
}
}
+ }else{
+ result.setTo(zid);
}
return result;
}
diff --git a/icu4c/source/i18n/olsontz.cpp b/icu4c/source/i18n/olsontz.cpp
index d31fa4d30be..792a996b185 100644
--- a/icu4c/source/i18n/olsontz.cpp
+++ b/icu4c/source/i18n/olsontz.cpp
@@ -473,7 +473,18 @@ UBool OlsonTimeZone::useDaylightTime() const {
}
return FALSE;
}
-
+inline int32_t OlsonTimeZone::getDSTSavings() const{
+ if(finalZone!=NULL){
+ return finalZone->getDSTSavings();
+ }
+ // return super->getDSTSavings();
+ // this is basically identical to implementation in
+ // superclass timezone
+ if (useDaylightTime()) {
+ return 3600000;
+ }
+ return 0;
+}
/**
* TimeZone API.
*/
diff --git a/icu4c/source/i18n/olsontz.h b/icu4c/source/i18n/olsontz.h
index ef19ee2a225..4728b82adea 100644
--- a/icu4c/source/i18n/olsontz.h
+++ b/icu4c/source/i18n/olsontz.h
@@ -1,6 +1,6 @@
/*
**********************************************************************
-* Copyright (c) 2003-2004, International Business Machines
+* Copyright (c) 2003-2005, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Alan Liu
@@ -209,6 +209,8 @@ class U_I18N_API OlsonTimeZone: public TimeZone {
*/
virtual UBool inDaylightTime(UDate date, UErrorCode& ec) const;
+ virtual inline int32_t getDSTSavings() const;
+
protected:
/**
* Default constructor. Creates a time zone with an empty ID and
diff --git a/icu4c/source/i18n/simpletz.cpp b/icu4c/source/i18n/simpletz.cpp
index 393d339d285..111ca43f54c 100644
--- a/icu4c/source/i18n/simpletz.cpp
+++ b/icu4c/source/i18n/simpletz.cpp
@@ -1,6 +1,6 @@
/*
*******************************************************************************
-* Copyright (C) 1997-2003, International Business Machines Corporation and *
+* Copyright (C) 1997-2005, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@@ -27,6 +27,7 @@
#include "unicode/simpletz.h"
#include "unicode/gregocal.h"
+#include "unicode/smpdtfmt.h"
U_NAMESPACE_BEGIN
@@ -822,7 +823,7 @@ SimpleTimeZone::decodeStartRule(UErrorCode& status)
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
- } else if (startDay > STATICMONTHLENGTH[startMonth]) {
+ } else if (startDay<1 || startDay > STATICMONTHLENGTH[startMonth]) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
@@ -877,7 +878,7 @@ SimpleTimeZone::decodeEndRule(UErrorCode& status)
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
- } else if (endDay > STATICMONTHLENGTH[endMonth]) {
+ } else if (endDay<1 || endDay > STATICMONTHLENGTH[endMonth]) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
diff --git a/icu4c/source/i18n/timezone.cpp b/icu4c/source/i18n/timezone.cpp
index 79ecf4feef8..42200e475bd 100644
--- a/icu4c/source/i18n/timezone.cpp
+++ b/icu4c/source/i18n/timezone.cpp
@@ -1073,7 +1073,15 @@ TimeZone::getDisplayName(UBool daylight, EDisplayType style, UnicodeString& resu
{
return getDisplayName(daylight,style, Locale::getDefault(), result);
}
-
+//--------------------------------------
+inline int32_t
+TimeZone::getDSTSavings()const {
+ if (useDaylightTime()) {
+ return 3600000;
+ }
+ return 0;
+}
+//---------------------------------------
UnicodeString&
TimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& locale, UnicodeString& result) const
{
@@ -1100,14 +1108,17 @@ TimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& local
// and hence the same display name.
// We don't cache these because they're small and cheap to create.
UnicodeString tempID;
- SimpleTimeZone *tz = daylight ?
- // For the pure-DST zone, we use JANUARY and DECEMBER
-
- new SimpleTimeZone(getRawOffset(), getID(tempID),
- UCAL_JANUARY , 1, 0, 0,
- UCAL_DECEMBER , 31, 0, U_MILLIS_PER_DAY, status) :
- new SimpleTimeZone(getRawOffset(), getID(tempID));
-
+ SimpleTimeZone *tz = NULL;
+ if(daylight && useDaylightTime()){
+ // For the pure-DST zone, we use JANUARY and DECEMBER
+ int savings = getDSTSavings();
+ tz = new SimpleTimeZone(getRawOffset(), getID(tempID),
+ UCAL_JANUARY, 1, 0, 0,
+ UCAL_FEBRUARY, 1, 0, 0,
+ savings, status);
+ }else{
+ tz = new SimpleTimeZone(getRawOffset(), getID(tempID));
+ }
format.applyPattern(style == LONG ? ZZZZ_STR : Z_STR);
Calendar *myCalendar = (Calendar*)format.getCalendar();
myCalendar->setTimeZone(*tz); // copy
@@ -1115,7 +1126,7 @@ TimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& local
delete tz;
FieldPosition pos(FieldPosition::DONT_CARE);
- return format.format(UDate(196262345678.), result, pos); // Must use a valid date here.
+ return format.format(UDate(864000000L), result, pos); // Must use a valid date here.
}
diff --git a/icu4c/source/i18n/unicode/timezone.h b/icu4c/source/i18n/unicode/timezone.h
index 1d4e4bbe1b2..861a03bf969 100644
--- a/icu4c/source/i18n/unicode/timezone.h
+++ b/icu4c/source/i18n/unicode/timezone.h
@@ -602,7 +602,23 @@ public:
* @stable ICU 2.0
*/
virtual UClassID getDynamicClassID(void) const = 0;
-
+
+ /**
+ * Returns the amount of time to be added to local standard time
+ * to get local wall clock time.
+ *
+ * The default implementation always returns 3600000 milliseconds
+ * (i.e., one hour) if this time zone observes Daylight Saving
+ * Time. Otherwise, 0 (zero) is returned.
+ *
+ * If an underlying TimeZone implementation subclass supports
+ * historical Daylight Saving Time changes, this method returns
+ * the known latest daylight saving value.
+ *
+ * @return the amount of saving time in milliseconds
+ * @draft ICU 3.6
+ */
+ virtual inline int32_t getDSTSavings() const;
protected:
/**
diff --git a/icu4c/source/test/intltest/calregts.cpp b/icu4c/source/test/intltest/calregts.cpp
index d38bf8a9475..b515cf8f48e 100644
--- a/icu4c/source/test/intltest/calregts.cpp
+++ b/icu4c/source/test/intltest/calregts.cpp
@@ -215,6 +215,16 @@ CalendarRegressionTest::test4031502()
UErrorCode status = U_ZERO_ERROR;
StringEnumeration* ids = TimeZone::createEnumeration();
UBool bad = FALSE;
+ TimeZone* tz =TimeZone::createTimeZone("Asia/Riyadh87");
+ failure(status, "new TimeZone");
+ GregorianCalendar *cl = new GregorianCalendar(tz, status);
+ failure(status, "new GregorianCalendar");
+ cl->clear();
+ cl->set(1900, 15, 5, 5, 8, 13);
+ cl->get(UCAL_HOUR, status);
+ failure(status, "cl->get(UCAL_HOUR, status)");
+ status = U_ZERO_ERROR;
+ delete tz;
for (int32_t i=0; icount(status); ++i) {
TimeZone *zone = TimeZone::createTimeZone(*ids->snext(status));
GregorianCalendar *cal = new GregorianCalendar(zone, status);
diff --git a/icu4c/source/test/intltest/dtfmttst.cpp b/icu4c/source/test/intltest/dtfmttst.cpp
index a75653a0f2e..a1d94e5cdc1 100644
--- a/icu4c/source/test/intltest/dtfmttst.cpp
+++ b/icu4c/source/test/intltest/dtfmttst.cpp
@@ -176,6 +176,9 @@ DateFormatTest::TestEquals()
if (!(*fmtA == *fmtB)) errln((UnicodeString)"FAIL");
delete fmtA;
delete fmtB;
+
+ TimeZone* test = TimeZone::createTimeZone("PDT");
+ delete test;
}
// -------------------------------------
@@ -191,13 +194,21 @@ DateFormatTest::TestTwoDigitYearDSTParse(void)
SimpleDateFormat *fmt = new SimpleDateFormat((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status);
//DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH);
UnicodeString* s = new UnicodeString("03-Apr-04 2:20:47 o'clock AM PST", "");
- int32_t hour = 2;
-
+ TimeZone* defaultTZ = TimeZone::createDefault();
+ TimeZone* PST = TimeZone::createTimeZone("PST");
+ int32_t defaultOffset = defaultTZ->getRawOffset();
+ int32_t PSTOffset = PST->getRawOffset();
+ int32_t hour = 2 + (defaultOffset - PSTOffset) / (60*60*1000);
+ // hour is the expected hour of day, in units of seconds
+ hour = ((hour < 0) ? hour + 24 : hour) * 60*60;
+
UnicodeString str;
UDate d = fmt->parse(*s, status);
logln(*s + " P> " + ((DateFormat*)fullFmt)->format(d, str));
int32_t y, m, day, hr, min, sec;
dateToFields(d, y, m, day, hr, min, sec);
+ hour += defaultTZ->inDaylightTime(d, status) ? 1 : 0;
+ hr = hr*60*60;
if (hr != hour)
errln((UnicodeString)"FAIL: Should parse to hour " + hour + " but got " + hr);
@@ -207,6 +218,8 @@ DateFormatTest::TestTwoDigitYearDSTParse(void)
delete s;
delete fmt;
delete fullFmt;
+ delete PST;
+ delete defaultTZ;
}
// -------------------------------------
diff --git a/icu4c/source/test/intltest/intltest.vcproj b/icu4c/source/test/intltest/intltest.vcproj
index f77e64ce03a..3e90beeb0ef 100644
--- a/icu4c/source/test/intltest/intltest.vcproj
+++ b/icu4c/source/test/intltest/intltest.vcproj
@@ -362,6 +362,9 @@
+
+
@@ -384,9 +387,6 @@
-
-
diff --git a/icu4c/source/test/intltest/tzbdtest.cpp b/icu4c/source/test/intltest/tzbdtest.cpp
index 66e0f24a179..6e305f458f9 100644
--- a/icu4c/source/test/intltest/tzbdtest.cpp
+++ b/icu4c/source/test/intltest/tzbdtest.cpp
@@ -1,6 +1,6 @@
/***********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2004, International Business Machines Corporation
+ * Copyright (c) 1997-2005, International Business Machines Corporation
* and others. All Rights Reserved.
***********************************************************************/
@@ -193,13 +193,19 @@ TimeZoneBoundaryTest::verifyDST(UDate d, TimeZone* time_zone, UBool expUseDaylig
logln("-- Verifying time " + dateToString(d) + " in zone " + time_zone->getID(str));
if (time_zone->inDaylightTime(d, status) == expInDaylightTime)
logln(UnicodeString("PASS: inDaylightTime = ") + (time_zone->inDaylightTime(d, status)?"true":"false"));
- else errln(UnicodeString("FAIL: inDaylightTime = ") + (time_zone->inDaylightTime(d, status)?"true":"false"));
- if (failure(status, "TimeZone::inDaylightTime")) return;
+ else
+ errln(UnicodeString("FAIL: inDaylightTime = ") + (time_zone->inDaylightTime(d, status)?"true":"false"));
+ if (failure(status, "TimeZone::inDaylightTime"))
+ return;
if (time_zone->useDaylightTime() == expUseDaylightTime)
logln(UnicodeString("PASS: useDaylightTime = ") + (time_zone->useDaylightTime()?"true":"false"));
- else errln(UnicodeString("FAIL: useDaylightTime = ") + (time_zone->useDaylightTime()?"true":"false"));
- if (time_zone->getRawOffset() == expZoneOffset) logln(UnicodeString("PASS: getRawOffset() = ") + (expZoneOffset / ONE_HOUR));
- else errln(UnicodeString("FAIL: getRawOffset() = ") + (time_zone->getRawOffset() / ONE_HOUR) + "; expected " + (expZoneOffset / ONE_HOUR));
+ else
+ errln(UnicodeString("FAIL: useDaylightTime = ") + (time_zone->useDaylightTime()?"true":"false"));
+ if (time_zone->getRawOffset() == expZoneOffset)
+ logln(UnicodeString("PASS: getRawOffset() = ") + (expZoneOffset / ONE_HOUR));
+ else
+ errln(UnicodeString("FAIL: getRawOffset() = ") + (time_zone->getRawOffset() / ONE_HOUR) + "; expected " + (expZoneOffset / ONE_HOUR));
+
GregorianCalendar *gc = new GregorianCalendar(time_zone->clone(), status);
gc->setTime(d, status);
if (failure(status, "GregorianCalendar::setTime")) return;
@@ -215,7 +221,52 @@ TimeZoneBoundaryTest::verifyDST(UDate d, TimeZone* time_zone, UBool expUseDaylig
}
// -------------------------------------
-
+/**
+ * Check that the given year/month/dom/hour maps to and from the
+ * given epochHours. This verifies the functioning of the
+ * calendar and time zone in conjunction with one another,
+ * including the calendar time->fields and fields->time and
+ * the time zone getOffset method.
+ *
+ * @param epochHours hours after Jan 1 1970 0:00 GMT.
+ */
+void TimeZoneBoundaryTest::verifyMapping(Calendar& cal, int year, int month, int dom, int hour,
+ double epochHours) {
+ double H = 3600000.0;
+ UErrorCode status = U_ZERO_ERROR;
+ cal.clear();
+ cal.set(year, month, dom, hour, 0, 0);
+ UDate e = cal.getTime(status)/ H;
+ UDate ed = (epochHours * H);
+ if (e == epochHours) {
+ logln(UnicodeString("Ok: ") + year + "/" + (month+1) + "/" + dom + " " + hour + ":00 => " +
+ e + " (" + ed + ")");
+ } else {
+ errln(UnicodeString("FAIL: ") + year + "/" + (month+1) + "/" + dom + " " + hour + ":00 => " +
+ e + " (" + (e * H) + ")" +
+ ", expected " + epochHours + " (" + ed + ")");
+ }
+ cal.setTime(ed, status);
+ if (cal.get(UCAL_YEAR, status) == year &&
+ cal.get(UCAL_MONTH, status) == month &&
+ cal.get(UCAL_DATE, status) == dom &&
+ cal.get(UCAL_MILLISECONDS_IN_DAY, status) == hour * 3600000) {
+ logln(UnicodeString("Ok: ") + epochHours + " (" + ed + ") => " +
+ cal.get(UCAL_YEAR, status) + "/" +
+ (cal.get(UCAL_MONTH, status)+1) + "/" +
+ cal.get(UCAL_DATE, status) + " " +
+ cal.get(UCAL_MILLISECOND, status)/H);
+ } else {
+ errln(UnicodeString("FAIL: ") + epochHours + " (" + ed + ") => " +
+ cal.get(UCAL_YEAR, status) + "/" +
+ (cal.get(UCAL_MONTH, status)+1) + "/" +
+ cal.get(UCAL_DATE, status) + " " +
+ cal.get(UCAL_MILLISECOND, status)/H +
+ ", expected " + year + "/" + (month+1) + "/" + dom +
+ " " + hour);
+ }
+}
+
/**
* Test the behavior of SimpleTimeZone at the transition into and out of DST.
* Use a binary search to find boundaries.
@@ -223,6 +274,47 @@ TimeZoneBoundaryTest::verifyDST(UDate d, TimeZone* time_zone, UBool expUseDaylig
void
TimeZoneBoundaryTest::TestBoundaries()
{
+ UErrorCode status = U_ZERO_ERROR;
+ TimeZone* pst = TimeZone::createTimeZone("PST");
+ Calendar* tempcal = Calendar::createInstance(pst, status);
+ if(U_SUCCESS(status)){
+ verifyMapping(*tempcal, 1997, Calendar::APRIL, 3, 0, 238904.0);
+ verifyMapping(*tempcal, 1997, Calendar::APRIL, 4, 0, 238928.0);
+ verifyMapping(*tempcal, 1997, Calendar::APRIL, 5, 0, 238952.0);
+ verifyMapping(*tempcal, 1997, Calendar::APRIL, 5, 23, 238975.0);
+ verifyMapping(*tempcal, 1997, Calendar::APRIL, 6, 0, 238976.0);
+ verifyMapping(*tempcal, 1997, Calendar::APRIL, 6, 1, 238977.0);
+ verifyMapping(*tempcal, 1997, Calendar::APRIL, 6, 3, 238978.0);
+ }else{
+ errln("Could not create calendar. Error: %s", u_errorName(status));
+ }
+ TimeZone* utc = TimeZone::createTimeZone("UTC");
+ Calendar* utccal = Calendar::createInstance(utc, status);
+ if(U_SUCCESS(status)){
+ verifyMapping(*utccal, 1997, Calendar::APRIL, 6, 0, 238968.0);
+ }else{
+ errln("Could not create calendar. Error: %s", u_errorName(status));
+ }
+ TimeZone* save = TimeZone::createDefault();
+ TimeZone::setDefault(*pst);
+
+ // DST changeover for PST is 4/6/1997 at 2 hours past midnight
+ // at 238978.0 epoch hours.
+ tempcal->clear();
+ tempcal->set(1997, Calendar::APRIL, 6);
+ UDate d = tempcal->getTime(status);
+
+ // i is minutes past midnight standard time
+ for (int i=-120; i<=180; i+=60)
+ {
+ UBool inDST = (i >= 120);
+ tempcal->setTime(d + i*60*1000, status);
+ verifyDST(tempcal->getTime(status),pst, TRUE, inDST, -8*ONE_HOUR,inDST ? -7*ONE_HOUR : -8*ONE_HOUR);
+ }
+ TimeZone::setDefault(*save);
+ delete utccal;
+ delete tempcal;
+
#if 1
{
logln("--- Test a ---");
@@ -292,7 +384,7 @@ TimeZoneBoundaryTest::testUsingBinarySearch(SimpleTimeZone* tz, UDate d, UDate e
UBool startsInDST = tz->inDaylightTime(d, status);
if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
if (tz->inDaylightTime(max, status) == startsInDST) {
- logln("Error: inDaylightTime(" + dateToString(max) + ") != " + ((!startsInDST)?"true":"false"));
+ errln("Error: inDaylightTime(" + dateToString(max) + ") != " + ((!startsInDST)?"true":"false"));
}
if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
while ((max - min) > INTERVAL) {
diff --git a/icu4c/source/test/intltest/tzbdtest.h b/icu4c/source/test/intltest/tzbdtest.h
index f58beb62569..ecc867c9faf 100644
--- a/icu4c/source/test/intltest/tzbdtest.h
+++ b/icu4c/source/test/intltest/tzbdtest.h
@@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * Copyright (c) 1997-2005, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
@@ -79,7 +79,8 @@ public: // package
* Use a stepwise march to find boundaries.
*/
virtual void TestStepwise(void);
-
+ void verifyMapping(Calendar& cal, int year, int month, int dom, int hour,
+ double epochHours) ;
private:
const UDate ONE_SECOND;
const UDate ONE_MINUTE;
diff --git a/icu4c/source/test/intltest/tzregts.cpp b/icu4c/source/test/intltest/tzregts.cpp
index b13947873a8..c1844141a43 100644
--- a/icu4c/source/test/intltest/tzregts.cpp
+++ b/icu4c/source/test/intltest/tzregts.cpp
@@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2003, International Business Machines Corporation and
+ * Copyright (c) 1997-2005, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
@@ -18,7 +18,8 @@
// *****************************************************************************
// class TimeZoneRegressionTest
// *****************************************************************************
-
+/* length of an array */
+#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
void
@@ -44,7 +45,8 @@ TimeZoneRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &
CASE(14, TestJ186);
CASE(15, TestJ449);
CASE(16, TestJDK12API);
-
+ CASE(17, Test4176686);
+ CASE(18, Test4184229);
default: name = ""; break;
}
}
@@ -871,16 +873,16 @@ TimeZoneRegressionTest::Test4162593()
// Must construct the Date object AFTER setting the default zone
int32_t *p = (int32_t*)DATA_INT[j];
UDate d = CalendarRegressionTest::makeDate(p[0], p[1], p[2], p[3], p[4]);
- UBool transitionExpected = DATA_BOOL[j];
+ UBool transitionExpected = DATA_BOOL[j];
UnicodeString temp;
logln(tz->getID(temp) + ":");
for (int32_t i = 0; i < 4; ++i) {
FieldPosition pos(0);
zone[i].remove();
- zone[i] = fmt->format(d, zone[i], pos);
+ zone[i] = fmt->format(d+ i*ONE_HOUR, zone[i], pos);
logln(UnicodeString("") + i + ": " + d + " / " + zone[i]);
- d += (double) ONE_HOUR;
+ //d += (double) ONE_HOUR;
}
if(zone[0] == zone[1] &&
(zone[1] == zone[2]) != transitionExpected &&
@@ -896,6 +898,72 @@ TimeZoneRegressionTest::Test4162593()
delete DATA_TZ[0];
}
+ /**
+ * getDisplayName doesn't work with unusual savings/offsets.
+ */
+void TimeZoneRegressionTest::Test4176686() {
+ // Construct a zone that does not observe DST but
+ // that does have a DST savings (which should be ignored).
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t offset = 90 * 60000; // 1:30
+ SimpleTimeZone* z1 = new SimpleTimeZone(offset, "_std_zone_");
+ z1->setDSTSavings(45 * 60000, status); // 0:45
+
+ // Construct a zone that observes DST for the first 6 months.
+ SimpleTimeZone* z2 = new SimpleTimeZone(offset, "_dst_zone_");
+ z2->setDSTSavings(45 * 60000, status); // 0:45
+ z2->setStartRule(UCAL_JANUARY, 1, 0, status);
+ z2->setEndRule(UCAL_JULY, 1, 0, status);
+
+ // Also check DateFormat
+ DateFormat* fmt1 = new SimpleDateFormat(UnicodeString("z"), status);
+ fmt1->setTimeZone(*z1); // Format uses standard zone
+ DateFormat* fmt2 = new SimpleDateFormat(UnicodeString("z"), status);
+ fmt2->setTimeZone(*z2); // Format uses DST zone
+ Calendar* tempcal = Calendar::createInstance(status);
+ tempcal->clear();
+ tempcal->set(1970, UCAL_FEBRUARY, 1);
+ UDate dst = tempcal->getTime(status); // Time in DST
+ tempcal->set(1970, UCAL_AUGUST, 1);
+ UDate std = tempcal->getTime(status); // Time in standard
+
+ // Description, Result, Expected Result
+ UnicodeString a,b,c,d,e,f,g,h,i,j,k,l;
+ UnicodeString DATA[] = {
+ "z1->getDisplayName(false, SHORT)/std zone",
+ z1->getDisplayName(FALSE, TimeZone::SHORT, a), "GMT+01:30",
+ "z1->getDisplayName(false, LONG)/std zone",
+ z1->getDisplayName(FALSE, TimeZone::LONG, b), "GMT+01:30",
+ "z1->getDisplayName(true, SHORT)/std zone",
+ z1->getDisplayName(TRUE, TimeZone::SHORT, c), "GMT+01:30",
+ "z1->getDisplayName(true, LONG)/std zone",
+ z1->getDisplayName(TRUE, TimeZone::LONG, d ), "GMT+01:30",
+ "z2->getDisplayName(false, SHORT)/dst zone",
+ z2->getDisplayName(FALSE, TimeZone::SHORT, e), "GMT+01:30",
+ "z2->getDisplayName(false, LONG)/dst zone",
+ z2->getDisplayName(FALSE, TimeZone::LONG, f ), "GMT+01:30",
+ "z2->getDisplayName(true, SHORT)/dst zone",
+ z2->getDisplayName(TRUE, TimeZone::SHORT, g), "GMT+02:15",
+ "z2->getDisplayName(true, LONG)/dst zone",
+ z2->getDisplayName(TRUE, TimeZone::LONG, h ), "GMT+02:15",
+ "DateFormat.format(std)/std zone", fmt1->format(std, i), "GMT+01:30",
+ "DateFormat.format(dst)/std zone", fmt1->format(dst, j), "GMT+01:30",
+ "DateFormat.format(std)/dst zone", fmt2->format(std, k), "GMT+01:30",
+ "DateFormat.format(dst)/dst zone", fmt2->format(dst, l), "GMT+02:15",
+ };
+
+ for (int i=0; i " + DATA[i+1] + ", exp " + DATA[i+2]);
+ }
+ }
+ delete z1;
+ delete z2;
+ delete fmt1;
+ delete fmt2;
+ delete tempcal;
+}
+
/**
* Make sure setStartRule and setEndRule set the DST savings to nonzero
* if it was zero.
@@ -1050,5 +1118,76 @@ TimeZoneRegressionTest::TestJDK12API()
delete pst;
delete cst;
}
+/**
+ * SimpleTimeZone allows invalid DOM values.
+ */
+void TimeZoneRegressionTest::Test4184229() {
+ SimpleTimeZone* zone = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, status);
+ if(U_SUCCESS(status)){
+ errln("Failed. No exception has been thrown for DOM -1 startDay");
+ }else{
+ logln("(a) " + UnicodeString( u_errorName(status)));
+ }
+ status = U_ZERO_ERROR;
+ delete zone;
+
+ zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, status);
+ if(U_SUCCESS(status)){
+ errln("Failed. No exception has been thrown for DOM -1 endDay");
+ }else{
+ logln("(b) " + UnicodeString(u_errorName(status)));
+ }
+ status = U_ZERO_ERROR;
+ delete zone;
+
+ zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 1000, status);
+ if(U_SUCCESS(status)){
+ errln("Failed. No exception has been thrown for DOM -1 startDay+savings");
+ }else{
+ logln("(c) " + UnicodeString(u_errorName(status)));
+ }
+ status = U_ZERO_ERROR;
+ delete zone;
+ zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000, status);
+ if(U_SUCCESS(status)){
+ errln("Failed. No exception has been thrown for DOM -1 endDay+ savings");
+ }else{
+ logln("(d) " + UnicodeString(u_errorName(status)));
+ }
+ status = U_ZERO_ERROR;
+ delete zone;
+ // Make a valid constructor call for subsequent tests.
+ zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0, status);
+
+ zone->setStartRule(0, -1, 0, 0, status);
+ if(U_SUCCESS(status)){
+ errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings");
+ } else{
+ logln("(e) " + UnicodeString(u_errorName(status)));
+ }
+ zone->setStartRule(0, -1, 0, status);
+ if(U_SUCCESS(status)){
+ errln("Failed. No exception has been thrown for DOM -1 setStartRule");
+ } else{
+ logln("(f) " + UnicodeString(u_errorName(status)));
+ }
+
+ zone->setEndRule(0, -1, 0, 0, status);
+ if(U_SUCCESS(status)){
+ errln("Failed. No exception has been thrown for DOM -1 setEndRule+savings");
+ } else{
+ logln("(g) " + UnicodeString(u_errorName(status)));
+ }
+
+ zone->setEndRule(0, -1, 0, status);
+ if(U_SUCCESS(status)){
+ errln("Failed. No exception has been thrown for DOM -1 setEndRule");
+ } else{
+ logln("(h) " + UnicodeString(u_errorName(status)));
+ }
+ delete zone;
+}
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4c/source/test/intltest/tzregts.h b/icu4c/source/test/intltest/tzregts.h
index 5fefadb7476..6b5500c953e 100644
--- a/icu4c/source/test/intltest/tzregts.h
+++ b/icu4c/source/test/intltest/tzregts.h
@@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1998-2001, International Business Machines Corporation and
+ * Copyright (c) 1998-2005, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
@@ -41,10 +41,11 @@ public:
void Test4154650(void);
void Test4154525(void);
void Test4162593(void);
+ void Test4176686(void);
void TestJ186(void);
void TestJ449(void);
void TestJDK12API(void);
-
+ void Test4184229(void);
UBool checkCalendar314(GregorianCalendar *testCal, TimeZone *testTZ);
diff --git a/icu4c/source/test/intltest/tztest.cpp b/icu4c/source/test/intltest/tztest.cpp
index 9ec3b8e09f3..176f9677968 100644
--- a/icu4c/source/test/intltest/tztest.cpp
+++ b/icu4c/source/test/intltest/tztest.cpp
@@ -48,6 +48,7 @@ void TimeZoneTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
CASE(11,TestHistorical);
CASE(12,TestEquivalentIDs);
CASE(13, TestAliasedNames);
+ CASE(14, TestFractionalDST);
default: name = ""; break;
}
}
@@ -776,7 +777,7 @@ void TimeZoneTest::TestCustomParse()
kData[] =
{
// ID Expected offset in minutes
- //"GMT", kUnparseable, Isn't custom. Can't test it here. [returns normal GMT]
+ //{"GMT", kUnparseable}, //Isn't custom. Can't test it here. [returns normal GMT]
{"GMT-YOUR.AD.HERE", kUnparseable},
// {"GMT0", kUnparseable}, // ICU 2.8: An Olson zone ID
// {"GMT+0", (0)}, // ICU 2.8: An Olson zone ID
@@ -1334,6 +1335,22 @@ TimeZoneTest::TestAlternateRules()
+ (offset / U_MILLIS_PER_HOUR) + " hours.");
}
+void TimeZoneTest::TestFractionalDST() {
+ const char* tzName = "Australia/Lord_Howe"; // 30 min offset
+ TimeZone* tz_icu = TimeZone::createTimeZone(tzName);
+ int dst_icu = tz_icu->getDSTSavings();
+ UnicodeString id;
+ int32_t expected = 1800000;
+ if (expected != dst_icu) {
+ errln(UnicodeString("java reports dst savings of ") + expected +
+ " but icu reports " + dst_icu +
+ " for tz " + tz_icu->getID(id));
+ } else {
+ logln(UnicodeString("both java and icu report dst savings of ") + expected + " for tz " + tz_icu->getID(id));
+ }
+ delete tz_icu;
+}
+
/**
* Test country code support. Jitterbug 776.
*/
diff --git a/icu4c/source/test/intltest/tztest.h b/icu4c/source/test/intltest/tztest.h
index 5e24930bb4b..6aa70343ff0 100644
--- a/icu4c/source/test/intltest/tztest.h
+++ b/icu4c/source/test/intltest/tztest.h
@@ -84,7 +84,9 @@ public:
void TestEquivalentIDs(void);
void TestAliasedNames(void);
-
+
+ void TestFractionalDST(void);
+
static const UDate INTERVAL;
private: