ICU-6207 Disable getting windows timezone information from static tables. Use resource bundles and TimeZone and Calendar API to get needed timezone information. Create a new file in i18n to allow access to TimeZone and Calendar API. Update subsequent files to use new wintzimpl.h API.

X-SVN-Rev: 24594
This commit is contained in:
Michael Ow 2008-09-18 21:13:52 +00:00
parent e3c2598407
commit eac717e1df
8 changed files with 354 additions and 24 deletions

2
.gitattributes vendored
View File

@ -97,6 +97,8 @@ icu4c/source/i18n/dtitvfmt.cpp -text
icu4c/source/i18n/dtitvinf.cpp -text
icu4c/source/i18n/unicode/dtitvfmt.h -text
icu4c/source/i18n/unicode/dtitvinf.h -text
icu4c/source/i18n/wintzimpl.cpp -text
icu4c/source/i18n/wintzimpl.h -text
icu4c/source/samples/layout/cgnomelayout.c -text
icu4c/source/samples/ucnv/data02.bin -text
icu4c/source/test/compat/tzone.pl -text

View File

@ -19,6 +19,7 @@
#include "cstring.h"
#include "unicode/ustring.h"
#include "unicode/ures.h"
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
@ -28,22 +29,15 @@
# define NOMCX
#include <windows.h>
#if 0
/* Note: The structs and the macro definitions here are deprecated due to the
* new implementation not using any static tables. 9/15/2008 Michael Ow
*/
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
#define NEW_ARRAY(type,count) (type *) uprv_malloc((count) * sizeof(type))
#define DELETE_ARRAY(array) uprv_free((void *) (array))
#define ICUID_STACK_BUFFER_SIZE 32
/* The layout of the Tzi value in the registry */
typedef struct
{
int32_t bias;
int32_t standardBias;
int32_t daylightBias;
SYSTEMTIME standardDate;
SYSTEMTIME daylightDate;
} TZI;
typedef struct
{
const char *icuid;
@ -54,6 +48,17 @@ typedef struct {
const char* winid;
const char* altwinid;
} WindowsZoneRemap;
#endif
/* The layout of the Tzi value in the registry */
typedef struct
{
int32_t bias;
int32_t standardBias;
int32_t daylightBias;
SYSTEMTIME standardDate;
SYSTEMTIME daylightDate;
} TZI;
/**
* Various registry keys and key fragments.
@ -104,6 +109,9 @@ enum {
};
# if 0
/* Note: The static tables here are disabled and deprecated due to the new implementation
* using resource bundles instead. 9/15/2008 Michael Ow
*/
/*
* ZONE_MAP from supplementalData.txt
*/
@ -192,7 +200,6 @@ static const WindowsICUMap NEW_ZONE_MAP[] = {
{"Pacific/Kwajalein", "Dateline"},
{"Pacific/Tongatapu", "Tonga"}
};
#endif
/* NOTE: Some Windows zone ids appear more than once. In such cases the
* ICU zone id from the first one is the preferred match.
@ -586,6 +593,7 @@ static const WindowsZoneRemap ZONE_REMAP[] = {
"Central Standard Time (Mexico)", "+Mexico",
NULL, NULL,
};
#endif
static int32_t gWinType = 0;
@ -616,6 +624,8 @@ static int32_t detectWindowsType()
return winType+1; // +1 to bring it inline with the enum
}
#if 0
/* Note: This is method is deprecated and disabled. See uprv_getWindowsTimeZoneInfo() below. */
/*
* TODO: Binary search sorted ZONE_MAP...
* (u_detectWindowsTimeZone() needs them sorted by offset...)
@ -651,10 +661,11 @@ static const char *findWindowsZoneID(const UChar *icuid, int32_t length)
return result;
}
#endif
static LONG openTZRegKey(HKEY *hkey, const char *winid)
{
char subKeyName[96]; /* TODO: why 96?? */
char subKeyName[110]; /* TODO: why 96?? */
char *name;
LONG result;
@ -672,7 +683,7 @@ static LONG openTZRegKey(HKEY *hkey, const char *winid)
(winid[strlen(winid) - 1] != ')') &&
!(gWinType == WIN_NT_TYPE && strcmp(winid, "GMT") == 0))
{
uprv_strcat(subKeyName, STANDARD_TIME_REGKEY);
/* uprv_strcat(subKeyName, STANDARD_TIME_REGKEY); */
}
result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
@ -680,7 +691,14 @@ static LONG openTZRegKey(HKEY *hkey, const char *winid)
0,
KEY_QUERY_VALUE,
hkey);
return result;
#if 0
/* Note: This portion of the code is deprecated due to the new implementation
* avoiding the use of static tables. Caution should be used in removing this
* code completely because the fallback method being implemented here may be
* actually be needed. Only after thorough testing should this code be removed.
* 9/15/2008 Michael Ow
*/
if (result != ERROR_SUCCESS) {
int i;
@ -700,6 +718,7 @@ static LONG openTZRegKey(HKEY *hkey, const char *winid)
}
}
}
#endif
return result;
}
@ -727,6 +746,8 @@ static LONG getTZI(const char *winid, TZI *tzi)
return result;
}
#if 0
/* This method is deprecated and the new implementation, not using static tables, is in i18n\wintzimpl.h */
U_CAPI UBool U_EXPORT2
uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length)
{
@ -752,6 +773,7 @@ uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid,
return FALSE;
}
#endif
/*
This code attempts to detect the Windows time zone, as set in the
@ -807,13 +829,16 @@ uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid,
*/
U_CFUNC const char* U_EXPORT2
uprv_detectWindowsTimeZone() {
UErrorCode status = U_ZERO_ERROR;
UResourceBundle* supplBundle = NULL;
UResourceBundle* mapTZBundle = NULL;
UResourceBundle* winTZBundle = NULL;
char* icuid = NULL;
LONG result;
HKEY hkey;
TZI tziKey;
TZI tziReg;
TIME_ZONE_INFORMATION apiTZI;
int firstMatch, lastMatch;
int j;
/* Obtain TIME_ZONE_INFORMATION from the API, and then convert it
to TZI. We could also interrogate the registry directly; we do
@ -828,6 +853,54 @@ uprv_detectWindowsTimeZone() {
uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate,
sizeof(apiTZI.DaylightDate));
supplBundle = ures_openDirect(NULL, "supplementalData", &status);
mapTZBundle = ures_getByKey(supplBundle, "mapTimezones", NULL, &status);
winTZBundle = ures_getByKey(mapTZBundle, "windows", NULL, &status);
/* Note: We get the winid not from static tables but from resource bundle. */
while (U_SUCCESS(status) && ures_hasNext(winTZBundle)) {
const char* winid;
int32_t len;
UResourceBundle* winTZ = ures_getNextResource(winTZBundle, NULL, &status);
if (U_FAILURE(status)) {
break;
}
winid = ures_getKey(winTZ);
result = getTZI(winid, &tziReg);
if (result == ERROR_SUCCESS) {
/* Windows alters the DaylightBias in some situations.
Using the bias and the rules suffices, so overwrite
these unreliable fields. */
tziKey.standardBias = tziReg.standardBias;
tziKey.daylightBias = tziReg.daylightBias;
if (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey)) == 0) {
const UChar* icuTZ = ures_getString(winTZ, &len, &status);
if (U_SUCCESS(status)) {
icuid = (char*)uprv_malloc(sizeof(char) * (len + 1));
uprv_memset(icuid, 0, len + 1);
u_austrncpy(icuid, icuTZ, len);
}
}
}
ures_close(winTZ);
if (icuid != NULL) {
break;
}
}
ures_close(winTZBundle);
ures_close(mapTZBundle);
ures_close(supplBundle);
return icuid;
#if 0
/* Note: The following is the original implementation and can be safely removed. 9/15/2008 Michael Ow */
HKEY hkey;
int firstMatch, lastMatch;
int j;
/* For each zone that can be identified by Offset+Rules, see if we
have a match. Continue scanning after finding a match,
recording the index of the first and the last match. We have
@ -836,13 +909,17 @@ uprv_detectWindowsTimeZone() {
firstMatch = -1;
lastMatch = -1;
for (j=0; ZONE_MAP[j].icuid; j++) {
const char* winid;
int32_t len;
winid = ures_getKey(winTZ);
result = getTZI(ZONE_MAP[j].winid, &tziReg);
if (result == ERROR_SUCCESS) {
/* Assume that offsets are grouped together, and bail out
when we've scanned everything with a matching
offset. */
if (firstMatch >= 0 && tziKey.bias != tziReg.bias) {
if ( firstMatch >= 0 && tziKey.bias != tziReg.bias) {
break;
}
@ -928,6 +1005,7 @@ uprv_detectWindowsTimeZone() {
}
return ZONE_MAP[firstMatch].icuid;
#endif
}
#endif /* #ifdef U_WINDOWS */

