Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[winpr,timezone] refactor timezone mapping
* update windowsZones.xml update url * add option to use ICU as a fallback mapping (eliminate need for WindowsZones mapping list) * extract timezone related settings from localtime_r and eliminate the need to parse the complex TimeZones table * Add new TimeZoneNameMap to map IANA to windows names (Id, Stnadard, Daylight and Display names) * Implement GetDynamicTimeZoneInformation
- Loading branch information
1 parent
f5548cb
commit 4d9ef46
Showing
8 changed files
with
713 additions
and
4,300 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
|
||
#ifndef WINPR_TIME_NAME_MAP_H_ | ||
#define WINPR_TIME_NAME_MAP_H_ | ||
|
||
#include <winpr/wtypes.h> | ||
|
||
typedef enum | ||
{ | ||
TIME_ZONE_NAME_ID, | ||
TIME_ZONE_NAME_STANDARD, | ||
TIME_ZONE_NAME_DISPLAY, | ||
TIME_ZONE_NAME_DAYLIGHT, | ||
TIME_ZONE_NAME_IANA, | ||
} TimeZoneNameType; | ||
|
||
typedef struct | ||
{ | ||
const char* Id; | ||
const char* StandardName; | ||
const char* DisplayName; | ||
const char* DaylightName; | ||
const char* Iana; | ||
} TimeZoneNameMapEntry; | ||
|
||
extern const TimeZoneNameMapEntry TimeZoneNameMap[]; | ||
extern const size_t TimeZoneNameMapSize; | ||
|
||
const char* TimeZoneIanaToWindows(const char* iana, TimeZoneNameType type); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
#include <winpr/config.h> | ||
#include <winpr/assert.h> | ||
#include <winpr/string.h> | ||
|
||
#include <string.h> | ||
|
||
#if defined(WITH_TIMEZONE_ICU) | ||
#include <unicode/ucal.h> | ||
#else | ||
#include "WindowsZones.h" | ||
#endif | ||
|
||
#include "TimeZoneNameMap.h" | ||
|
||
static const char* return_type(const TimeZoneNameMapEntry* entry, TimeZoneNameType type) | ||
{ | ||
WINPR_ASSERT(entry); | ||
switch (type) | ||
{ | ||
case TIME_ZONE_NAME_IANA: | ||
return entry->Iana; | ||
case TIME_ZONE_NAME_ID: | ||
return entry->Id; | ||
case TIME_ZONE_NAME_STANDARD: | ||
return entry->StandardName; | ||
case TIME_ZONE_NAME_DISPLAY: | ||
return entry->DisplayName; | ||
case TIME_ZONE_NAME_DAYLIGHT: | ||
return entry->DaylightName; | ||
default: | ||
return NULL; | ||
} | ||
} | ||
|
||
#if defined(WITH_TIMEZONE_ICU) | ||
static char* get_wzid_icu(const UChar* utzid, size_t utzid_len) | ||
{ | ||
char* res = NULL; | ||
UErrorCode error = U_ZERO_ERROR; | ||
|
||
int32_t rc = ucal_getWindowsTimeZoneID(utzid, utzid_len, NULL, 0, &error); | ||
if ((error == U_BUFFER_OVERFLOW_ERROR) && (rc > 0)) | ||
{ | ||
rc++; // make space for '\0' | ||
UChar* wzid = calloc((size_t)rc + 1, sizeof(UChar)); | ||
if (wzid) | ||
{ | ||
UErrorCode error2 = U_ZERO_ERROR; | ||
int32_t rc2 = ucal_getWindowsTimeZoneID(utzid, utzid_len, wzid, rc, &error2); | ||
if (U_SUCCESS(error2) && (rc2 > 0)) | ||
res = ConvertWCharNToUtf8Alloc(wzid, (size_t)rc, NULL); | ||
free(wzid); | ||
} | ||
} | ||
return res; | ||
} | ||
|
||
static char* get(const char* iana) | ||
{ | ||
size_t utzid_len = 0; | ||
UChar* utzid = ConvertUtf8ToWCharAlloc(iana, &utzid_len); | ||
if (!utzid) | ||
return NULL; | ||
|
||
char* wzid = get_wzid_icu(utzid, utzid_len); | ||
free(utzid); | ||
return wzid; | ||
} | ||
|
||
static const char* map_fallback(const char* iana, TimeZoneNameType type) | ||
{ | ||
const char* res = NULL; | ||
char* wzid = get(iana); | ||
if (!wzid) | ||
return NULL; | ||
|
||
for (size_t x = 0; x < TimeZoneNameMapSize; x++) | ||
{ | ||
const TimeZoneNameMapEntry* entry = &TimeZoneNameMap[x]; | ||
if (strcmp(wzid, entry->Id) == 0) | ||
{ | ||
res = return_type(entry, type); | ||
break; | ||
} | ||
} | ||
|
||
free(wzid); | ||
return res; | ||
} | ||
#else | ||
static const char* map_fallback(const char* iana, TimeZoneNameType type) | ||
{ | ||
if (!iana) | ||
return NULL; | ||
|
||
for (size_t x = 0; x < WindowsTimeZoneIdTableNrElements; x++) | ||
{ | ||
const WINDOWS_TZID_ENTRY* const entry = &WindowsTimeZoneIdTable[x]; | ||
if (strcmp(entry->tzid, iana) == 0) | ||
return entry->windows; | ||
} | ||
|
||
return NULL; | ||
} | ||
#endif | ||
|
||
const char* TimeZoneIanaToWindows(const char* iana, TimeZoneNameType type) | ||
{ | ||
if (!iana) | ||
return NULL; | ||
|
||
for (size_t x = 0; x < TimeZoneNameMapSize; x++) | ||
{ | ||
const TimeZoneNameMapEntry* entry = &TimeZoneNameMap[x]; | ||
if (strcmp(iana, entry->Iana) == 0) | ||
return return_type(entry, type); | ||
} | ||
|
||
const char* wzid = map_fallback(iana, type); | ||
if (!wzid) | ||
return NULL; | ||
|
||
for (size_t x = 0; x < TimeZoneNameMapSize; x++) | ||
{ | ||
const TimeZoneNameMapEntry* entry = &TimeZoneNameMap[x]; | ||
if (strcmp(wzid, entry->Id) == 0) | ||
return return_type(entry, type); | ||
} | ||
return NULL; | ||
} |
Oops, something went wrong.