Adjust tzset() implementation to better follow the POSIX specs and
make some more perl tests happy. * no longer expect a ICU timezone ID in the TZ environment variable, but only expect this format if the TZ-value is starting with ':' * accept "standard" TZ-values like "EST5" (of which only "EST" is relevant to us) - if such a value is specified, we hardcode the timezone name to the given value, no matter how ICU calls it * adjust tests accordingly git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39415 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -45,7 +45,7 @@ public:
|
||||
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
||||
size_t& outSize);
|
||||
|
||||
virtual status_t TZSet(const char* timeZoneID);
|
||||
virtual status_t TZSet(const char* timeZoneID, const char* tz);
|
||||
virtual status_t Localtime(const time_t* inTime,
|
||||
struct tm* tmOut);
|
||||
virtual status_t Gmtime(const time_t* inTime, struct tm* tmOut);
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
virtual void Initialize(
|
||||
TimeConversionDataBridge* dataBridge);
|
||||
|
||||
status_t TZSet(const char* timeZoneID);
|
||||
status_t TZSet(const char* timeZoneID, const char* tz);
|
||||
|
||||
status_t Localtime(const time_t* inTime,
|
||||
struct tm* tmOut);
|
||||
|
||||
@@ -127,7 +127,8 @@ public:
|
||||
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
||||
size_t& outSize) = 0;
|
||||
|
||||
virtual status_t TZSet(const char* timeZoneID) = 0;
|
||||
virtual status_t TZSet(const char* timeZoneID,
|
||||
const char* tz) = 0;
|
||||
virtual status_t Localtime(const time_t* inTime,
|
||||
struct tm* tmOut) = 0;
|
||||
virtual status_t Gmtime(const time_t* inTime,
|
||||
|
||||
@@ -245,11 +245,11 @@ ICULocaleBackend::Strxfrm(char* out, const char* in, size_t size,
|
||||
|
||||
|
||||
status_t
|
||||
ICULocaleBackend::TZSet(const char* timeZoneID)
|
||||
ICULocaleBackend::TZSet(const char* timeZoneID, const char* tz)
|
||||
{
|
||||
ErrnoMaintainer errnoMaintainer;
|
||||
|
||||
return fTimeConversion.TZSet(timeZoneID);
|
||||
return fTimeConversion.TZSet(timeZoneID, tz);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,13 +39,41 @@ ICUTimeConversion::Initialize(TimeConversionDataBridge* dataBridge)
|
||||
|
||||
|
||||
status_t
|
||||
ICUTimeConversion::TZSet(const char* timeZoneID)
|
||||
ICUTimeConversion::TZSet(const char* timeZoneID, const char* tz)
|
||||
{
|
||||
// nothing to do if the given name matches any name of the current timezone
|
||||
if (strcasecmp(fTimeZoneID, timeZoneID) == 0)
|
||||
return B_OK;
|
||||
// The given TZ environment variable's content overrides the default
|
||||
// system timezone.
|
||||
if (tz != NULL) {
|
||||
// If the value given in the TZ env-var starts with a colon, that
|
||||
// value is implementation specific, we expect a full timezone ID.
|
||||
if (*tz == ':') {
|
||||
// nothing to do if the given name matches the current timezone
|
||||
if (strcasecmp(fTimeZoneID, tz + 1) == 0)
|
||||
return B_OK;
|
||||
|
||||
strlcpy(fTimeZoneID, timeZoneID, sizeof(fTimeZoneID));
|
||||
strlcpy(fTimeZoneID, tz + 1, sizeof(fTimeZoneID));
|
||||
} else {
|
||||
// We ignore anything following the timezone name, as those values
|
||||
// are determined by the corresponding ICU-timezone (and glibc's
|
||||
// tzset() implementation seems to do the same).
|
||||
const char* tzNameEnd = tz;
|
||||
while(isalpha(*tzNameEnd))
|
||||
++tzNameEnd;
|
||||
|
||||
strlcpy(fTimeZoneID, tz,
|
||||
min_c((uint32)(1 + tzNameEnd - tz), sizeof(fTimeZoneID)));
|
||||
|
||||
// nothing to do if the given name matches the current timezone
|
||||
if (strcasecmp(fTimeZoneID, fDataBridge->addrOfTZName[0]) == 0)
|
||||
return B_OK;
|
||||
}
|
||||
} else {
|
||||
// nothing to do if the given name matches the current timezone
|
||||
if (strcasecmp(fTimeZoneID, timeZoneID) == 0)
|
||||
return B_OK;
|
||||
|
||||
strlcpy(fTimeZoneID, timeZoneID, sizeof(fTimeZoneID));
|
||||
}
|
||||
|
||||
ObjectDeleter<TimeZone> icuTimeZone = TimeZone::createTimeZone(fTimeZoneID);
|
||||
if (icuTimeZone.Get() == NULL)
|
||||
@@ -71,16 +99,20 @@ ICUTimeConversion::TZSet(const char* timeZoneID)
|
||||
*fDataBridge->addrOfDaylight = icuTimeZone->useDaylightTime();
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
UnicodeString icuString;
|
||||
icuTimeZone->getDisplayName(i == 1, TimeZone::SHORT_COMMONLY_USED,
|
||||
fTimeData.ICULocale(), icuString);
|
||||
CheckedArrayByteSink byteSink(fDataBridge->addrOfTZName[i],
|
||||
sizeof(fTimeZoneID));
|
||||
icuString.toUTF8(byteSink);
|
||||
if (tz != NULL && *tz != ':' && i == 0) {
|
||||
strcpy(fDataBridge->addrOfTZName[0], fTimeZoneID);
|
||||
} else {
|
||||
UnicodeString icuString;
|
||||
icuTimeZone->getDisplayName(i == 1, TimeZone::SHORT_COMMONLY_USED,
|
||||
fTimeData.ICULocale(), icuString);
|
||||
CheckedArrayByteSink byteSink(fDataBridge->addrOfTZName[i],
|
||||
sizeof(fTimeZoneID));
|
||||
icuString.toUTF8(byteSink);
|
||||
|
||||
// make sure to canonicalize "GMT+00:00" to just "GMT"
|
||||
if (strcmp(fDataBridge->addrOfTZName[i], "GMT+00:00") == 0)
|
||||
fDataBridge->addrOfTZName[i][3] = '\0';
|
||||
// make sure to canonicalize "GMT+00:00" to just "GMT"
|
||||
if (strcmp(fDataBridge->addrOfTZName[i], "GMT+00:00") == 0)
|
||||
fDataBridge->addrOfTZName[i][3] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
||||
@@ -39,15 +39,9 @@ tzset(void)
|
||||
return;
|
||||
|
||||
char timeZoneID[B_FILE_NAME_LENGTH] = { "GMT" };
|
||||
_kern_get_timezone(NULL, timeZoneID, sizeof(timeZoneID));
|
||||
|
||||
const char* tz = getenv("TZ");
|
||||
if (tz != NULL)
|
||||
strlcpy(timeZoneID, tz, sizeof(timeZoneID));
|
||||
else
|
||||
_kern_get_timezone(NULL, timeZoneID, sizeof(timeZoneID));
|
||||
|
||||
if (gLocaleBackend != NULL)
|
||||
gLocaleBackend->TZSet(timeZoneID);
|
||||
gLocaleBackend->TZSet(timeZoneID, getenv("TZ"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1819,30 +1819,42 @@ test_timeconversions()
|
||||
gtm.tm_wday = -1;
|
||||
gtm.tm_yday = -1;
|
||||
test_mktime("GMT", gtm, testTime, 6, 197);
|
||||
|
||||
tm btm = {
|
||||
9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST"
|
||||
};
|
||||
test_localtime("Europe/Berlin", testTime, btm);
|
||||
test_gmtime("Europe/Berlin", testTime, gtm);
|
||||
test_localtime(":Europe/Berlin", testTime, btm);
|
||||
test_gmtime(":Europe/Berlin", testTime, gtm);
|
||||
btm.tm_wday = -1;
|
||||
btm.tm_yday = -1;
|
||||
test_mktime("Europe/Berlin", btm, testTime, 6, 197);
|
||||
test_mktime(":Europe/Berlin", btm, testTime, 6, 197);
|
||||
|
||||
tm ctm = {
|
||||
9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST"
|
||||
};
|
||||
test_localtime("CET", testTime, ctm);
|
||||
test_gmtime("CET", testTime, gtm);
|
||||
ctm.tm_wday = -1;
|
||||
ctm.tm_yday = -1;
|
||||
test_mktime("CET", ctm, testTime, 6, 197);
|
||||
|
||||
tm latm = {
|
||||
9, 26, 11, 17, 6, 110, 6, 197, 1, -7 * 3600, (char*)"PDT"
|
||||
};
|
||||
test_localtime("America/Los_Angeles", testTime, latm);
|
||||
test_gmtime("America/Los_Angeles", testTime, gtm);
|
||||
test_localtime(":America/Los_Angeles", testTime, latm);
|
||||
test_gmtime(":America/Los_Angeles", testTime, gtm);
|
||||
latm.tm_wday = -1;
|
||||
latm.tm_yday = -1;
|
||||
test_mktime("America/Los_Angeles", latm, testTime, 6, 197);
|
||||
test_mktime(":America/Los_Angeles", latm, testTime, 6, 197);
|
||||
|
||||
tm ttm = {
|
||||
9, 26, 3, 18, 6, 110, 0, 198, 0, 9 * 3600, (char*)"JST"
|
||||
};
|
||||
test_localtime("Asia/Tokyo", testTime, ttm);
|
||||
test_gmtime("Asia/Tokyo", testTime, gtm);
|
||||
test_localtime(":Asia/Tokyo", testTime, ttm);
|
||||
test_gmtime(":Asia/Tokyo", testTime, gtm);
|
||||
ttm.tm_wday = -1;
|
||||
ttm.tm_yday = -1;
|
||||
test_mktime("Asia/Tokyo", ttm, testTime, 0, 198);
|
||||
test_mktime(":Asia/Tokyo", ttm, testTime, 0, 198);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1855,30 +1867,42 @@ test_timeconversions()
|
||||
gtm.tm_wday = -1;
|
||||
gtm.tm_yday = -1;
|
||||
test_mktime("GMT", gtm, testTime, 2, 67);
|
||||
|
||||
tm btm = {
|
||||
9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET"
|
||||
};
|
||||
test_localtime("Europe/Berlin", testTime, btm);
|
||||
test_gmtime("Europe/Berlin", testTime, gtm);
|
||||
test_localtime(":Europe/Berlin", testTime, btm);
|
||||
test_gmtime(":Europe/Berlin", testTime, gtm);
|
||||
btm.tm_wday = -1;
|
||||
btm.tm_yday = -1;
|
||||
test_mktime("Europe/Berlin", btm, testTime, 2, 67);
|
||||
test_mktime(":Europe/Berlin", btm, testTime, 2, 67);
|
||||
|
||||
tm ctm = {
|
||||
9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET"
|
||||
};
|
||||
test_localtime("CET", testTime, ctm);
|
||||
test_gmtime("CET", testTime, gtm);
|
||||
ctm.tm_wday = -1;
|
||||
ctm.tm_yday = -1;
|
||||
test_mktime("CET", ctm, testTime, 2, 67);
|
||||
|
||||
tm latm = {
|
||||
9, 26, 10, 9, 2, 110, 2, 67, 0, -8 * 3600, (char*)"PST"
|
||||
};
|
||||
test_localtime("America/Los_Angeles", testTime, latm);
|
||||
test_gmtime("America/Los_Angeles", testTime, gtm);
|
||||
test_localtime(":America/Los_Angeles", testTime, latm);
|
||||
test_gmtime(":America/Los_Angeles", testTime, gtm);
|
||||
latm.tm_wday = -1;
|
||||
latm.tm_yday = -1;
|
||||
test_mktime("America/Los_Angeles", latm, testTime, 2, 67);
|
||||
test_mktime(":America/Los_Angeles", latm, testTime, 2, 67);
|
||||
|
||||
tm ttm = {
|
||||
9, 26, 3, 10, 2, 110, 3, 68, 0, 9 * 3600, (char*)"JST"
|
||||
};
|
||||
test_localtime("Asia/Tokyo", testTime, ttm);
|
||||
test_gmtime("Asia/Tokyo", testTime, gtm);
|
||||
test_localtime(":Asia/Tokyo", testTime, ttm);
|
||||
test_gmtime(":Asia/Tokyo", testTime, gtm);
|
||||
ttm.tm_wday = -1;
|
||||
ttm.tm_yday = -1;
|
||||
test_mktime("Asia/Tokyo", ttm, testTime, 3, 68);
|
||||
test_mktime(":Asia/Tokyo", ttm, testTime, 3, 68);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1891,30 +1915,42 @@ test_timeconversions()
|
||||
gtm.tm_wday = -1;
|
||||
gtm.tm_yday = -1;
|
||||
test_mktime("GMT", gtm, testTime, 4, 0);
|
||||
|
||||
tm btm = {
|
||||
0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET"
|
||||
};
|
||||
test_localtime("Europe/Berlin", testTime, btm);
|
||||
test_gmtime("Europe/Berlin", testTime, gtm);
|
||||
test_localtime(":Europe/Berlin", testTime, btm);
|
||||
test_gmtime(":Europe/Berlin", testTime, gtm);
|
||||
btm.tm_wday = -1;
|
||||
btm.tm_yday = -1;
|
||||
test_mktime("Europe/Berlin", btm, testTime, 4, 0);
|
||||
test_mktime(":Europe/Berlin", btm, testTime, 4, 0);
|
||||
|
||||
tm ctm = {
|
||||
0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET"
|
||||
};
|
||||
test_localtime("CET", testTime, ctm);
|
||||
test_gmtime("CET", testTime, gtm);
|
||||
ctm.tm_wday = -1;
|
||||
ctm.tm_yday = -1;
|
||||
test_mktime("CET", ctm, testTime, 4, 0);
|
||||
|
||||
tm latm = {
|
||||
0, 0, 16, 31, 11, 69, 3, 364, 0, -8 * 3600, (char*)"PST"
|
||||
};
|
||||
test_localtime("America/Los_Angeles", testTime, latm);
|
||||
test_gmtime("America/Los_Angeles", testTime, gtm);
|
||||
test_localtime(":America/Los_Angeles", testTime, latm);
|
||||
test_gmtime(":America/Los_Angeles", testTime, gtm);
|
||||
latm.tm_wday = -1;
|
||||
latm.tm_yday = -1;
|
||||
test_mktime("America/Los_Angeles", latm, testTime, 3, 364);
|
||||
test_mktime(":America/Los_Angeles", latm, testTime, 3, 364);
|
||||
|
||||
tm ttm = {
|
||||
0, 0, 9, 1, 0, 70, 4, 0, 0, 9 * 3600, (char*)"JST"
|
||||
};
|
||||
test_localtime("Asia/Tokyo", testTime, ttm);
|
||||
test_gmtime("Asia/Tokyo", testTime, gtm);
|
||||
test_localtime(":Asia/Tokyo", testTime, ttm);
|
||||
test_gmtime(":Asia/Tokyo", testTime, gtm);
|
||||
ttm.tm_wday = -1;
|
||||
ttm.tm_yday = -1;
|
||||
test_mktime("Asia/Tokyo", ttm, testTime, 4, 0);
|
||||
test_mktime(":Asia/Tokyo", ttm, testTime, 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user