View File

@ -1,6 +1,6 @@
/*
********************************************************************************
* Copyright (C) 2005-2007, International Business Machines
* Copyright (C) 2005-2008, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@ -26,8 +26,11 @@ U_CDECL_BEGIN
typedef struct _TIME_ZONE_INFORMATION TIME_ZONE_INFORMATION;
U_CDECL_END
#if 0
/* This function is deprecated and is replaced by the function in i18n\wintzimpl.h */
U_CAPI UBool U_EXPORT2
uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length);
#endif
U_CFUNC const char* U_EXPORT2
uprv_detectWindowsTimeZone();

View File

@ -2824,6 +2824,46 @@
<File
RelativePath=".\winnmfmt.h"
>
</File>
<File
RelativePath=".\wintzimpl.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
DisableLanguageExtensions="false"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
DisableLanguageExtensions="false"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
DisableLanguageExtensions="false"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
DisableLanguageExtensions="false"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\wintzimpl.h"
>
</File>
<File
RelativePath=".\zonemeta.cpp"

View File

@ -1,6 +1,6 @@
/*
********************************************************************************
* Copyright (C) 2005-2007, International Business Machines
* Copyright (C) 2005-2008, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@ -31,7 +31,7 @@
#include "cmemory.h"
#include "uresimp.h"
#include "windtfmt.h"
#include "wintz.h"
#include "wintzimpl.h"
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN

View File

@ -0,0 +1,170 @@
/*
********************************************************************************
* Copyright (C) 2008, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
* File WINTZIMPL.CPP
*
********************************************************************************
*/
#include "unicode/utypes.h"
#ifdef U_WINDOWS
#include "wintzimpl.h"
#include "unicode/unistr.h"
#include "unicode/timezone.h"
#include "unicode/basictz.h"
#include "unicode/calendar.h"
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
# define NOUSER
# define NOSERVICE
# define NOIME
# define NOMCX
#include <windows.h>
UBool getSystemTimeInformation(TimeZone *tz, SYSTEMTIME &daylightDate, SYSTEMTIME &standardDate, int32_t &bias, int32_t &daylightBias, int32_t &standardBias) {
UErrorCode status = U_ZERO_ERROR;
UBool result = TRUE;
BasicTimeZone *btz = NULL;
Calendar *cal = NULL;
InitialTimeZoneRule *initial = NULL;
AnnualTimeZoneRule *std = NULL;
AnnualTimeZoneRule *dst = NULL;
UDate currentTime;
int32_t currentYear;
int32_t rawOffset = tz->getRawOffset();
int32_t dstOffset = tz->getDSTSavings();
/* Offset set needs to be normalized so to Windows */
bias = (tz->getRawOffset() * -1)/(60000);
standardBias = 0;
if (tz->useDaylightTime()) {
daylightBias = (tz->getDSTSavings() / 60000) * -1;
} else {
daylightBias = 0;
}
btz = (BasicTimeZone *)tz->clone();
cal = Calendar::createInstance(tz, status);
if (btz != NULL && cal != NULL && U_SUCCESS(status)) {
currentTime = cal->getTime(status);
currentYear = cal->get(UCAL_YEAR, status);
btz->getSimpleRulesNear(currentTime, initial, std, dst, status);
if (U_SUCCESS(status)) {
if (std == NULL || dst == NULL) {
/* Generally, if std is NULL, dst will also be NULL.
* This indicates that daylight saving is not observed
* in this timezone so the standarDate and daylightDate
* should be zero.
*/
standardDate.wYear = standardDate.wMonth = standardDate.wDayOfWeek = standardDate.wDay =
standardDate.wHour = standardDate.wMinute = standardDate.wSecond = standardDate.wMilliseconds = 0;
daylightDate.wYear = daylightDate.wMonth = daylightDate.wDayOfWeek = daylightDate.wDay =
daylightDate.wHour = daylightDate.wMinute = daylightDate.wSecond = daylightDate.wMilliseconds = 0;
} else {
/* Get the UDate value for the start of the timezone standard time and daylight saving time.
* Then set the standardDate and daylightDate to this. The wYear value is 0 to indicate that
* this is not an absolute date but a rule. (e.g. the first Sunday in November)
*/
UDate dateTime;
if (std->getStartInYear(currentYear, rawOffset, 0, dateTime)) {
cal->setTime(dateTime, status);
standardDate.wYear = 0;
standardDate.wMonth = cal->get(UCAL_MONTH, status) + 1;
standardDate.wDayOfWeek = cal->get(UCAL_DAY_OF_WEEK, status) - 1;
standardDate.wDay = cal->get(UCAL_DAY_OF_WEEK_IN_MONTH, status);
standardDate.wHour = cal->get(UCAL_HOUR_OF_DAY, status);
standardDate.wMinute = cal->get(UCAL_MINUTE, status);
standardDate.wSecond = cal->get(UCAL_SECOND, status);
standardDate.wMilliseconds = cal->get(UCAL_MILLISECOND, status);
if (U_SUCCESS(status) && dst->getStartInYear(currentYear, rawOffset, dstOffset, dateTime)) {
cal->setTime(dateTime, status);
daylightDate.wYear = 0;
daylightDate.wMonth = cal->get(UCAL_MONTH, status) + 1;
daylightDate.wDayOfWeek = cal->get(UCAL_DAY_OF_WEEK, status) - 1;
daylightDate.wDay = cal->get(UCAL_DAY_OF_WEEK_IN_MONTH, status);
daylightDate.wHour = cal->get(UCAL_HOUR_OF_DAY, status) + dstOffset/3600000;
daylightDate.wMinute = cal->get(UCAL_MINUTE, status);
daylightDate.wSecond = cal->get(UCAL_SECOND, status);
daylightDate.wMilliseconds = cal->get(UCAL_MILLISECOND, status);
} else {
result = FALSE;
}
} else {
result = FALSE;
}
}
} else {
result = FALSE;
}
} else {
result = FALSE;
}
if (result && U_FAILURE(status)) {
result = FALSE;
}
delete btz;
delete cal;
delete initial;
delete std;
delete dst;
return result;
}
UBool getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length) {
UBool result = FALSE;
UnicodeString id = UnicodeString(icuid, length);
TimeZone *tz = TimeZone::createTimeZone(id);
if (tz != NULL) {
int32_t bias;
int32_t daylightBias;
int32_t standardBias;
SYSTEMTIME daylightDate;
SYSTEMTIME standardDate;
if (!getSystemTimeInformation(tz, daylightDate, standardDate, bias, daylightBias, standardBias)) {
result = FALSE;
} else {
zoneInfo->Bias = bias;
zoneInfo->DaylightBias = daylightBias;
zoneInfo->StandardBias = standardBias;
zoneInfo->DaylightDate = daylightDate;
zoneInfo->StandardDate = standardDate;
result = TRUE;
}
}
return result;
}
/*
* Given the timezone icuid, fill in zoneInfo by calling auxillary functions that creates a timezone and extract the
* information to put into zoneInfo. This includes bias and standard time date and daylight saving date.
*/
U_CAPI UBool U_EXPORT2
uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length)
{
if (getWindowsTimeZoneInfo(zoneInfo, icuid, length)) {
return TRUE;
} else {
return FALSE;
}
}
#endif

View File

@ -0,0 +1,37 @@
/*
********************************************************************************
* Copyright (C) 2008, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
* File WINTZIMPL.H
*
********************************************************************************
*/
#ifndef __WINTZIMPL
#define __WINTZIMPL
#include "unicode/utypes.h"
#ifdef U_WINDOWS
/**
* \file
* \brief C API: Utilities for dealing w/ Windows time zones.
*/
U_CDECL_BEGIN
/* Forward declarations for Windows types... */
typedef struct _TIME_ZONE_INFORMATION TIME_ZONE_INFORMATION;
U_CDECL_END
/*
* This method was moved over from common/wintz.h to allow for access to i18n functions
* needed to get the Windows time zone information without using static tables.
*/
U_CAPI UBool U_EXPORT2
uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length);
#endif /* #ifdef U_WINDOWS */
#endif /* __WINTZIMPL */

View File

@ -1,6 +1,6 @@
/*
********************************************************************************
* Copyright (C) 2005-2006, International Business Machines
* Copyright (C) 2005-2008, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@ -29,7 +29,7 @@
#include "cmemory.h"
#include "cstring.h"
#include "locmap.h"
#include "wintz.h"
#include "wintzimpl.h"
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN