ICU-6321 TimeZone::getDisplayName(), move bug fixes from Java to C++

X-SVN-Rev: 24126
This commit is contained in:
Andy Heninger 2008-06-09 03:46:34 +00:00
parent 2fa2db21f7
commit 4635ea3a9c
3 changed files with 140 additions and 18 deletions

View file

@ -1175,7 +1175,7 @@ TimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& local
char buf[128];
fID.extract(0, sizeof(buf)-1, buf, sizeof(buf), "");
#endif
SimpleDateFormat format(style == LONG ? ZZZZ_STR : Z_STR,locale,status);
SimpleDateFormat format(style == LONG ? ZZZZ_STR : Z_STR, locale, status);
U_DEBUG_TZ_MSG(("getDisplayName(%s)\n", buf));
if(!U_SUCCESS(status))
{
@ -1187,30 +1187,69 @@ TimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& local
return result.remove();
}
UDate d = Calendar::getNow();
int32_t rawOffset;
int32_t dstOffset;
this->getOffset(d, FALSE, rawOffset, dstOffset, status);
if (U_FAILURE(status)) {
return result.remove();
}
if ((daylight && dstOffset != 0) || (!daylight && dstOffset == 0)) {
// Current time and the request (daylight / not daylight) agree.
format.setTimeZone(*this);
return format.format(d, result);
}
// Create a new SimpleTimeZone as a stand-in for this zone; the
// stand-in will have no DST, or all DST, but the same ID and offset,
// stand-in will have no DST, or DST during July, but the same ID and offset,
// and hence the same display name.
// We don't cache these because they're small and cheap to create.
UnicodeString tempID;
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));
if(daylight && useDaylightTime()){
// The display name for daylight saving time was requested, but currently not in DST
// Set a fixed date (July 1) in this Gregorian year
GregorianCalendar cal(*this, status);
if (U_FAILURE(status)) {
return result.remove();
}
cal.set(UCAL_MONTH, UCAL_JULY);
cal.set(UCAL_DATE, 1);
// Get July 1 date
d = cal.getTime(status);
// Check if it is in DST
if (cal.get(UCAL_DST_OFFSET, status) == 0) {
// We need to create a fake time zone
tz = new SimpleTimeZone(rawOffset, tempID,
UCAL_JUNE, 1, 0, 0,
UCAL_AUGUST, 1, 0, 0,
getDSTSavings(), status);
if (U_FAILURE(status) || tz == NULL) {
if (U_SUCCESS(status)) {
status = U_MEMORY_ALLOCATION_ERROR;
}
return result.remove();
}
format.adoptTimeZone(tz);
}
} else {
// The display name for standard time was requested, but currently in DST
tz = new SimpleTimeZone(rawOffset, tempID);
if (U_FAILURE(status) || tz == NULL) {
if (U_SUCCESS(status)) {
status = U_MEMORY_ALLOCATION_ERROR;
}
return result.remove();
}
format.adoptTimeZone(tz);
}
format.applyPattern(style == LONG ? ZZZZ_STR : Z_STR);
Calendar *myCalendar = (Calendar*)format.getCalendar();
myCalendar->setTimeZone(*tz); // copy
delete tz;
FieldPosition pos(FieldPosition::DONT_CARE);
return format.format(UDate(864000000L), result, pos); // Must use a valid date here.
format.format(d, result, status);
return result;
}

View file

@ -55,6 +55,7 @@ void TimeZoneTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
CASE(14, TestFractionalDST);
CASE(15, TestFebruary);
CASE(16, TestCanonicalID);
CASE(17, TestDisplayNamesMeta);
default: name = ""; break;
}
}
@ -1805,4 +1806,84 @@ void TimeZoneTest::TestCanonicalID() {
}
}
//
// Test Display Names, choosing zones and lcoales where there are multiple
// meta-zones defined.
//
static struct {
const char *zoneName;
const char *localeName;
UBool summerTime;
TimeZone::EDisplayType style;
const char *expectedDisplayName; }
zoneDisplayTestData [] = {
// zone id locale summer format expected display name
{"Europe/London", "en", FALSE, TimeZone::SHORT, "GMT"},
{"Europe/London", "en", FALSE, TimeZone::LONG, "Greenwich Mean Time"},
{"Europe/London", "en", TRUE, TimeZone::SHORT, "GMT+01:00" /*"BST"*/},
{"Europe/London", "en", TRUE, TimeZone::LONG, "British Summer Time"},
{"America/Anchorage", "en", FALSE, TimeZone::SHORT, "AKST"},
{"America/Anchorage", "en", FALSE, TimeZone::LONG, "Alaska Standard Time"},
{"America/Anchorage", "en", TRUE, TimeZone::SHORT, "AKDT"},
{"America/Anchorage", "en", TRUE, TimeZone::LONG, "Alaska Daylight Time"},
// Southern Hemisphere, all data from meta:Australia_Western
{"Australia/Perth", "en", FALSE, TimeZone::SHORT, "GMT+08:00"/*"AWST"*/},
{"Australia/Perth", "en", FALSE, TimeZone::LONG, "Australian Western Standard Time"},
{"Australia/Perth", "en", TRUE, TimeZone::SHORT, "GMT+09:00"/*"AWDT"*/},
{"Australia/Perth", "en", TRUE, TimeZone::LONG, "Australian Western Daylight Time"},
{"America/Sao_Paulo", "en", FALSE, TimeZone::SHORT, "GMT-03:00"/*"BRT"*/},
{"America/Sao_Paulo", "en", FALSE, TimeZone::LONG, "Brasilia Time"},
{"America/Sao_Paulo", "en", TRUE, TimeZone::SHORT, "GMT-02:00"/*"BRST"*/},
{"America/Sao_Paulo", "en", TRUE, TimeZone::LONG, "Brasilia Summer Time"},
// No Summer Time, but had it before 1983.
{"Pacific/Honolulu", "en", FALSE, TimeZone::SHORT, "HST"},
{"Pacific/Honolulu", "en", FALSE, TimeZone::LONG, "Hawaii-Aleutian Standard Time"},
{"Pacific/Honolulu", "en", TRUE, TimeZone::SHORT, "HST"},
{"Pacific/Honolulu", "en", TRUE, TimeZone::LONG, "Hawaii-Aleutian Standard Time"},
// Northern, has Summer, not commonly used.
{"Europe/Helsinki", "en", FALSE, TimeZone::SHORT, "GMT+02:00"/*"EET"*/},
{"Europe/Helsinki", "en", FALSE, TimeZone::LONG, "Eastern European Time"},
{"Europe/Helsinki", "en", TRUE, TimeZone::SHORT, "GMT+03:00"/*"EEST"*/},
{"Europe/Helsinki", "en", true, TimeZone::LONG, "Eastern European Summer Time"},
{NULL, NULL, FALSE, TimeZone::SHORT, NULL} // NULL values terminate list
};
void TimeZoneTest::TestDisplayNamesMeta() {
UBool sawAnError = FALSE;
for (int testNum = 0; zoneDisplayTestData[testNum].zoneName != NULL; testNum++) {
Locale locale = Locale::createFromName(zoneDisplayTestData[testNum].localeName);
TimeZone *zone = TimeZone::createTimeZone(zoneDisplayTestData[testNum].zoneName);
UnicodeString displayName;
zone->getDisplayName(zoneDisplayTestData[testNum].summerTime,
zoneDisplayTestData[testNum].style,
locale,
displayName);
if (displayName != zoneDisplayTestData[testNum].expectedDisplayName) {
sawAnError = TRUE;
char name[100];
UErrorCode status = U_ZERO_ERROR;
displayName.extract(name, 100, NULL, status);
errln("Incorrect time zone display name. zone = \"%s\",\n"
" locale = \"%s\", style = %s, Summertime = %d\n"
" Expected \"%s\", "
" Got \"%s\"\n", zoneDisplayTestData[testNum].zoneName,
zoneDisplayTestData[testNum].localeName,
zoneDisplayTestData[testNum].style==TimeZone::SHORT ?
"SHORT" : "LONG",
zoneDisplayTestData[testNum].summerTime,
zoneDisplayTestData[testNum].expectedDisplayName,
name);
}
delete zone;
}
if (sawAnError) {
errln("Note: Errors could be the result of changes to zoneStrings locale data");
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -89,6 +89,8 @@ public:
void TestFebruary(void);
void TestCanonicalID(void);
virtual void TestDisplayNamesMeta();
static const UDate INTERVAL;