8209167: Use CLDR's time zone mappings for Windows

Reviewed-by: erikj, rriggs, ihse
This commit is contained in:
Naoto Sato 2018-09-13 13:41:17 -07:00
parent 85b57de9ce
commit 009cd15a1b
7 changed files with 176 additions and 289 deletions

View file

@ -36,6 +36,7 @@
#define MAX_ZONE_CHAR 256
#define MAX_MAPID_LENGTH 32
#define MAX_REGION_LENGTH 4
#define NT_TZ_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"
#define WIN_TZ_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones"
@ -145,7 +146,7 @@ static void customZoneName(LONG bias, char *buffer) {
/*
* Gets the current time zone entry in the "Time Zones" registry.
*/
static int getWinTimeZone(char *winZoneName, char *winMapID)
static int getWinTimeZone(char *winZoneName)
{
DYNAMIC_TIME_ZONE_INFORMATION dtzi;
DWORD timeType;
@ -231,7 +232,6 @@ static int getWinTimeZone(char *winZoneName, char *winMapID)
WCHAR stdNameInReg[MAX_ZONE_CHAR];
TziValue tempTzi;
WCHAR *stdNamePtr = tzi.StandardName;
DWORD valueSize;
int onlyMapID;
timeType = GetTimeZoneInformation(&tzi);
@ -372,24 +372,7 @@ static int getWinTimeZone(char *winZoneName, char *winMapID)
(void) RegCloseKey(hSubKey);
}
/*
* Get the "MapID" value of the registry to be able to eliminate
* duplicated key names later.
*/
valueSize = MAX_MAPID_LENGTH;
ret = RegQueryValueExA(hSubKey, "MapID", NULL, &valueType, winMapID, &valueSize);
(void) RegCloseKey(hSubKey);
(void) RegCloseKey(hKey);
if (ret != ERROR_SUCCESS) {
/*
* Vista doesn't have mapID. VALUE_UNKNOWN should be returned
* only for Windows NT.
*/
if (onlyMapID == 1) {
return VALUE_UNKNOWN;
}
}
}
return VALUE_KEY;
@ -410,24 +393,17 @@ static int getWinTimeZone(char *winZoneName, char *winMapID)
* Index values for the mapping table.
*/
#define TZ_WIN_NAME 0
#define TZ_MAPID 1
#define TZ_REGION 2
#define TZ_JAVA_NAME 3
#define TZ_REGION 1
#define TZ_JAVA_NAME 2
#define TZ_NITEMS 4 /* number of items (fields) */
#define TZ_NITEMS 3 /* number of items (fields) */
/*
* Looks up the mapping table (tzmappings) and returns a Java time
* zone ID (e.g., "America/Los_Angeles") if found. Otherwise, NULL is
* returned.
*
* value_type is one of the following values:
* VALUE_KEY for exact key matching
* VALUE_MAPID for MapID (this is
* required for the old Windows, such as NT 4.0 SP3).
*/
static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName,
char *mapID)
static char *matchJavaTZ(const char *java_home_dir, char *tzName)
{
int line;
int IDmatched = 0;
@ -436,9 +412,22 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName
char *items[TZ_NITEMS];
char *mapFileName;
char lineBuffer[MAX_ZONE_CHAR * 4];
int noMapID = *mapID == '\0'; /* no mapID on Vista and later */
int offset = 0;
const char* errorMessage = "unknown error";
char region[MAX_REGION_LENGTH];
// Get the user's location
if (GetGeoInfo(GetUserGeoID(GEOCLASS_NATION),
GEO_ISO2, region, MAX_REGION_LENGTH, 0) == 0) {
// If GetGeoInfo fails, fallback to LCID's country
LCID lcid = GetUserDefaultLCID();
if (GetLocaleInfo(lcid,
LOCALE_SISO3166CTRYNAME, region, MAX_REGION_LENGTH) == 0 &&
GetLocaleInfo(lcid,
LOCALE_SISO3166CTRYNAME2, region, MAX_REGION_LENGTH) == 0) {
region[0] = '\0';
}
}
mapFileName = malloc(strlen(java_home_dir) + strlen(MAPPINGS_FILE) + 1);
if (mapFileName == NULL) {
@ -494,28 +483,20 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName
goto illegal_format;
}
if (noMapID || strcmp(mapID, items[TZ_MAPID]) == 0) {
/*
* We need to scan items until the
* exact match is found or the end of data is detected.
*/
if (strcmp(items[TZ_WIN_NAME], tzName) == 0) {
/*
* When there's no mapID, we need to scan items until the
* exact match is found or the end of data is detected.
* Found the time zone in the mapping table.
* Check the region code and select the appropriate entry
*/
if (!noMapID) {
IDmatched = 1;
}
if (strcmp(items[TZ_WIN_NAME], tzName) == 0) {
/*
* Found the time zone in the mapping table.
*/
if (strcmp(items[TZ_REGION], region) == 0 ||
strcmp(items[TZ_REGION], "001") == 0) {
javaTZName = _strdup(items[TZ_JAVA_NAME]);
break;
}
} else {
if (IDmatched == 1) {
/*
* No need to look up the mapping table further.
*/
break;
}
}
}
fclose(fp);
@ -535,19 +516,16 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName
char *findJavaTZ_md(const char *java_home_dir)
{
char winZoneName[MAX_ZONE_CHAR];
char winMapID[MAX_MAPID_LENGTH];
char *std_timezone = NULL;
int result;
winMapID[0] = 0;
result = getWinTimeZone(winZoneName, winMapID);
result = getWinTimeZone(winZoneName);
if (result != VALUE_UNKNOWN) {
if (result == VALUE_GMTOFFSET) {
std_timezone = _strdup(winZoneName);
} else {
std_timezone = matchJavaTZ(java_home_dir, result,
winZoneName, winMapID);
std_timezone = matchJavaTZ(java_home_dir, winZoneName);
if (std_timezone == NULL) {
std_timezone = getGMTOffsetID();
}