Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
65
third_party/FreeRDP/winpr/libwinpr/timezone/CMakeLists.txt
vendored
Normal file
65
third_party/FreeRDP/winpr/libwinpr/timezone/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-timezone cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
if(${CMAKE_VERSION} GREATER_EQUAL "3.31.0")
|
||||
cmake_policy(SET CMP0177 NEW)
|
||||
endif()
|
||||
|
||||
option(WITH_TIMEZONE_COMPILED "Use compiled in timezone definitions" ON)
|
||||
if(WITH_TIMEZONE_COMPILED)
|
||||
winpr_definition_add(WITH_TIMEZONE_COMPILED)
|
||||
endif()
|
||||
|
||||
include(CMakeDependentOption)
|
||||
cmake_dependent_option(WITH_TIMEZONE_FROM_FILE "Use timezone definitions from JSON file" OFF WITH_WINPR_JSON OFF)
|
||||
if(WITH_TIMEZONE_FROM_FILE)
|
||||
|
||||
winpr_definition_add(WINPR_RESOURCE_ROOT="${WINPR_RESOURCE_ROOT}")
|
||||
winpr_definition_add(WITH_TIMEZONE_FROM_FILE)
|
||||
|
||||
install(FILES TimeZoneNameMap.json DESTINATION ${WINPR_RESOURCE_ROOT})
|
||||
endif()
|
||||
|
||||
set(SRCS TimeZoneNameMapUtils.c TimeZoneNameMap.h timezone.c timezone.h)
|
||||
if(WITH_TIMEZONE_COMPILED)
|
||||
list(APPEND SRCS TimeZoneNameMap_static.h)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
list(APPEND SRCS TimeZoneIanaAbbrevMap.c TimeZoneIanaAbbrevMap.h)
|
||||
endif()
|
||||
|
||||
option(WITH_TIMEZONE_ICU "Use ICU for improved timezone mapping" OFF)
|
||||
if(WITH_TIMEZONE_ICU)
|
||||
find_package(ICU COMPONENTS i18n uc REQUIRED)
|
||||
winpr_pc_add_requires_private("icu-uc")
|
||||
winpr_pc_add_requires_private("icu-i18n")
|
||||
winpr_system_include_directory_add(${ICU_INCLUDE_DIRS})
|
||||
winpr_library_add_private(${ICU_LIBRARIES})
|
||||
winpr_definition_add(WITH_TIMEZONE_ICU)
|
||||
else()
|
||||
list(APPEND SRCS WindowsZones.c WindowsZones.h)
|
||||
endif()
|
||||
|
||||
winpr_module_add(${SRCS})
|
||||
|
||||
if(WIN32)
|
||||
option(WITH_TIMEZONE_UPDATER "Build C# tzextract" OFF)
|
||||
if(WITH_TIMEZONE_UPDATER)
|
||||
add_subdirectory(utils)
|
||||
endif()
|
||||
endif()
|
||||
9
third_party/FreeRDP/winpr/libwinpr/timezone/ModuleOptions.cmake
vendored
Normal file
9
third_party/FreeRDP/winpr/libwinpr/timezone/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
set(MINWIN_LAYER "1")
|
||||
set(MINWIN_GROUP "core")
|
||||
set(MINWIN_MAJOR_VERSION "1")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "timezone")
|
||||
set(MINWIN_LONG_NAME "Time Zone Functions")
|
||||
set(MODULE_LIBRARY_NAME
|
||||
"api-ms-win-${MINWIN_GROUP}-${MINWIN_SHORT_NAME}-l${MINWIN_LAYER}-${MINWIN_MAJOR_VERSION}-${MINWIN_MINOR_VERSION}"
|
||||
)
|
||||
263
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneIanaAbbrevMap.c
vendored
Normal file
263
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneIanaAbbrevMap.c
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Time Zone
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "TimeZoneIanaAbbrevMap.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/synch.h>
|
||||
#include "timezone.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* Iana;
|
||||
char* Abbrev;
|
||||
} TimeZoneInanaAbbrevMapEntry;
|
||||
|
||||
const static char* zonepath = "/usr/share/zoneinfo";
|
||||
|
||||
static TimeZoneInanaAbbrevMapEntry* TimeZoneIanaAbbrevMap = nullptr;
|
||||
static size_t TimeZoneIanaAbbrevMapSize = 0;
|
||||
|
||||
static void append(const char* iana, const char* sname)
|
||||
{
|
||||
const size_t size = TimeZoneIanaAbbrevMapSize + 1;
|
||||
|
||||
TimeZoneInanaAbbrevMapEntry* tmp =
|
||||
realloc(TimeZoneIanaAbbrevMap, size * sizeof(TimeZoneInanaAbbrevMapEntry));
|
||||
if (!tmp)
|
||||
return;
|
||||
TimeZoneIanaAbbrevMap = tmp;
|
||||
TimeZoneIanaAbbrevMapSize = size;
|
||||
|
||||
TimeZoneInanaAbbrevMapEntry* cur = &TimeZoneIanaAbbrevMap[size - 1];
|
||||
cur->Abbrev = _strdup(sname);
|
||||
cur->Iana = _strdup(iana);
|
||||
}
|
||||
|
||||
static void append_timezone(const char* dir, const char* name)
|
||||
{
|
||||
char* tz = nullptr;
|
||||
if (!dir && !name)
|
||||
return;
|
||||
if (!dir)
|
||||
{
|
||||
size_t len = 0;
|
||||
winpr_asprintf(&tz, &len, "%s", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = 0;
|
||||
winpr_asprintf(&tz, &len, "%s/%s", dir, name);
|
||||
}
|
||||
if (!tz)
|
||||
return;
|
||||
|
||||
char* oldtz = setNewAndSaveOldTZ(tz);
|
||||
|
||||
const time_t t = time(nullptr);
|
||||
struct tm lt = WINPR_C_ARRAY_INIT;
|
||||
(void)localtime_r(&t, <);
|
||||
append(tz, lt.tm_zone);
|
||||
restoreSavedTZ(oldtz);
|
||||
free(tz);
|
||||
}
|
||||
|
||||
static void handle_link(const char* base, const char* dir, const char* name);
|
||||
|
||||
static char* topath(const char* base, const char* bname, const char* name)
|
||||
{
|
||||
size_t plen = 0;
|
||||
char* path = nullptr;
|
||||
|
||||
if (!base && !bname && !name)
|
||||
return nullptr;
|
||||
|
||||
if (!base && !name)
|
||||
return _strdup(bname);
|
||||
|
||||
if (!bname && !name)
|
||||
return _strdup(base);
|
||||
|
||||
if (!base && !bname)
|
||||
return _strdup(name);
|
||||
|
||||
if (!base)
|
||||
winpr_asprintf(&path, &plen, "%s/%s", bname, name);
|
||||
else if (!bname)
|
||||
winpr_asprintf(&path, &plen, "%s/%s", base, name);
|
||||
else if (!name)
|
||||
winpr_asprintf(&path, &plen, "%s/%s", base, bname);
|
||||
else
|
||||
winpr_asprintf(&path, &plen, "%s/%s/%s", base, bname, name);
|
||||
return path;
|
||||
}
|
||||
|
||||
static void iterate_subdir_recursive(const char* base, const char* bname, const char* name)
|
||||
{
|
||||
char* path = topath(base, bname, name);
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
DIR* d = opendir(path);
|
||||
if (d)
|
||||
{
|
||||
struct dirent* dp = nullptr;
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
while ((dp = readdir(d)) != nullptr)
|
||||
{
|
||||
switch (dp->d_type)
|
||||
{
|
||||
case DT_DIR:
|
||||
{
|
||||
if (strcmp(dp->d_name, ".") == 0)
|
||||
continue;
|
||||
if (strcmp(dp->d_name, "..") == 0)
|
||||
continue;
|
||||
iterate_subdir_recursive(path, dp->d_name, nullptr);
|
||||
}
|
||||
break;
|
||||
case DT_LNK:
|
||||
handle_link(base, bname, dp->d_name);
|
||||
break;
|
||||
case DT_REG:
|
||||
append_timezone(bname, dp->d_name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
|
||||
static char* get_link_target(const char* base, const char* dir, const char* name)
|
||||
{
|
||||
char* apath = nullptr;
|
||||
char* path = topath(base, dir, name);
|
||||
if (!path)
|
||||
return nullptr;
|
||||
|
||||
SSIZE_T rc = -1;
|
||||
size_t size = 0;
|
||||
char* target = nullptr;
|
||||
do
|
||||
{
|
||||
size += 64;
|
||||
char* tmp = realloc(target, size + 1);
|
||||
if (!tmp)
|
||||
goto fail;
|
||||
|
||||
target = tmp;
|
||||
|
||||
memset(target, 0, size + 1);
|
||||
rc = readlink(path, target, size);
|
||||
if (rc < 0)
|
||||
goto fail;
|
||||
} while ((size_t)rc >= size);
|
||||
|
||||
apath = topath(base, dir, target);
|
||||
fail:
|
||||
free(target);
|
||||
free(path);
|
||||
return apath;
|
||||
}
|
||||
|
||||
void handle_link(const char* base, const char* dir, const char* name)
|
||||
{
|
||||
int isDir = -1;
|
||||
|
||||
char* target = get_link_target(base, dir, name);
|
||||
if (target)
|
||||
{
|
||||
struct stat s = WINPR_C_ARRAY_INIT;
|
||||
const int rc3 = stat(target, &s);
|
||||
if (rc3 == 0)
|
||||
isDir = S_ISDIR(s.st_mode);
|
||||
|
||||
free(target);
|
||||
}
|
||||
|
||||
switch (isDir)
|
||||
{
|
||||
case 1:
|
||||
iterate_subdir_recursive(base, dir, name);
|
||||
break;
|
||||
case 0:
|
||||
append_timezone(dir, name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void TimeZoneIanaAbbrevCleanup(void)
|
||||
{
|
||||
if (!TimeZoneIanaAbbrevMap)
|
||||
return;
|
||||
|
||||
for (size_t x = 0; x < TimeZoneIanaAbbrevMapSize; x++)
|
||||
{
|
||||
TimeZoneInanaAbbrevMapEntry* entry = &TimeZoneIanaAbbrevMap[x];
|
||||
free(entry->Iana);
|
||||
free(entry->Abbrev);
|
||||
}
|
||||
free(TimeZoneIanaAbbrevMap);
|
||||
TimeZoneIanaAbbrevMap = nullptr;
|
||||
TimeZoneIanaAbbrevMapSize = 0;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK TimeZoneIanaAbbrevInitialize(WINPR_ATTR_UNUSED PINIT_ONCE once,
|
||||
WINPR_ATTR_UNUSED PVOID param,
|
||||
WINPR_ATTR_UNUSED PVOID* context)
|
||||
{
|
||||
iterate_subdir_recursive(zonepath, nullptr, nullptr);
|
||||
(void)atexit(TimeZoneIanaAbbrevCleanup);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t TimeZoneIanaAbbrevGet(const char* abbrev, const char** list, size_t listsize)
|
||||
{
|
||||
static INIT_ONCE init_guard = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
if (!InitOnceExecuteOnce(&init_guard, TimeZoneIanaAbbrevInitialize, nullptr, nullptr))
|
||||
return 0;
|
||||
|
||||
size_t rc = 0;
|
||||
for (size_t x = 0; x < TimeZoneIanaAbbrevMapSize; x++)
|
||||
{
|
||||
const TimeZoneInanaAbbrevMapEntry* entry = &TimeZoneIanaAbbrevMap[x];
|
||||
if (strcmp(abbrev, entry->Abbrev) == 0)
|
||||
{
|
||||
if (listsize > rc)
|
||||
list[rc] = entry->Iana;
|
||||
rc++;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
36
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneIanaAbbrevMap.h
vendored
Normal file
36
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneIanaAbbrevMap.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Time Zone
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WINPR_TIMEZONE_IANA_ABBREV
|
||||
#define WINPR_TIMEZONE_IANA_ABBREV
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
/**! \brief returns a list of IANA names for a short timezone name
|
||||
*
|
||||
* \param abbrev The short name to look for
|
||||
* \param list The list to hold the const IANA names
|
||||
* \param listsize The size of the \b list. Set to 0 to only get the required size.
|
||||
*
|
||||
* \return The number of mappings found
|
||||
*/
|
||||
size_t TimeZoneIanaAbbrevGet(const char* abbrev, const char** list, size_t listsize);
|
||||
|
||||
#endif
|
||||
47
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneNameMap.h
vendored
Normal file
47
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneNameMap.h
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Time Zone Name Map
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#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
|
||||
{
|
||||
char* Id;
|
||||
char* StandardName;
|
||||
char* DisplayName;
|
||||
char* DaylightName;
|
||||
char* Iana;
|
||||
} TimeZoneNameMapEntry;
|
||||
|
||||
const TimeZoneNameMapEntry* TimeZoneGetAt(size_t index);
|
||||
const char* TimeZoneIanaToWindows(const char* iana, TimeZoneNameType type);
|
||||
|
||||
#endif
|
||||
991
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneNameMap.json
vendored
Normal file
991
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneNameMap.json
vendored
Normal file
@@ -0,0 +1,991 @@
|
||||
{
|
||||
"TimeZoneNameMap": [
|
||||
{
|
||||
"Id": "Dateline Standard Time",
|
||||
"StandardName": "Dateline Standard Time",
|
||||
"DisplayName": "(UTC-12:00) International Date Line West",
|
||||
"DaylightName": "Dateline Daylight Time",
|
||||
"Iana": "Etc/GMT+12"
|
||||
},
|
||||
{
|
||||
"Id": "UTC-11",
|
||||
"StandardName": "UTC-11",
|
||||
"DisplayName": "(UTC-11:00) Coordinated Universal Time-11",
|
||||
"DaylightName": "UTC-11",
|
||||
"Iana": "Etc/GMT+11"
|
||||
},
|
||||
{
|
||||
"Id": "Aleutian Standard Time",
|
||||
"StandardName": "Aleutian Standard Time",
|
||||
"DisplayName": "(UTC-10:00) Aleutian Islands",
|
||||
"DaylightName": "Aleutian Daylight Time",
|
||||
"Iana": "America/Adak"
|
||||
},
|
||||
{
|
||||
"Id": "Hawaiian Standard Time",
|
||||
"StandardName": "Hawaiian Standard Time",
|
||||
"DisplayName": "(UTC-10:00) Hawaii",
|
||||
"DaylightName": "Hawaiian Daylight Time",
|
||||
"Iana": "Pacific/Honolulu"
|
||||
},
|
||||
{
|
||||
"Id": "Marquesas Standard Time",
|
||||
"StandardName": "Marquesas Standard Time",
|
||||
"DisplayName": "(UTC-09:30) Marquesas Islands",
|
||||
"DaylightName": "Marquesas Daylight Time",
|
||||
"Iana": "Pacific/Marquesas"
|
||||
},
|
||||
{
|
||||
"Id": "Alaskan Standard Time",
|
||||
"StandardName": "Alaskan Standard Time",
|
||||
"DisplayName": "(UTC-09:00) Alaska",
|
||||
"DaylightName": "Alaskan Daylight Time",
|
||||
"Iana": "America/Anchorage"
|
||||
},
|
||||
{
|
||||
"Id": "UTC-09",
|
||||
"StandardName": "UTC-09",
|
||||
"DisplayName": "(UTC-09:00) Coordinated Universal Time-09",
|
||||
"DaylightName": "UTC-09",
|
||||
"Iana": "Etc/GMT+9"
|
||||
},
|
||||
{
|
||||
"Id": "Pacific Standard Time (Mexico)",
|
||||
"StandardName": "Pacific Standard Time (Mexico)",
|
||||
"DisplayName": "(UTC-08:00) Baja California",
|
||||
"DaylightName": "Pacific Daylight Time (Mexico)",
|
||||
"Iana": "America/Tijuana"
|
||||
},
|
||||
{
|
||||
"Id": "UTC-08",
|
||||
"StandardName": "UTC-08",
|
||||
"DisplayName": "(UTC-08:00) Coordinated Universal Time-08",
|
||||
"DaylightName": "UTC-08",
|
||||
"Iana": "Etc/GMT+8"
|
||||
},
|
||||
{
|
||||
"Id": "Pacific Standard Time",
|
||||
"StandardName": "Pacific Standard Time",
|
||||
"DisplayName": "(UTC-08:00) Pacific Time (US & Canada)",
|
||||
"DaylightName": "Pacific Daylight Time",
|
||||
"Iana": "America/Los_Angeles"
|
||||
},
|
||||
{
|
||||
"Id": "US Mountain Standard Time",
|
||||
"StandardName": "US Mountain Standard Time",
|
||||
"DisplayName": "(UTC-07:00) Arizona",
|
||||
"DaylightName": "US Mountain Daylight Time",
|
||||
"Iana": "America/Phoenix"
|
||||
},
|
||||
{
|
||||
"Id": "Mountain Standard Time (Mexico)",
|
||||
"StandardName": "Mountain Standard Time (Mexico)",
|
||||
"DisplayName": "(UTC-07:00) La Paz, Mazatlan",
|
||||
"DaylightName": "Mountain Daylight Time (Mexico)",
|
||||
"Iana": "America/Chihuahua"
|
||||
},
|
||||
{
|
||||
"Id": "Mountain Standard Time",
|
||||
"StandardName": "Mountain Standard Time",
|
||||
"DisplayName": "(UTC-07:00) Mountain Time (US & Canada)",
|
||||
"DaylightName": "Mountain Daylight Time",
|
||||
"Iana": "America/Denver"
|
||||
},
|
||||
{
|
||||
"Id": "Yukon Standard Time",
|
||||
"StandardName": "Yukon Standard Time",
|
||||
"DisplayName": "(UTC-07:00) Yukon",
|
||||
"DaylightName": "Yukon Daylight Time",
|
||||
"Iana": "America/Whitehorse"
|
||||
},
|
||||
{
|
||||
"Id": "Central America Standard Time",
|
||||
"StandardName": "Central America Standard Time",
|
||||
"DisplayName": "(UTC-06:00) Central America",
|
||||
"DaylightName": "Central America Daylight Time",
|
||||
"Iana": "America/Guatemala"
|
||||
},
|
||||
{
|
||||
"Id": "Central Standard Time",
|
||||
"StandardName": "Central Standard Time",
|
||||
"DisplayName": "(UTC-06:00) Central Time (US & Canada)",
|
||||
"DaylightName": "Central Daylight Time",
|
||||
"Iana": "America/Chicago"
|
||||
},
|
||||
{
|
||||
"Id": "Easter Island Standard Time",
|
||||
"StandardName": "Easter Island Standard Time",
|
||||
"DisplayName": "(UTC-06:00) Easter Island",
|
||||
"DaylightName": "Easter Island Daylight Time",
|
||||
"Iana": "Pacific/Easter"
|
||||
},
|
||||
{
|
||||
"Id": "Central Standard Time (Mexico)",
|
||||
"StandardName": "Central Standard Time (Mexico)",
|
||||
"DisplayName": "(UTC-06:00) Guadalajara, Mexico City, Monterrey",
|
||||
"DaylightName": "Central Daylight Time (Mexico)",
|
||||
"Iana": "America/Mexico_City"
|
||||
},
|
||||
{
|
||||
"Id": "Canada Central Standard Time",
|
||||
"StandardName": "Canada Central Standard Time",
|
||||
"DisplayName": "(UTC-06:00) Saskatchewan",
|
||||
"DaylightName": "Canada Central Daylight Time",
|
||||
"Iana": "America/Regina"
|
||||
},
|
||||
{
|
||||
"Id": "SA Pacific Standard Time",
|
||||
"StandardName": "SA Pacific Standard Time",
|
||||
"DisplayName": "(UTC-05:00) Bogota, Lima, Quito, Rio Branco",
|
||||
"DaylightName": "SA Pacific Daylight Time",
|
||||
"Iana": "America/Bogota"
|
||||
},
|
||||
{
|
||||
"Id": "Eastern Standard Time (Mexico)",
|
||||
"StandardName": "Eastern Standard Time (Mexico)",
|
||||
"DisplayName": "(UTC-05:00) Chetumal",
|
||||
"DaylightName": "Eastern Daylight Time (Mexico)",
|
||||
"Iana": "America/Cancun"
|
||||
},
|
||||
{
|
||||
"Id": "Eastern Standard Time",
|
||||
"StandardName": "Eastern Standard Time",
|
||||
"DisplayName": "(UTC-05:00) Eastern Time (US & Canada)",
|
||||
"DaylightName": "Eastern Daylight Time",
|
||||
"Iana": "America/New_York"
|
||||
},
|
||||
{
|
||||
"Id": "Haiti Standard Time",
|
||||
"StandardName": "Haiti Standard Time",
|
||||
"DisplayName": "(UTC-05:00) Haiti",
|
||||
"DaylightName": "Haiti Daylight Time",
|
||||
"Iana": "America/Port-au-Prince"
|
||||
},
|
||||
{
|
||||
"Id": "Cuba Standard Time",
|
||||
"StandardName": "Cuba Standard Time",
|
||||
"DisplayName": "(UTC-05:00) Havana",
|
||||
"DaylightName": "Cuba Daylight Time",
|
||||
"Iana": "America/Havana"
|
||||
},
|
||||
{
|
||||
"Id": "US Eastern Standard Time",
|
||||
"StandardName": "US Eastern Standard Time",
|
||||
"DisplayName": "(UTC-05:00) Indiana (East)",
|
||||
"DaylightName": "US Eastern Daylight Time",
|
||||
"Iana": "America/Indianapolis"
|
||||
},
|
||||
{
|
||||
"Id": "Turks And Caicos Standard Time",
|
||||
"StandardName": "Turks and Caicos Standard Time",
|
||||
"DisplayName": "(UTC-05:00) Turks and Caicos",
|
||||
"DaylightName": "Turks and Caicos Daylight Time",
|
||||
"Iana": "America/Grand_Turk"
|
||||
},
|
||||
{
|
||||
"Id": "Atlantic Standard Time",
|
||||
"StandardName": "Atlantic Standard Time",
|
||||
"DisplayName": "(UTC-04:00) Atlantic Time (Canada)",
|
||||
"DaylightName": "Atlantic Daylight Time",
|
||||
"Iana": "America/Halifax"
|
||||
},
|
||||
{
|
||||
"Id": "Venezuela Standard Time",
|
||||
"StandardName": "Venezuela Standard Time",
|
||||
"DisplayName": "(UTC-04:00) Caracas",
|
||||
"DaylightName": "Venezuela Daylight Time",
|
||||
"Iana": "America/Caracas"
|
||||
},
|
||||
{
|
||||
"Id": "Central Brazilian Standard Time",
|
||||
"StandardName": "Central Brazilian Standard Time",
|
||||
"DisplayName": "(UTC-04:00) Cuiaba",
|
||||
"DaylightName": "Central Brazilian Daylight Time",
|
||||
"Iana": "America/Cuiaba"
|
||||
},
|
||||
{
|
||||
"Id": "SA Western Standard Time",
|
||||
"StandardName": "SA Western Standard Time",
|
||||
"DisplayName": "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan",
|
||||
"DaylightName": "SA Western Daylight Time",
|
||||
"Iana": "America/La_Paz"
|
||||
},
|
||||
{
|
||||
"Id": "Pacific SA Standard Time",
|
||||
"StandardName": "Pacific SA Standard Time",
|
||||
"DisplayName": "(UTC-04:00) Santiago",
|
||||
"DaylightName": "Pacific SA Daylight Time",
|
||||
"Iana": "America/Santiago"
|
||||
},
|
||||
{
|
||||
"Id": "Newfoundland Standard Time",
|
||||
"StandardName": "Newfoundland Standard Time",
|
||||
"DisplayName": "(UTC-03:30) Newfoundland",
|
||||
"DaylightName": "Newfoundland Daylight Time",
|
||||
"Iana": "America/St_Johns"
|
||||
},
|
||||
{
|
||||
"Id": "Tocantins Standard Time",
|
||||
"StandardName": "Tocantins Standard Time",
|
||||
"DisplayName": "(UTC-03:00) Araguaina",
|
||||
"DaylightName": "Tocantins Daylight Time",
|
||||
"Iana": "America/Araguaina"
|
||||
},
|
||||
{
|
||||
"Id": "Paraguay Standard Time",
|
||||
"StandardName": "Paraguay Standard Time",
|
||||
"DisplayName": "(UTC-03:00) Asuncion",
|
||||
"DaylightName": "Paraguay Daylight Time",
|
||||
"Iana": "America/Asuncion"
|
||||
},
|
||||
{
|
||||
"Id": "E. South America Standard Time",
|
||||
"StandardName": "E. South America Standard Time",
|
||||
"DisplayName": "(UTC-03:00) Brasilia",
|
||||
"DaylightName": "E. South America Daylight Time",
|
||||
"Iana": "America/Sao_Paulo"
|
||||
},
|
||||
{
|
||||
"Id": "SA Eastern Standard Time",
|
||||
"StandardName": "SA Eastern Standard Time",
|
||||
"DisplayName": "(UTC-03:00) Cayenne, Fortaleza",
|
||||
"DaylightName": "SA Eastern Daylight Time",
|
||||
"Iana": "America/Cayenne"
|
||||
},
|
||||
{
|
||||
"Id": "Argentina Standard Time",
|
||||
"StandardName": "Argentina Standard Time",
|
||||
"DisplayName": "(UTC-03:00) City of Buenos Aires",
|
||||
"DaylightName": "Argentina Daylight Time",
|
||||
"Iana": "America/Buenos_Aires"
|
||||
},
|
||||
{
|
||||
"Id": "Montevideo Standard Time",
|
||||
"StandardName": "Montevideo Standard Time",
|
||||
"DisplayName": "(UTC-03:00) Montevideo",
|
||||
"DaylightName": "Montevideo Daylight Time",
|
||||
"Iana": "America/Montevideo"
|
||||
},
|
||||
{
|
||||
"Id": "Magallanes Standard Time",
|
||||
"StandardName": "Magallanes Standard Time",
|
||||
"DisplayName": "(UTC-03:00) Punta Arenas",
|
||||
"DaylightName": "Magallanes Daylight Time",
|
||||
"Iana": "America/Punta_Arenas"
|
||||
},
|
||||
{
|
||||
"Id": "Saint Pierre Standard Time",
|
||||
"StandardName": "Saint Pierre Standard Time",
|
||||
"DisplayName": "(UTC-03:00) Saint Pierre and Miquelon",
|
||||
"DaylightName": "Saint Pierre Daylight Time",
|
||||
"Iana": "America/Miquelon"
|
||||
},
|
||||
{
|
||||
"Id": "Bahia Standard Time",
|
||||
"StandardName": "Bahia Standard Time",
|
||||
"DisplayName": "(UTC-03:00) Salvador",
|
||||
"DaylightName": "Bahia Daylight Time",
|
||||
"Iana": "America/Bahia"
|
||||
},
|
||||
{
|
||||
"Id": "UTC-02",
|
||||
"StandardName": "UTC-02",
|
||||
"DisplayName": "(UTC-02:00) Coordinated Universal Time-02",
|
||||
"DaylightName": "UTC-02",
|
||||
"Iana": "Etc/GMT+2"
|
||||
},
|
||||
{
|
||||
"Id": "Greenland Standard Time",
|
||||
"StandardName": "Greenland Standard Time",
|
||||
"DisplayName": "(UTC-02:00) Greenland",
|
||||
"DaylightName": "Greenland Daylight Time",
|
||||
"Iana": "America/Godthab"
|
||||
},
|
||||
{
|
||||
"Id": "Mid-Atlantic Standard Time",
|
||||
"StandardName": "Mid-Atlantic Standard Time",
|
||||
"DisplayName": "(UTC-02:00) Mid-Atlantic - Old",
|
||||
"DaylightName": "Mid-Atlantic Daylight Time",
|
||||
"Iana": ""
|
||||
},
|
||||
{
|
||||
"Id": "Azores Standard Time",
|
||||
"StandardName": "Azores Standard Time",
|
||||
"DisplayName": "(UTC-01:00) Azores",
|
||||
"DaylightName": "Azores Daylight Time",
|
||||
"Iana": "Atlantic/Azores"
|
||||
},
|
||||
{
|
||||
"Id": "Cape Verde Standard Time",
|
||||
"StandardName": "Cabo Verde Standard Time",
|
||||
"DisplayName": "(UTC-01:00) Cabo Verde Is.",
|
||||
"DaylightName": "Cabo Verde Daylight Time",
|
||||
"Iana": "Atlantic/Cape_Verde"
|
||||
},
|
||||
{
|
||||
"Id": "UTC",
|
||||
"StandardName": "Coordinated Universal Time",
|
||||
"DisplayName": "(UTC) Coordinated Universal Time",
|
||||
"DaylightName": "Coordinated Universal Time",
|
||||
"Iana": "Etc/UTC"
|
||||
},
|
||||
{
|
||||
"Id": "GMT Standard Time",
|
||||
"StandardName": "GMT Standard Time",
|
||||
"DisplayName": "(UTC+00:00) Dublin, Edinburgh, Lisbon, London",
|
||||
"DaylightName": "GMT Daylight Time",
|
||||
"Iana": "Europe/London"
|
||||
},
|
||||
{
|
||||
"Id": "Greenwich Standard Time",
|
||||
"StandardName": "Greenwich Standard Time",
|
||||
"DisplayName": "(UTC+00:00) Monrovia, Reykjavik",
|
||||
"DaylightName": "Greenwich Daylight Time",
|
||||
"Iana": "Atlantic/Reykjavik"
|
||||
},
|
||||
{
|
||||
"Id": "Sao Tome Standard Time",
|
||||
"StandardName": "Sao Tome Standard Time",
|
||||
"DisplayName": "(UTC+00:00) Sao Tome",
|
||||
"DaylightName": "Sao Tome Daylight Time",
|
||||
"Iana": "Africa/Sao_Tome"
|
||||
},
|
||||
{
|
||||
"Id": "Morocco Standard Time",
|
||||
"StandardName": "Morocco Standard Time",
|
||||
"DisplayName": "(UTC+01:00) Casablanca",
|
||||
"DaylightName": "Morocco Daylight Time",
|
||||
"Iana": "Africa/Casablanca"
|
||||
},
|
||||
{
|
||||
"Id": "W. Europe Standard Time",
|
||||
"StandardName": "W. Europe Standard Time",
|
||||
"DisplayName": "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna",
|
||||
"DaylightName": "W. Europe Daylight Time",
|
||||
"Iana": "Europe/Berlin"
|
||||
},
|
||||
{
|
||||
"Id": "Central Europe Standard Time",
|
||||
"StandardName": "Central Europe Standard Time",
|
||||
"DisplayName": "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague",
|
||||
"DaylightName": "Central Europe Daylight Time",
|
||||
"Iana": "Europe/Budapest"
|
||||
},
|
||||
{
|
||||
"Id": "Romance Standard Time",
|
||||
"StandardName": "Romance Standard Time",
|
||||
"DisplayName": "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris",
|
||||
"DaylightName": "Romance Daylight Time",
|
||||
"Iana": "Europe/Paris"
|
||||
},
|
||||
{
|
||||
"Id": "Central European Standard Time",
|
||||
"StandardName": "Central European Standard Time",
|
||||
"DisplayName": "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb",
|
||||
"DaylightName": "Central European Daylight Time",
|
||||
"Iana": "Europe/Warsaw"
|
||||
},
|
||||
{
|
||||
"Id": "W. Central Africa Standard Time",
|
||||
"StandardName": "W. Central Africa Standard Time",
|
||||
"DisplayName": "(UTC+01:00) West Central Africa",
|
||||
"DaylightName": "W. Central Africa Daylight Time",
|
||||
"Iana": "Africa/Lagos"
|
||||
},
|
||||
{
|
||||
"Id": "GTB Standard Time",
|
||||
"StandardName": "GTB Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Athens, Bucharest",
|
||||
"DaylightName": "GTB Daylight Time",
|
||||
"Iana": "Europe/Bucharest"
|
||||
},
|
||||
{
|
||||
"Id": "Middle East Standard Time",
|
||||
"StandardName": "Middle East Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Beirut",
|
||||
"DaylightName": "Middle East Daylight Time",
|
||||
"Iana": "Asia/Beirut"
|
||||
},
|
||||
{
|
||||
"Id": "Egypt Standard Time",
|
||||
"StandardName": "Egypt Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Cairo",
|
||||
"DaylightName": "Egypt Daylight Time",
|
||||
"Iana": "Africa/Cairo"
|
||||
},
|
||||
{
|
||||
"Id": "E. Europe Standard Time",
|
||||
"StandardName": "E. Europe Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Chisinau",
|
||||
"DaylightName": "E. Europe Daylight Time",
|
||||
"Iana": "Europe/Chisinau"
|
||||
},
|
||||
{
|
||||
"Id": "West Bank Standard Time",
|
||||
"StandardName": "West Bank Gaza Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Gaza, Hebron",
|
||||
"DaylightName": "West Bank Gaza Daylight Time",
|
||||
"Iana": "Asia/Hebron"
|
||||
},
|
||||
{
|
||||
"Id": "South Africa Standard Time",
|
||||
"StandardName": "South Africa Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Harare, Pretoria",
|
||||
"DaylightName": "South Africa Daylight Time",
|
||||
"Iana": "Africa/Johannesburg"
|
||||
},
|
||||
{
|
||||
"Id": "FLE Standard Time",
|
||||
"StandardName": "FLE Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius",
|
||||
"DaylightName": "FLE Daylight Time",
|
||||
"Iana": "Europe/Kiev"
|
||||
},
|
||||
{
|
||||
"Id": "Israel Standard Time",
|
||||
"StandardName": "Jerusalem Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Jerusalem",
|
||||
"DaylightName": "Jerusalem Daylight Time",
|
||||
"Iana": "Asia/Jerusalem"
|
||||
},
|
||||
{
|
||||
"Id": "South Sudan Standard Time",
|
||||
"StandardName": "South Sudan Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Juba",
|
||||
"DaylightName": "South Sudan Daylight Time",
|
||||
"Iana": "Africa/Juba"
|
||||
},
|
||||
{
|
||||
"Id": "Kaliningrad Standard Time",
|
||||
"StandardName": "Russia TZ 1 Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Kaliningrad",
|
||||
"DaylightName": "Russia TZ 1 Daylight Time",
|
||||
"Iana": "Europe/Kaliningrad"
|
||||
},
|
||||
{
|
||||
"Id": "Sudan Standard Time",
|
||||
"StandardName": "Sudan Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Khartoum",
|
||||
"DaylightName": "Sudan Daylight Time",
|
||||
"Iana": "Africa/Khartoum"
|
||||
},
|
||||
{
|
||||
"Id": "Libya Standard Time",
|
||||
"StandardName": "Libya Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Tripoli",
|
||||
"DaylightName": "Libya Daylight Time",
|
||||
"Iana": "Africa/Tripoli"
|
||||
},
|
||||
{
|
||||
"Id": "Namibia Standard Time",
|
||||
"StandardName": "Namibia Standard Time",
|
||||
"DisplayName": "(UTC+02:00) Windhoek",
|
||||
"DaylightName": "Namibia Daylight Time",
|
||||
"Iana": "Africa/Windhoek"
|
||||
},
|
||||
{
|
||||
"Id": "Jordan Standard Time",
|
||||
"StandardName": "Jordan Standard Time",
|
||||
"DisplayName": "(UTC+03:00) Amman",
|
||||
"DaylightName": "Jordan Daylight Time",
|
||||
"Iana": "Asia/Amman"
|
||||
},
|
||||
{
|
||||
"Id": "Arabic Standard Time",
|
||||
"StandardName": "Arabic Standard Time",
|
||||
"DisplayName": "(UTC+03:00) Baghdad",
|
||||
"DaylightName": "Arabic Daylight Time",
|
||||
"Iana": "Asia/Baghdad"
|
||||
},
|
||||
{
|
||||
"Id": "Syria Standard Time",
|
||||
"StandardName": "Syria Standard Time",
|
||||
"DisplayName": "(UTC+03:00) Damascus",
|
||||
"DaylightName": "Syria Daylight Time",
|
||||
"Iana": "Asia/Damascus"
|
||||
},
|
||||
{
|
||||
"Id": "Turkey Standard Time",
|
||||
"StandardName": "Turkey Standard Time",
|
||||
"DisplayName": "(UTC+03:00) Istanbul",
|
||||
"DaylightName": "Turkey Daylight Time",
|
||||
"Iana": "Europe/Istanbul"
|
||||
},
|
||||
{
|
||||
"Id": "Arab Standard Time",
|
||||
"StandardName": "Arab Standard Time",
|
||||
"DisplayName": "(UTC+03:00) Kuwait, Riyadh",
|
||||
"DaylightName": "Arab Daylight Time",
|
||||
"Iana": "Asia/Riyadh"
|
||||
},
|
||||
{
|
||||
"Id": "Belarus Standard Time",
|
||||
"StandardName": "Belarus Standard Time",
|
||||
"DisplayName": "(UTC+03:00) Minsk",
|
||||
"DaylightName": "Belarus Daylight Time",
|
||||
"Iana": "Europe/Minsk"
|
||||
},
|
||||
{
|
||||
"Id": "Russian Standard Time",
|
||||
"StandardName": "Russia TZ 2 Standard Time",
|
||||
"DisplayName": "(UTC+03:00) Moscow, St. Petersburg",
|
||||
"DaylightName": "Russia TZ 2 Daylight Time",
|
||||
"Iana": "Europe/Moscow"
|
||||
},
|
||||
{
|
||||
"Id": "E. Africa Standard Time",
|
||||
"StandardName": "E. Africa Standard Time",
|
||||
"DisplayName": "(UTC+03:00) Nairobi",
|
||||
"DaylightName": "E. Africa Daylight Time",
|
||||
"Iana": "Africa/Nairobi"
|
||||
},
|
||||
{
|
||||
"Id": "Volgograd Standard Time",
|
||||
"StandardName": "Volgograd Standard Time",
|
||||
"DisplayName": "(UTC+03:00) Volgograd",
|
||||
"DaylightName": "Volgograd Daylight Time",
|
||||
"Iana": "Europe/Volgograd"
|
||||
},
|
||||
{
|
||||
"Id": "Iran Standard Time",
|
||||
"StandardName": "Iran Standard Time",
|
||||
"DisplayName": "(UTC+03:30) Tehran",
|
||||
"DaylightName": "Iran Daylight Time",
|
||||
"Iana": "Asia/Tehran"
|
||||
},
|
||||
{
|
||||
"Id": "Arabian Standard Time",
|
||||
"StandardName": "Arabian Standard Time",
|
||||
"DisplayName": "(UTC+04:00) Abu Dhabi, Muscat",
|
||||
"DaylightName": "Arabian Daylight Time",
|
||||
"Iana": "Asia/Dubai"
|
||||
},
|
||||
{
|
||||
"Id": "Astrakhan Standard Time",
|
||||
"StandardName": "Astrakhan Standard Time",
|
||||
"DisplayName": "(UTC+04:00) Astrakhan, Ulyanovsk",
|
||||
"DaylightName": "Astrakhan Daylight Time",
|
||||
"Iana": "Europe/Astrakhan"
|
||||
},
|
||||
{
|
||||
"Id": "Azerbaijan Standard Time",
|
||||
"StandardName": "Azerbaijan Standard Time",
|
||||
"DisplayName": "(UTC+04:00) Baku",
|
||||
"DaylightName": "Azerbaijan Daylight Time",
|
||||
"Iana": "Asia/Baku"
|
||||
},
|
||||
{
|
||||
"Id": "Russia Time Zone 3",
|
||||
"StandardName": "Russia TZ 3 Standard Time",
|
||||
"DisplayName": "(UTC+04:00) Izhevsk, Samara",
|
||||
"DaylightName": "Russia TZ 3 Daylight Time",
|
||||
"Iana": "Europe/Samara"
|
||||
},
|
||||
{
|
||||
"Id": "Mauritius Standard Time",
|
||||
"StandardName": "Mauritius Standard Time",
|
||||
"DisplayName": "(UTC+04:00) Port Louis",
|
||||
"DaylightName": "Mauritius Daylight Time",
|
||||
"Iana": "Indian/Mauritius"
|
||||
},
|
||||
{
|
||||
"Id": "Saratov Standard Time",
|
||||
"StandardName": "Saratov Standard Time",
|
||||
"DisplayName": "(UTC+04:00) Saratov",
|
||||
"DaylightName": "Saratov Daylight Time",
|
||||
"Iana": "Europe/Saratov"
|
||||
},
|
||||
{
|
||||
"Id": "Georgian Standard Time",
|
||||
"StandardName": "Georgian Standard Time",
|
||||
"DisplayName": "(UTC+04:00) Tbilisi",
|
||||
"DaylightName": "Georgian Daylight Time",
|
||||
"Iana": "Asia/Tbilisi"
|
||||
},
|
||||
{
|
||||
"Id": "Caucasus Standard Time",
|
||||
"StandardName": "Caucasus Standard Time",
|
||||
"DisplayName": "(UTC+04:00) Yerevan",
|
||||
"DaylightName": "Caucasus Daylight Time",
|
||||
"Iana": "Asia/Yerevan"
|
||||
},
|
||||
{
|
||||
"Id": "Afghanistan Standard Time",
|
||||
"StandardName": "Afghanistan Standard Time",
|
||||
"DisplayName": "(UTC+04:30) Kabul",
|
||||
"DaylightName": "Afghanistan Daylight Time",
|
||||
"Iana": "Asia/Kabul"
|
||||
},
|
||||
{
|
||||
"Id": "West Asia Standard Time",
|
||||
"StandardName": "West Asia Standard Time",
|
||||
"DisplayName": "(UTC+05:00) Ashgabat, Tashkent",
|
||||
"DaylightName": "West Asia Daylight Time",
|
||||
"Iana": "Asia/Tashkent"
|
||||
},
|
||||
{
|
||||
"Id": "Qyzylorda Standard Time",
|
||||
"StandardName": "Qyzylorda Standard Time",
|
||||
"DisplayName": "(UTC+05:00) Astana",
|
||||
"DaylightName": "Qyzylorda Daylight Time",
|
||||
"Iana": "Asia/Qyzylorda"
|
||||
},
|
||||
{
|
||||
"Id": "Ekaterinburg Standard Time",
|
||||
"StandardName": "Russia TZ 4 Standard Time",
|
||||
"DisplayName": "(UTC+05:00) Ekaterinburg",
|
||||
"DaylightName": "Russia TZ 4 Daylight Time",
|
||||
"Iana": "Asia/Yekaterinburg"
|
||||
},
|
||||
{
|
||||
"Id": "Pakistan Standard Time",
|
||||
"StandardName": "Pakistan Standard Time",
|
||||
"DisplayName": "(UTC+05:00) Islamabad, Karachi",
|
||||
"DaylightName": "Pakistan Daylight Time",
|
||||
"Iana": "Asia/Karachi"
|
||||
},
|
||||
{
|
||||
"Id": "India Standard Time",
|
||||
"StandardName": "India Standard Time",
|
||||
"DisplayName": "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi",
|
||||
"DaylightName": "India Daylight Time",
|
||||
"Iana": "Asia/Calcutta"
|
||||
},
|
||||
{
|
||||
"Id": "Sri Lanka Standard Time",
|
||||
"StandardName": "Sri Lanka Standard Time",
|
||||
"DisplayName": "(UTC+05:30) Sri Jayawardenepura",
|
||||
"DaylightName": "Sri Lanka Daylight Time",
|
||||
"Iana": "Asia/Colombo"
|
||||
},
|
||||
{
|
||||
"Id": "Nepal Standard Time",
|
||||
"StandardName": "Nepal Standard Time",
|
||||
"DisplayName": "(UTC+05:45) Kathmandu",
|
||||
"DaylightName": "Nepal Daylight Time",
|
||||
"Iana": "Asia/Katmandu"
|
||||
},
|
||||
{
|
||||
"Id": "Central Asia Standard Time",
|
||||
"StandardName": "Central Asia Standard Time",
|
||||
"DisplayName": "(UTC+06:00) Bishkek",
|
||||
"DaylightName": "Central Asia Daylight Time",
|
||||
"Iana": "Asia/Almaty"
|
||||
},
|
||||
{
|
||||
"Id": "Bangladesh Standard Time",
|
||||
"StandardName": "Bangladesh Standard Time",
|
||||
"DisplayName": "(UTC+06:00) Dhaka",
|
||||
"DaylightName": "Bangladesh Daylight Time",
|
||||
"Iana": "Asia/Dhaka"
|
||||
},
|
||||
{
|
||||
"Id": "Omsk Standard Time",
|
||||
"StandardName": "Omsk Standard Time",
|
||||
"DisplayName": "(UTC+06:00) Omsk",
|
||||
"DaylightName": "Omsk Daylight Time",
|
||||
"Iana": "Asia/Omsk"
|
||||
},
|
||||
{
|
||||
"Id": "Myanmar Standard Time",
|
||||
"StandardName": "Myanmar Standard Time",
|
||||
"DisplayName": "(UTC+06:30) Yangon (Rangoon)",
|
||||
"DaylightName": "Myanmar Daylight Time",
|
||||
"Iana": "Asia/Rangoon"
|
||||
},
|
||||
{
|
||||
"Id": "SE Asia Standard Time",
|
||||
"StandardName": "SE Asia Standard Time",
|
||||
"DisplayName": "(UTC+07:00) Bangkok, Hanoi, Jakarta",
|
||||
"DaylightName": "SE Asia Daylight Time",
|
||||
"Iana": "Asia/Bangkok"
|
||||
},
|
||||
{
|
||||
"Id": "Altai Standard Time",
|
||||
"StandardName": "Altai Standard Time",
|
||||
"DisplayName": "(UTC+07:00) Barnaul, Gorno-Altaysk",
|
||||
"DaylightName": "Altai Daylight Time",
|
||||
"Iana": "Asia/Barnaul"
|
||||
},
|
||||
{
|
||||
"Id": "W. Mongolia Standard Time",
|
||||
"StandardName": "W. Mongolia Standard Time",
|
||||
"DisplayName": "(UTC+07:00) Hovd",
|
||||
"DaylightName": "W. Mongolia Daylight Time",
|
||||
"Iana": "Asia/Hovd"
|
||||
},
|
||||
{
|
||||
"Id": "North Asia Standard Time",
|
||||
"StandardName": "Russia TZ 6 Standard Time",
|
||||
"DisplayName": "(UTC+07:00) Krasnoyarsk",
|
||||
"DaylightName": "Russia TZ 6 Daylight Time",
|
||||
"Iana": "Asia/Krasnoyarsk"
|
||||
},
|
||||
{
|
||||
"Id": "N. Central Asia Standard Time",
|
||||
"StandardName": "Novosibirsk Standard Time",
|
||||
"DisplayName": "(UTC+07:00) Novosibirsk",
|
||||
"DaylightName": "Novosibirsk Daylight Time",
|
||||
"Iana": "Asia/Novosibirsk"
|
||||
},
|
||||
{
|
||||
"Id": "Tomsk Standard Time",
|
||||
"StandardName": "Tomsk Standard Time",
|
||||
"DisplayName": "(UTC+07:00) Tomsk",
|
||||
"DaylightName": "Tomsk Daylight Time",
|
||||
"Iana": "Asia/Tomsk"
|
||||
},
|
||||
{
|
||||
"Id": "China Standard Time",
|
||||
"StandardName": "China Standard Time",
|
||||
"DisplayName": "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi",
|
||||
"DaylightName": "China Daylight Time",
|
||||
"Iana": "Asia/Shanghai"
|
||||
},
|
||||
{
|
||||
"Id": "North Asia East Standard Time",
|
||||
"StandardName": "Russia TZ 7 Standard Time",
|
||||
"DisplayName": "(UTC+08:00) Irkutsk",
|
||||
"DaylightName": "Russia TZ 7 Daylight Time",
|
||||
"Iana": "Asia/Irkutsk"
|
||||
},
|
||||
{
|
||||
"Id": "Singapore Standard Time",
|
||||
"StandardName": "Malay Peninsula Standard Time",
|
||||
"DisplayName": "(UTC+08:00) Kuala Lumpur, Singapore",
|
||||
"DaylightName": "Malay Peninsula Daylight Time",
|
||||
"Iana": "Asia/Singapore"
|
||||
},
|
||||
{
|
||||
"Id": "W. Australia Standard Time",
|
||||
"StandardName": "W. Australia Standard Time",
|
||||
"DisplayName": "(UTC+08:00) Perth",
|
||||
"DaylightName": "W. Australia Daylight Time",
|
||||
"Iana": "Australia/Perth"
|
||||
},
|
||||
{
|
||||
"Id": "Taipei Standard Time",
|
||||
"StandardName": "Taipei Standard Time",
|
||||
"DisplayName": "(UTC+08:00) Taipei",
|
||||
"DaylightName": "Taipei Daylight Time",
|
||||
"Iana": "Asia/Taipei"
|
||||
},
|
||||
{
|
||||
"Id": "Ulaanbaatar Standard Time",
|
||||
"StandardName": "Ulaanbaatar Standard Time",
|
||||
"DisplayName": "(UTC+08:00) Ulaanbaatar",
|
||||
"DaylightName": "Ulaanbaatar Daylight Time",
|
||||
"Iana": "Asia/Ulaanbaatar"
|
||||
},
|
||||
{
|
||||
"Id": "Aus Central W. Standard Time",
|
||||
"StandardName": "Aus Central W. Standard Time",
|
||||
"DisplayName": "(UTC+08:45) Eucla",
|
||||
"DaylightName": "Aus Central W. Daylight Time",
|
||||
"Iana": "Australia/Eucla"
|
||||
},
|
||||
{
|
||||
"Id": "Transbaikal Standard Time",
|
||||
"StandardName": "Transbaikal Standard Time",
|
||||
"DisplayName": "(UTC+09:00) Chita",
|
||||
"DaylightName": "Transbaikal Daylight Time",
|
||||
"Iana": "Asia/Chita"
|
||||
},
|
||||
{
|
||||
"Id": "Tokyo Standard Time",
|
||||
"StandardName": "Tokyo Standard Time",
|
||||
"DisplayName": "(UTC+09:00) Osaka, Sapporo, Tokyo",
|
||||
"DaylightName": "Tokyo Daylight Time",
|
||||
"Iana": "Asia/Tokyo"
|
||||
},
|
||||
{
|
||||
"Id": "North Korea Standard Time",
|
||||
"StandardName": "North Korea Standard Time",
|
||||
"DisplayName": "(UTC+09:00) Pyongyang",
|
||||
"DaylightName": "North Korea Daylight Time",
|
||||
"Iana": "Asia/Pyongyang"
|
||||
},
|
||||
{
|
||||
"Id": "Korea Standard Time",
|
||||
"StandardName": "Korea Standard Time",
|
||||
"DisplayName": "(UTC+09:00) Seoul",
|
||||
"DaylightName": "Korea Daylight Time",
|
||||
"Iana": "Asia/Seoul"
|
||||
},
|
||||
{
|
||||
"Id": "Yakutsk Standard Time",
|
||||
"StandardName": "Russia TZ 8 Standard Time",
|
||||
"DisplayName": "(UTC+09:00) Yakutsk",
|
||||
"DaylightName": "Russia TZ 8 Daylight Time",
|
||||
"Iana": "Asia/Yakutsk"
|
||||
},
|
||||
{
|
||||
"Id": "Cen. Australia Standard Time",
|
||||
"StandardName": "Cen. Australia Standard Time",
|
||||
"DisplayName": "(UTC+09:30) Adelaide",
|
||||
"DaylightName": "Cen. Australia Daylight Time",
|
||||
"Iana": "Australia/Adelaide"
|
||||
},
|
||||
{
|
||||
"Id": "AUS Central Standard Time",
|
||||
"StandardName": "AUS Central Standard Time",
|
||||
"DisplayName": "(UTC+09:30) Darwin",
|
||||
"DaylightName": "AUS Central Daylight Time",
|
||||
"Iana": "Australia/Darwin"
|
||||
},
|
||||
{
|
||||
"Id": "E. Australia Standard Time",
|
||||
"StandardName": "E. Australia Standard Time",
|
||||
"DisplayName": "(UTC+10:00) Brisbane",
|
||||
"DaylightName": "E. Australia Daylight Time",
|
||||
"Iana": "Australia/Brisbane"
|
||||
},
|
||||
{
|
||||
"Id": "AUS Eastern Standard Time",
|
||||
"StandardName": "AUS Eastern Standard Time",
|
||||
"DisplayName": "(UTC+10:00) Canberra, Melbourne, Sydney",
|
||||
"DaylightName": "AUS Eastern Daylight Time",
|
||||
"Iana": "Australia/Sydney"
|
||||
},
|
||||
{
|
||||
"Id": "West Pacific Standard Time",
|
||||
"StandardName": "West Pacific Standard Time",
|
||||
"DisplayName": "(UTC+10:00) Guam, Port Moresby",
|
||||
"DaylightName": "West Pacific Daylight Time",
|
||||
"Iana": "Pacific/Port_Moresby"
|
||||
},
|
||||
{
|
||||
"Id": "Tasmania Standard Time",
|
||||
"StandardName": "Tasmania Standard Time",
|
||||
"DisplayName": "(UTC+10:00) Hobart",
|
||||
"DaylightName": "Tasmania Daylight Time",
|
||||
"Iana": "Australia/Hobart"
|
||||
},
|
||||
{
|
||||
"Id": "Vladivostok Standard Time",
|
||||
"StandardName": "Russia TZ 9 Standard Time",
|
||||
"DisplayName": "(UTC+10:00) Vladivostok",
|
||||
"DaylightName": "Russia TZ 9 Daylight Time",
|
||||
"Iana": "Asia/Vladivostok"
|
||||
},
|
||||
{
|
||||
"Id": "Lord Howe Standard Time",
|
||||
"StandardName": "Lord Howe Standard Time",
|
||||
"DisplayName": "(UTC+10:30) Lord Howe Island",
|
||||
"DaylightName": "Lord Howe Daylight Time",
|
||||
"Iana": "Australia/Lord_Howe"
|
||||
},
|
||||
{
|
||||
"Id": "Bougainville Standard Time",
|
||||
"StandardName": "Bougainville Standard Time",
|
||||
"DisplayName": "(UTC+11:00) Bougainville Island",
|
||||
"DaylightName": "Bougainville Daylight Time",
|
||||
"Iana": "Pacific/Bougainville"
|
||||
},
|
||||
{
|
||||
"Id": "Russia Time Zone 10",
|
||||
"StandardName": "Russia TZ 10 Standard Time",
|
||||
"DisplayName": "(UTC+11:00) Chokurdakh",
|
||||
"DaylightName": "Russia TZ 10 Daylight Time",
|
||||
"Iana": "Asia/Srednekolymsk"
|
||||
},
|
||||
{
|
||||
"Id": "Magadan Standard Time",
|
||||
"StandardName": "Magadan Standard Time",
|
||||
"DisplayName": "(UTC+11:00) Magadan",
|
||||
"DaylightName": "Magadan Daylight Time",
|
||||
"Iana": "Asia/Magadan"
|
||||
},
|
||||
{
|
||||
"Id": "Norfolk Standard Time",
|
||||
"StandardName": "Norfolk Standard Time",
|
||||
"DisplayName": "(UTC+11:00) Norfolk Island",
|
||||
"DaylightName": "Norfolk Daylight Time",
|
||||
"Iana": "Pacific/Norfolk"
|
||||
},
|
||||
{
|
||||
"Id": "Sakhalin Standard Time",
|
||||
"StandardName": "Sakhalin Standard Time",
|
||||
"DisplayName": "(UTC+11:00) Sakhalin",
|
||||
"DaylightName": "Sakhalin Daylight Time",
|
||||
"Iana": "Asia/Sakhalin"
|
||||
},
|
||||
{
|
||||
"Id": "Central Pacific Standard Time",
|
||||
"StandardName": "Central Pacific Standard Time",
|
||||
"DisplayName": "(UTC+11:00) Solomon Is., New Caledonia",
|
||||
"DaylightName": "Central Pacific Daylight Time",
|
||||
"Iana": "Pacific/Guadalcanal"
|
||||
},
|
||||
{
|
||||
"Id": "Russia Time Zone 11",
|
||||
"StandardName": "Russia TZ 11 Standard Time",
|
||||
"DisplayName": "(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky",
|
||||
"DaylightName": "Russia TZ 11 Daylight Time",
|
||||
"Iana": "Asia/Kamchatka"
|
||||
},
|
||||
{
|
||||
"Id": "New Zealand Standard Time",
|
||||
"StandardName": "New Zealand Standard Time",
|
||||
"DisplayName": "(UTC+12:00) Auckland, Wellington",
|
||||
"DaylightName": "New Zealand Daylight Time",
|
||||
"Iana": "Pacific/Auckland"
|
||||
},
|
||||
{
|
||||
"Id": "UTC+12",
|
||||
"StandardName": "UTC+12",
|
||||
"DisplayName": "(UTC+12:00) Coordinated Universal Time+12",
|
||||
"DaylightName": "UTC+12",
|
||||
"Iana": "Etc/GMT-12"
|
||||
},
|
||||
{
|
||||
"Id": "Fiji Standard Time",
|
||||
"StandardName": "Fiji Standard Time",
|
||||
"DisplayName": "(UTC+12:00) Fiji",
|
||||
"DaylightName": "Fiji Daylight Time",
|
||||
"Iana": "Pacific/Fiji"
|
||||
},
|
||||
{
|
||||
"Id": "Kamchatka Standard Time",
|
||||
"StandardName": "Kamchatka Standard Time",
|
||||
"DisplayName": "(UTC+12:00) Petropavlovsk-Kamchatsky - Old",
|
||||
"DaylightName": "Kamchatka Daylight Time",
|
||||
"Iana": ""
|
||||
},
|
||||
{
|
||||
"Id": "Chatham Islands Standard Time",
|
||||
"StandardName": "Chatham Islands Standard Time",
|
||||
"DisplayName": "(UTC+12:45) Chatham Islands",
|
||||
"DaylightName": "Chatham Islands Daylight Time",
|
||||
"Iana": "Pacific/Chatham"
|
||||
},
|
||||
{
|
||||
"Id": "UTC+13",
|
||||
"StandardName": "UTC+13",
|
||||
"DisplayName": "(UTC+13:00) Coordinated Universal Time+13",
|
||||
"DaylightName": "UTC+13",
|
||||
"Iana": "Etc/GMT-13"
|
||||
},
|
||||
{
|
||||
"Id": "Tonga Standard Time",
|
||||
"StandardName": "Tonga Standard Time",
|
||||
"DisplayName": "(UTC+13:00) Nuku'alofa",
|
||||
"DaylightName": "Tonga Daylight Time",
|
||||
"Iana": "Pacific/Tongatapu"
|
||||
},
|
||||
{
|
||||
"Id": "Samoa Standard Time",
|
||||
"StandardName": "Samoa Standard Time",
|
||||
"DisplayName": "(UTC+13:00) Samoa",
|
||||
"DaylightName": "Samoa Daylight Time",
|
||||
"Iana": "Pacific/Apia"
|
||||
},
|
||||
{
|
||||
"Id": "Line Islands Standard Time",
|
||||
"StandardName": "Line Islands Standard Time",
|
||||
"DisplayName": "(UTC+14:00) Kiritimati Island",
|
||||
"DaylightName": "Line Islands Daylight Time",
|
||||
"Iana": "Pacific/Kiritimati"
|
||||
}
|
||||
]
|
||||
}
|
||||
408
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneNameMapUtils.c
vendored
Normal file
408
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneNameMapUtils.c
vendored
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Time Zone Name Map Utils
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/json.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/file.h>
|
||||
|
||||
#include "../log.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define TAG WINPR_TAG("timezone.utils")
|
||||
|
||||
#if defined(WITH_TIMEZONE_ICU)
|
||||
#include <unicode/ucal.h>
|
||||
#else
|
||||
#include "WindowsZones.h"
|
||||
#endif
|
||||
|
||||
#include "TimeZoneNameMap.h"
|
||||
|
||||
#if defined(WITH_TIMEZONE_COMPILED)
|
||||
#include "TimeZoneNameMap_static.h"
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t count;
|
||||
TimeZoneNameMapEntry* entries;
|
||||
} TimeZoneNameMapContext;
|
||||
|
||||
static TimeZoneNameMapContext tz_context = WINPR_C_ARRAY_INIT;
|
||||
|
||||
static void tz_entry_free(TimeZoneNameMapEntry* entry)
|
||||
{
|
||||
if (!entry)
|
||||
return;
|
||||
free(entry->DaylightName);
|
||||
free(entry->DisplayName);
|
||||
free(entry->Iana);
|
||||
free(entry->Id);
|
||||
free(entry->StandardName);
|
||||
|
||||
const TimeZoneNameMapEntry empty = WINPR_C_ARRAY_INIT;
|
||||
*entry = empty;
|
||||
}
|
||||
|
||||
static TimeZoneNameMapEntry tz_entry_clone(const TimeZoneNameMapEntry* entry)
|
||||
{
|
||||
TimeZoneNameMapEntry clone = WINPR_C_ARRAY_INIT;
|
||||
if (!entry)
|
||||
return clone;
|
||||
|
||||
if (entry->DaylightName)
|
||||
clone.DaylightName = _strdup(entry->DaylightName);
|
||||
if (entry->DisplayName)
|
||||
clone.DisplayName = _strdup(entry->DisplayName);
|
||||
if (entry->Iana)
|
||||
clone.Iana = _strdup(entry->Iana);
|
||||
if (entry->Id)
|
||||
clone.Id = _strdup(entry->Id);
|
||||
if (entry->StandardName)
|
||||
clone.StandardName = _strdup(entry->StandardName);
|
||||
return clone;
|
||||
}
|
||||
|
||||
static void tz_context_free(void)
|
||||
{
|
||||
for (size_t x = 0; x < tz_context.count; x++)
|
||||
tz_entry_free(&tz_context.entries[x]);
|
||||
free(tz_context.entries);
|
||||
tz_context.count = 0;
|
||||
tz_context.entries = nullptr;
|
||||
}
|
||||
|
||||
#if defined(WITH_TIMEZONE_FROM_FILE) && defined(WITH_WINPR_JSON)
|
||||
static char* tz_get_object_str(WINPR_JSON* json, size_t pos, const char* name)
|
||||
{
|
||||
WINPR_ASSERT(json);
|
||||
if (!WINPR_JSON_IsObject(json) || !WINPR_JSON_HasObjectItem(json, name))
|
||||
{
|
||||
WLog_WARN(TAG, "Invalid JSON entry at entry %" PRIuz ", missing an Object named '%s'", pos,
|
||||
name);
|
||||
return nullptr;
|
||||
}
|
||||
WINPR_JSON* obj = WINPR_JSON_GetObjectItemCaseSensitive(json, name);
|
||||
WINPR_ASSERT(obj);
|
||||
if (!WINPR_JSON_IsString(obj))
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"Invalid JSON entry at entry %" PRIuz ", Object named '%s': Not of type string",
|
||||
pos, name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* str = WINPR_JSON_GetStringValue(obj);
|
||||
if (!str)
|
||||
{
|
||||
WLog_WARN(TAG, "Invalid JSON entry at entry %" PRIuz ", Object named '%s': nullptr string",
|
||||
pos, name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _strdup(str);
|
||||
}
|
||||
|
||||
static BOOL tz_parse_json_entry(WINPR_JSON* json, size_t pos, TimeZoneNameMapEntry* entry)
|
||||
{
|
||||
WINPR_ASSERT(entry);
|
||||
if (!json || !WINPR_JSON_IsObject(json))
|
||||
{
|
||||
WLog_WARN(TAG, "Invalid JSON entry at entry %" PRIuz ", expected an array", pos);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
entry->Id = tz_get_object_str(json, pos, "Id");
|
||||
entry->StandardName = tz_get_object_str(json, pos, "StandardName");
|
||||
entry->DisplayName = tz_get_object_str(json, pos, "DisplayName");
|
||||
entry->DaylightName = tz_get_object_str(json, pos, "DaylightName");
|
||||
entry->Iana = tz_get_object_str(json, pos, "Iana");
|
||||
if (!entry->Id || !entry->StandardName || !entry->DisplayName || !entry->DaylightName ||
|
||||
!entry->Iana)
|
||||
{
|
||||
tz_entry_free(entry);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static WINPR_JSON* load_timezones_from_file(const char* filename)
|
||||
{
|
||||
WINPR_JSON* json = WINPR_JSON_ParseFromFile(filename);
|
||||
if (!json)
|
||||
WLog_WARN(TAG, "Timezone resource file '%s' is not a valid JSON file", filename);
|
||||
return json;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL reallocate_context(TimeZoneNameMapContext* context, size_t size_to_add)
|
||||
{
|
||||
{
|
||||
TimeZoneNameMapEntry* tmp = realloc(context->entries, (context->count + size_to_add) *
|
||||
sizeof(TimeZoneNameMapEntry));
|
||||
if (!tmp)
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"Failed to reallocate TimeZoneNameMapEntry::entries to %" PRIuz " elements",
|
||||
context->count + size_to_add);
|
||||
return FALSE;
|
||||
}
|
||||
const size_t offset = context->count;
|
||||
context->entries = tmp;
|
||||
context->count += size_to_add;
|
||||
|
||||
memset(&context->entries[offset], 0, size_to_add * sizeof(TimeZoneNameMapEntry));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK load_timezones(PINIT_ONCE once, PVOID param, PVOID* pvcontext)
|
||||
{
|
||||
TimeZoneNameMapContext* context = param;
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_UNUSED(pvcontext);
|
||||
WINPR_UNUSED(once);
|
||||
|
||||
const TimeZoneNameMapContext empty = WINPR_C_ARRAY_INIT;
|
||||
*context = empty;
|
||||
|
||||
#if defined(WITH_TIMEZONE_FROM_FILE) && defined(WITH_WINPR_JSON)
|
||||
{
|
||||
WINPR_JSON* json = nullptr;
|
||||
char* filename = GetCombinedPath(WINPR_RESOURCE_ROOT, "TimeZoneNameMap.json");
|
||||
if (!filename)
|
||||
{
|
||||
WLog_WARN(TAG, "Could not create WinPR timezone resource filename");
|
||||
goto end;
|
||||
}
|
||||
|
||||
json = load_timezones_from_file(filename);
|
||||
if (!json)
|
||||
goto end;
|
||||
|
||||
if (!WINPR_JSON_IsObject(json))
|
||||
{
|
||||
WLog_WARN(TAG, "Invalid top level JSON type in file %s, expected an array", filename);
|
||||
goto end;
|
||||
}
|
||||
|
||||
WINPR_JSON* obj = WINPR_JSON_GetObjectItemCaseSensitive(json, "TimeZoneNameMap");
|
||||
if (!WINPR_JSON_IsArray(obj))
|
||||
{
|
||||
WLog_WARN(TAG, "Invalid top level JSON type in file %s, expected an array", filename);
|
||||
goto end;
|
||||
}
|
||||
const size_t count = WINPR_JSON_GetArraySize(obj);
|
||||
const size_t offset = context->count;
|
||||
if (!reallocate_context(context, count))
|
||||
goto end;
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
WINPR_JSON* entry = WINPR_JSON_GetArrayItem(obj, x);
|
||||
if (!tz_parse_json_entry(entry, x, &context->entries[offset + x]))
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
free(filename);
|
||||
WINPR_JSON_Delete(json);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WITH_TIMEZONE_COMPILED)
|
||||
{
|
||||
const size_t offset = context->count;
|
||||
if (!reallocate_context(context, TimeZoneNameMapSize))
|
||||
return FALSE;
|
||||
for (size_t x = 0; x < TimeZoneNameMapSize; x++)
|
||||
context->entries[offset + x] = tz_entry_clone(&TimeZoneNameMap[x]);
|
||||
}
|
||||
#endif
|
||||
|
||||
(void)atexit(tz_context_free);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const TimeZoneNameMapEntry* TimeZoneGetAt(size_t index)
|
||||
{
|
||||
static INIT_ONCE init_guard = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
if (!InitOnceExecuteOnce(&init_guard, load_timezones, &tz_context, nullptr))
|
||||
return nullptr;
|
||||
if (index >= tz_context.count)
|
||||
return nullptr;
|
||||
return &tz_context.entries[index];
|
||||
}
|
||||
|
||||
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 nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL iana_cmp(const TimeZoneNameMapEntry* entry, const char* iana)
|
||||
{
|
||||
if (!entry || !iana || !entry->Iana)
|
||||
return FALSE;
|
||||
return strcmp(iana, entry->Iana) == 0;
|
||||
}
|
||||
|
||||
static BOOL id_cmp(const TimeZoneNameMapEntry* entry, const char* id)
|
||||
{
|
||||
if (!entry || !id || !entry->Id)
|
||||
return FALSE;
|
||||
return strcmp(id, entry->Id) == 0;
|
||||
}
|
||||
|
||||
static const char* get_for_type(const char* val, TimeZoneNameType type,
|
||||
BOOL (*cmp)(const TimeZoneNameMapEntry*, const char*))
|
||||
{
|
||||
WINPR_ASSERT(val);
|
||||
WINPR_ASSERT(cmp);
|
||||
|
||||
size_t index = 0;
|
||||
while (TRUE)
|
||||
{
|
||||
const TimeZoneNameMapEntry* entry = TimeZoneGetAt(index++);
|
||||
if (!entry)
|
||||
return nullptr;
|
||||
if (cmp(entry, val))
|
||||
return return_type(entry, type);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WITH_TIMEZONE_ICU)
|
||||
static char* get_wzid_icu(const UChar* utzid, size_t utzid_len)
|
||||
{
|
||||
char* res = nullptr;
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
|
||||
int32_t rc = ucal_getWindowsTimeZoneID(utzid, WINPR_ASSERTING_INT_CAST(int32_t, utzid_len),
|
||||
nullptr, 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, WINPR_ASSERTING_INT_CAST(int32_t, utzid_len), wzid, rc, &error2);
|
||||
if (U_SUCCESS(error2) && (rc2 > 0))
|
||||
res = ConvertWCharNToUtf8Alloc(wzid, (size_t)rc, nullptr);
|
||||
free(wzid);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static char* get(const char* iana)
|
||||
{
|
||||
size_t utzid_len = 0;
|
||||
UChar* utzid = ConvertUtf8ToWCharAlloc(iana, &utzid_len);
|
||||
if (!utzid)
|
||||
return nullptr;
|
||||
|
||||
char* wzid = get_wzid_icu(utzid, utzid_len);
|
||||
free(utzid);
|
||||
return wzid;
|
||||
}
|
||||
|
||||
static const char* map_fallback(const char* iana, TimeZoneNameType type)
|
||||
{
|
||||
char* wzid = get(iana);
|
||||
if (!wzid)
|
||||
return nullptr;
|
||||
|
||||
const char* res = get_for_type(wzid, type, id_cmp);
|
||||
free(wzid);
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
static const char* map_fallback(const char* iana, WINPR_ATTR_UNUSED TimeZoneNameType type)
|
||||
{
|
||||
if (!iana)
|
||||
return nullptr;
|
||||
|
||||
for (size_t x = 0; x < WindowsZonesNrElements; x++)
|
||||
{
|
||||
const WINDOWS_TZID_ENTRY* const entry = &WindowsZones[x];
|
||||
if (strchr(entry->tzid, ' '))
|
||||
{
|
||||
const char* res = nullptr;
|
||||
char* tzid = _strdup(entry->tzid);
|
||||
char* ctzid = tzid;
|
||||
while (tzid)
|
||||
{
|
||||
char* space = strchr(tzid, ' ');
|
||||
if (space)
|
||||
*space++ = '\0';
|
||||
if (strcmp(tzid, iana) == 0)
|
||||
{
|
||||
res = entry->windows;
|
||||
break;
|
||||
}
|
||||
tzid = space;
|
||||
}
|
||||
free(ctzid);
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
else if (strcmp(entry->tzid, iana) == 0)
|
||||
return entry->windows;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* TimeZoneIanaToWindows(const char* iana, TimeZoneNameType type)
|
||||
{
|
||||
if (!iana)
|
||||
return nullptr;
|
||||
|
||||
const char* val = get_for_type(iana, type, iana_cmp);
|
||||
if (val)
|
||||
return val;
|
||||
|
||||
const char* wzid = map_fallback(iana, type);
|
||||
if (!wzid)
|
||||
return nullptr;
|
||||
|
||||
return get_for_type(wzid, type, id_cmp);
|
||||
}
|
||||
292
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneNameMap_static.h
vendored
Normal file
292
third_party/FreeRDP/winpr/libwinpr/timezone/TimeZoneNameMap_static.h
vendored
Normal file
@@ -0,0 +1,292 @@
|
||||
/* Automatically generated by tzextract */
|
||||
|
||||
#include "TimeZoneNameMap.h"
|
||||
|
||||
static const TimeZoneNameMapEntry TimeZoneNameMap[] = {
|
||||
{ "Dateline Standard Time", "Dateline Standard Time",
|
||||
"(UTC-12:00) International Date Line West", "Dateline Daylight Time", "Etc/GMT+12" },
|
||||
{ "UTC-11", "UTC-11", "(UTC-11:00) Coordinated Universal Time-11", "UTC-11", "Etc/GMT+11" },
|
||||
{ "Aleutian Standard Time", "Aleutian Standard Time", "(UTC-10:00) Aleutian Islands",
|
||||
"Aleutian Daylight Time", "America/Adak" },
|
||||
{ "Hawaiian Standard Time", "Hawaiian Standard Time", "(UTC-10:00) Hawaii",
|
||||
"Hawaiian Daylight Time", "Pacific/Honolulu" },
|
||||
{ "Marquesas Standard Time", "Marquesas Standard Time", "(UTC-09:30) Marquesas Islands",
|
||||
"Marquesas Daylight Time", "Pacific/Marquesas" },
|
||||
{ "Alaskan Standard Time", "Alaskan Standard Time", "(UTC-09:00) Alaska",
|
||||
"Alaskan Daylight Time", "America/Anchorage" },
|
||||
{ "UTC-09", "UTC-09", "(UTC-09:00) Coordinated Universal Time-09", "UTC-09", "Etc/GMT+9" },
|
||||
{ "Pacific Standard Time (Mexico)", "Pacific Standard Time (Mexico)",
|
||||
"(UTC-08:00) Baja California", "Pacific Daylight Time (Mexico)", "America/Tijuana" },
|
||||
{ "UTC-08", "UTC-08", "(UTC-08:00) Coordinated Universal Time-08", "UTC-08", "Etc/GMT+8" },
|
||||
{ "Pacific Standard Time", "Pacific Standard Time", "(UTC-08:00) Pacific Time (US & Canada)",
|
||||
"Pacific Daylight Time", "America/Los_Angeles" },
|
||||
{ "US Mountain Standard Time", "US Mountain Standard Time", "(UTC-07:00) Arizona",
|
||||
"US Mountain Daylight Time", "America/Phoenix" },
|
||||
{ "Mountain Standard Time (Mexico)", "Mountain Standard Time (Mexico)",
|
||||
"(UTC-07:00) La Paz, Mazatlan", "Mountain Daylight Time (Mexico)", "America/Chihuahua" },
|
||||
{ "Mountain Standard Time", "Mountain Standard Time", "(UTC-07:00) Mountain Time (US & Canada)",
|
||||
"Mountain Daylight Time", "America/Denver" },
|
||||
{ "Yukon Standard Time", "Yukon Standard Time", "(UTC-07:00) Yukon", "Yukon Daylight Time",
|
||||
"America/Whitehorse" },
|
||||
{ "Central America Standard Time", "Central America Standard Time",
|
||||
"(UTC-06:00) Central America", "Central America Daylight Time", "America/Guatemala" },
|
||||
{ "Central Standard Time", "Central Standard Time", "(UTC-06:00) Central Time (US & Canada)",
|
||||
"Central Daylight Time", "America/Chicago" },
|
||||
{ "Easter Island Standard Time", "Easter Island Standard Time", "(UTC-06:00) Easter Island",
|
||||
"Easter Island Daylight Time", "Pacific/Easter" },
|
||||
{ "Central Standard Time (Mexico)", "Central Standard Time (Mexico)",
|
||||
"(UTC-06:00) Guadalajara, Mexico City, Monterrey", "Central Daylight Time (Mexico)",
|
||||
"America/Mexico_City" },
|
||||
{ "Canada Central Standard Time", "Canada Central Standard Time", "(UTC-06:00) Saskatchewan",
|
||||
"Canada Central Daylight Time", "America/Regina" },
|
||||
{ "SA Pacific Standard Time", "SA Pacific Standard Time",
|
||||
"(UTC-05:00) Bogota, Lima, Quito, Rio Branco", "SA Pacific Daylight Time", "America/Bogota" },
|
||||
{ "Eastern Standard Time (Mexico)", "Eastern Standard Time (Mexico)", "(UTC-05:00) Chetumal",
|
||||
"Eastern Daylight Time (Mexico)", "America/Cancun" },
|
||||
{ "Eastern Standard Time", "Eastern Standard Time", "(UTC-05:00) Eastern Time (US & Canada)",
|
||||
"Eastern Daylight Time", "America/New_York" },
|
||||
{ "Haiti Standard Time", "Haiti Standard Time", "(UTC-05:00) Haiti", "Haiti Daylight Time",
|
||||
"America/Port-au-Prince" },
|
||||
{ "Cuba Standard Time", "Cuba Standard Time", "(UTC-05:00) Havana", "Cuba Daylight Time",
|
||||
"America/Havana" },
|
||||
{ "US Eastern Standard Time", "US Eastern Standard Time", "(UTC-05:00) Indiana (East)",
|
||||
"US Eastern Daylight Time", "America/Indianapolis" },
|
||||
{ "Turks And Caicos Standard Time", "Turks and Caicos Standard Time",
|
||||
"(UTC-05:00) Turks and Caicos", "Turks and Caicos Daylight Time", "America/Grand_Turk" },
|
||||
{ "Atlantic Standard Time", "Atlantic Standard Time", "(UTC-04:00) Atlantic Time (Canada)",
|
||||
"Atlantic Daylight Time", "America/Halifax" },
|
||||
{ "Venezuela Standard Time", "Venezuela Standard Time", "(UTC-04:00) Caracas",
|
||||
"Venezuela Daylight Time", "America/Caracas" },
|
||||
{ "Central Brazilian Standard Time", "Central Brazilian Standard Time", "(UTC-04:00) Cuiaba",
|
||||
"Central Brazilian Daylight Time", "America/Cuiaba" },
|
||||
{ "SA Western Standard Time", "SA Western Standard Time",
|
||||
"(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", "SA Western Daylight Time",
|
||||
"America/La_Paz" },
|
||||
{ "Pacific SA Standard Time", "Pacific SA Standard Time", "(UTC-04:00) Santiago",
|
||||
"Pacific SA Daylight Time", "America/Santiago" },
|
||||
{ "Newfoundland Standard Time", "Newfoundland Standard Time", "(UTC-03:30) Newfoundland",
|
||||
"Newfoundland Daylight Time", "America/St_Johns" },
|
||||
{ "Tocantins Standard Time", "Tocantins Standard Time", "(UTC-03:00) Araguaina",
|
||||
"Tocantins Daylight Time", "America/Araguaina" },
|
||||
{ "Paraguay Standard Time", "Paraguay Standard Time", "(UTC-03:00) Asuncion",
|
||||
"Paraguay Daylight Time", "America/Asuncion" },
|
||||
{ "E. South America Standard Time", "E. South America Standard Time", "(UTC-03:00) Brasilia",
|
||||
"E. South America Daylight Time", "America/Sao_Paulo" },
|
||||
{ "SA Eastern Standard Time", "SA Eastern Standard Time", "(UTC-03:00) Cayenne, Fortaleza",
|
||||
"SA Eastern Daylight Time", "America/Cayenne" },
|
||||
{ "Argentina Standard Time", "Argentina Standard Time", "(UTC-03:00) City of Buenos Aires",
|
||||
"Argentina Daylight Time", "America/Buenos_Aires" },
|
||||
{ "Montevideo Standard Time", "Montevideo Standard Time", "(UTC-03:00) Montevideo",
|
||||
"Montevideo Daylight Time", "America/Montevideo" },
|
||||
{ "Magallanes Standard Time", "Magallanes Standard Time", "(UTC-03:00) Punta Arenas",
|
||||
"Magallanes Daylight Time", "America/Punta_Arenas" },
|
||||
{ "Saint Pierre Standard Time", "Saint Pierre Standard Time",
|
||||
"(UTC-03:00) Saint Pierre and Miquelon", "Saint Pierre Daylight Time", "America/Miquelon" },
|
||||
{ "Bahia Standard Time", "Bahia Standard Time", "(UTC-03:00) Salvador", "Bahia Daylight Time",
|
||||
"America/Bahia" },
|
||||
{ "UTC-02", "UTC-02", "(UTC-02:00) Coordinated Universal Time-02", "UTC-02", "Etc/GMT+2" },
|
||||
{ "Greenland Standard Time", "Greenland Standard Time", "(UTC-02:00) Greenland",
|
||||
"Greenland Daylight Time", "America/Godthab" },
|
||||
{ "Mid-Atlantic Standard Time", "Mid-Atlantic Standard Time", "(UTC-02:00) Mid-Atlantic - Old",
|
||||
"Mid-Atlantic Daylight Time", "" },
|
||||
{ "Azores Standard Time", "Azores Standard Time", "(UTC-01:00) Azores", "Azores Daylight Time",
|
||||
"Atlantic/Azores" },
|
||||
{ "Cape Verde Standard Time", "Cabo Verde Standard Time", "(UTC-01:00) Cabo Verde Is.",
|
||||
"Cabo Verde Daylight Time", "Atlantic/Cape_Verde" },
|
||||
{ "UTC", "Coordinated Universal Time", "(UTC) Coordinated Universal Time",
|
||||
"Coordinated Universal Time", "Etc/UTC" },
|
||||
{ "GMT Standard Time", "GMT Standard Time", "(UTC+00:00) Dublin, Edinburgh, Lisbon, London",
|
||||
"GMT Daylight Time", "Europe/London" },
|
||||
{ "Greenwich Standard Time", "Greenwich Standard Time", "(UTC+00:00) Monrovia, Reykjavik",
|
||||
"Greenwich Daylight Time", "Atlantic/Reykjavik" },
|
||||
{ "Sao Tome Standard Time", "Sao Tome Standard Time", "(UTC+00:00) Sao Tome",
|
||||
"Sao Tome Daylight Time", "Africa/Sao_Tome" },
|
||||
{ "Morocco Standard Time", "Morocco Standard Time", "(UTC+01:00) Casablanca",
|
||||
"Morocco Daylight Time", "Africa/Casablanca" },
|
||||
{ "W. Europe Standard Time", "W. Europe Standard Time",
|
||||
"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", "W. Europe Daylight Time",
|
||||
"Europe/Berlin" },
|
||||
{ "Central Europe Standard Time", "Central Europe Standard Time",
|
||||
"(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague",
|
||||
"Central Europe Daylight Time", "Europe/Budapest" },
|
||||
{ "Romance Standard Time", "Romance Standard Time",
|
||||
"(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", "Romance Daylight Time", "Europe/Paris" },
|
||||
{ "Central European Standard Time", "Central European Standard Time",
|
||||
"(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", "Central European Daylight Time",
|
||||
"Europe/Warsaw" },
|
||||
{ "W. Central Africa Standard Time", "W. Central Africa Standard Time",
|
||||
"(UTC+01:00) West Central Africa", "W. Central Africa Daylight Time", "Africa/Lagos" },
|
||||
{ "GTB Standard Time", "GTB Standard Time", "(UTC+02:00) Athens, Bucharest",
|
||||
"GTB Daylight Time", "Europe/Bucharest" },
|
||||
{ "Middle East Standard Time", "Middle East Standard Time", "(UTC+02:00) Beirut",
|
||||
"Middle East Daylight Time", "Asia/Beirut" },
|
||||
{ "Egypt Standard Time", "Egypt Standard Time", "(UTC+02:00) Cairo", "Egypt Daylight Time",
|
||||
"Africa/Cairo" },
|
||||
{ "E. Europe Standard Time", "E. Europe Standard Time", "(UTC+02:00) Chisinau",
|
||||
"E. Europe Daylight Time", "Europe/Chisinau" },
|
||||
{ "West Bank Standard Time", "West Bank Gaza Standard Time", "(UTC+02:00) Gaza, Hebron",
|
||||
"West Bank Gaza Daylight Time", "Asia/Hebron" },
|
||||
{ "South Africa Standard Time", "South Africa Standard Time", "(UTC+02:00) Harare, Pretoria",
|
||||
"South Africa Daylight Time", "Africa/Johannesburg" },
|
||||
{ "FLE Standard Time", "FLE Standard Time",
|
||||
"(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", "FLE Daylight Time",
|
||||
"Europe/Kiev" },
|
||||
{ "Israel Standard Time", "Jerusalem Standard Time", "(UTC+02:00) Jerusalem",
|
||||
"Jerusalem Daylight Time", "Asia/Jerusalem" },
|
||||
{ "South Sudan Standard Time", "South Sudan Standard Time", "(UTC+02:00) Juba",
|
||||
"South Sudan Daylight Time", "Africa/Juba" },
|
||||
{ "Kaliningrad Standard Time", "Russia TZ 1 Standard Time", "(UTC+02:00) Kaliningrad",
|
||||
"Russia TZ 1 Daylight Time", "Europe/Kaliningrad" },
|
||||
{ "Sudan Standard Time", "Sudan Standard Time", "(UTC+02:00) Khartoum", "Sudan Daylight Time",
|
||||
"Africa/Khartoum" },
|
||||
{ "Libya Standard Time", "Libya Standard Time", "(UTC+02:00) Tripoli", "Libya Daylight Time",
|
||||
"Africa/Tripoli" },
|
||||
{ "Namibia Standard Time", "Namibia Standard Time", "(UTC+02:00) Windhoek",
|
||||
"Namibia Daylight Time", "Africa/Windhoek" },
|
||||
{ "Jordan Standard Time", "Jordan Standard Time", "(UTC+03:00) Amman", "Jordan Daylight Time",
|
||||
"Asia/Amman" },
|
||||
{ "Arabic Standard Time", "Arabic Standard Time", "(UTC+03:00) Baghdad", "Arabic Daylight Time",
|
||||
"Asia/Baghdad" },
|
||||
{ "Syria Standard Time", "Syria Standard Time", "(UTC+03:00) Damascus", "Syria Daylight Time",
|
||||
"Asia/Damascus" },
|
||||
{ "Turkey Standard Time", "Turkey Standard Time", "(UTC+03:00) Istanbul",
|
||||
"Turkey Daylight Time", "Europe/Istanbul" },
|
||||
{ "Arab Standard Time", "Arab Standard Time", "(UTC+03:00) Kuwait, Riyadh",
|
||||
"Arab Daylight Time", "Asia/Riyadh" },
|
||||
{ "Belarus Standard Time", "Belarus Standard Time", "(UTC+03:00) Minsk",
|
||||
"Belarus Daylight Time", "Europe/Minsk" },
|
||||
{ "Russian Standard Time", "Russia TZ 2 Standard Time", "(UTC+03:00) Moscow, St. Petersburg",
|
||||
"Russia TZ 2 Daylight Time", "Europe/Moscow" },
|
||||
{ "E. Africa Standard Time", "E. Africa Standard Time", "(UTC+03:00) Nairobi",
|
||||
"E. Africa Daylight Time", "Africa/Nairobi" },
|
||||
{ "Volgograd Standard Time", "Volgograd Standard Time", "(UTC+03:00) Volgograd",
|
||||
"Volgograd Daylight Time", "Europe/Volgograd" },
|
||||
{ "Iran Standard Time", "Iran Standard Time", "(UTC+03:30) Tehran", "Iran Daylight Time",
|
||||
"Asia/Tehran" },
|
||||
{ "Arabian Standard Time", "Arabian Standard Time", "(UTC+04:00) Abu Dhabi, Muscat",
|
||||
"Arabian Daylight Time", "Asia/Dubai" },
|
||||
{ "Astrakhan Standard Time", "Astrakhan Standard Time", "(UTC+04:00) Astrakhan, Ulyanovsk",
|
||||
"Astrakhan Daylight Time", "Europe/Astrakhan" },
|
||||
{ "Azerbaijan Standard Time", "Azerbaijan Standard Time", "(UTC+04:00) Baku",
|
||||
"Azerbaijan Daylight Time", "Asia/Baku" },
|
||||
{ "Russia Time Zone 3", "Russia TZ 3 Standard Time", "(UTC+04:00) Izhevsk, Samara",
|
||||
"Russia TZ 3 Daylight Time", "Europe/Samara" },
|
||||
{ "Mauritius Standard Time", "Mauritius Standard Time", "(UTC+04:00) Port Louis",
|
||||
"Mauritius Daylight Time", "Indian/Mauritius" },
|
||||
{ "Saratov Standard Time", "Saratov Standard Time", "(UTC+04:00) Saratov",
|
||||
"Saratov Daylight Time", "Europe/Saratov" },
|
||||
{ "Georgian Standard Time", "Georgian Standard Time", "(UTC+04:00) Tbilisi",
|
||||
"Georgian Daylight Time", "Asia/Tbilisi" },
|
||||
{ "Caucasus Standard Time", "Caucasus Standard Time", "(UTC+04:00) Yerevan",
|
||||
"Caucasus Daylight Time", "Asia/Yerevan" },
|
||||
{ "Afghanistan Standard Time", "Afghanistan Standard Time", "(UTC+04:30) Kabul",
|
||||
"Afghanistan Daylight Time", "Asia/Kabul" },
|
||||
{ "West Asia Standard Time", "West Asia Standard Time", "(UTC+05:00) Ashgabat, Tashkent",
|
||||
"West Asia Daylight Time", "Asia/Tashkent" },
|
||||
{ "Qyzylorda Standard Time", "Qyzylorda Standard Time", "(UTC+05:00) Astana",
|
||||
"Qyzylorda Daylight Time", "Asia/Qyzylorda" },
|
||||
{ "Ekaterinburg Standard Time", "Russia TZ 4 Standard Time", "(UTC+05:00) Ekaterinburg",
|
||||
"Russia TZ 4 Daylight Time", "Asia/Yekaterinburg" },
|
||||
{ "Pakistan Standard Time", "Pakistan Standard Time", "(UTC+05:00) Islamabad, Karachi",
|
||||
"Pakistan Daylight Time", "Asia/Karachi" },
|
||||
{ "India Standard Time", "India Standard Time",
|
||||
"(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", "India Daylight Time", "Asia/Calcutta" },
|
||||
{ "Sri Lanka Standard Time", "Sri Lanka Standard Time", "(UTC+05:30) Sri Jayawardenepura",
|
||||
"Sri Lanka Daylight Time", "Asia/Colombo" },
|
||||
{ "Nepal Standard Time", "Nepal Standard Time", "(UTC+05:45) Kathmandu", "Nepal Daylight Time",
|
||||
"Asia/Katmandu" },
|
||||
{ "Central Asia Standard Time", "Central Asia Standard Time", "(UTC+06:00) Bishkek",
|
||||
"Central Asia Daylight Time", "Asia/Almaty" },
|
||||
{ "Bangladesh Standard Time", "Bangladesh Standard Time", "(UTC+06:00) Dhaka",
|
||||
"Bangladesh Daylight Time", "Asia/Dhaka" },
|
||||
{ "Omsk Standard Time", "Omsk Standard Time", "(UTC+06:00) Omsk", "Omsk Daylight Time",
|
||||
"Asia/Omsk" },
|
||||
{ "Myanmar Standard Time", "Myanmar Standard Time", "(UTC+06:30) Yangon (Rangoon)",
|
||||
"Myanmar Daylight Time", "Asia/Rangoon" },
|
||||
{ "SE Asia Standard Time", "SE Asia Standard Time", "(UTC+07:00) Bangkok, Hanoi, Jakarta",
|
||||
"SE Asia Daylight Time", "Asia/Bangkok" },
|
||||
{ "Altai Standard Time", "Altai Standard Time", "(UTC+07:00) Barnaul, Gorno-Altaysk",
|
||||
"Altai Daylight Time", "Asia/Barnaul" },
|
||||
{ "W. Mongolia Standard Time", "W. Mongolia Standard Time", "(UTC+07:00) Hovd",
|
||||
"W. Mongolia Daylight Time", "Asia/Hovd" },
|
||||
{ "North Asia Standard Time", "Russia TZ 6 Standard Time", "(UTC+07:00) Krasnoyarsk",
|
||||
"Russia TZ 6 Daylight Time", "Asia/Krasnoyarsk" },
|
||||
{ "N. Central Asia Standard Time", "Novosibirsk Standard Time", "(UTC+07:00) Novosibirsk",
|
||||
"Novosibirsk Daylight Time", "Asia/Novosibirsk" },
|
||||
{ "Tomsk Standard Time", "Tomsk Standard Time", "(UTC+07:00) Tomsk", "Tomsk Daylight Time",
|
||||
"Asia/Tomsk" },
|
||||
{ "China Standard Time", "China Standard Time",
|
||||
"(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", "China Daylight Time", "Asia/Shanghai" },
|
||||
{ "North Asia East Standard Time", "Russia TZ 7 Standard Time", "(UTC+08:00) Irkutsk",
|
||||
"Russia TZ 7 Daylight Time", "Asia/Irkutsk" },
|
||||
{ "Singapore Standard Time", "Malay Peninsula Standard Time",
|
||||
"(UTC+08:00) Kuala Lumpur, Singapore", "Malay Peninsula Daylight Time", "Asia/Singapore" },
|
||||
{ "W. Australia Standard Time", "W. Australia Standard Time", "(UTC+08:00) Perth",
|
||||
"W. Australia Daylight Time", "Australia/Perth" },
|
||||
{ "Taipei Standard Time", "Taipei Standard Time", "(UTC+08:00) Taipei", "Taipei Daylight Time",
|
||||
"Asia/Taipei" },
|
||||
{ "Ulaanbaatar Standard Time", "Ulaanbaatar Standard Time", "(UTC+08:00) Ulaanbaatar",
|
||||
"Ulaanbaatar Daylight Time", "Asia/Ulaanbaatar" },
|
||||
{ "Aus Central W. Standard Time", "Aus Central W. Standard Time", "(UTC+08:45) Eucla",
|
||||
"Aus Central W. Daylight Time", "Australia/Eucla" },
|
||||
{ "Transbaikal Standard Time", "Transbaikal Standard Time", "(UTC+09:00) Chita",
|
||||
"Transbaikal Daylight Time", "Asia/Chita" },
|
||||
{ "Tokyo Standard Time", "Tokyo Standard Time", "(UTC+09:00) Osaka, Sapporo, Tokyo",
|
||||
"Tokyo Daylight Time", "Asia/Tokyo" },
|
||||
{ "North Korea Standard Time", "North Korea Standard Time", "(UTC+09:00) Pyongyang",
|
||||
"North Korea Daylight Time", "Asia/Pyongyang" },
|
||||
{ "Korea Standard Time", "Korea Standard Time", "(UTC+09:00) Seoul", "Korea Daylight Time",
|
||||
"Asia/Seoul" },
|
||||
{ "Yakutsk Standard Time", "Russia TZ 8 Standard Time", "(UTC+09:00) Yakutsk",
|
||||
"Russia TZ 8 Daylight Time", "Asia/Yakutsk" },
|
||||
{ "Cen. Australia Standard Time", "Cen. Australia Standard Time", "(UTC+09:30) Adelaide",
|
||||
"Cen. Australia Daylight Time", "Australia/Adelaide" },
|
||||
{ "AUS Central Standard Time", "AUS Central Standard Time", "(UTC+09:30) Darwin",
|
||||
"AUS Central Daylight Time", "Australia/Darwin" },
|
||||
{ "E. Australia Standard Time", "E. Australia Standard Time", "(UTC+10:00) Brisbane",
|
||||
"E. Australia Daylight Time", "Australia/Brisbane" },
|
||||
{ "AUS Eastern Standard Time", "AUS Eastern Standard Time",
|
||||
"(UTC+10:00) Canberra, Melbourne, Sydney", "AUS Eastern Daylight Time", "Australia/Sydney" },
|
||||
{ "West Pacific Standard Time", "West Pacific Standard Time", "(UTC+10:00) Guam, Port Moresby",
|
||||
"West Pacific Daylight Time", "Pacific/Port_Moresby" },
|
||||
{ "Tasmania Standard Time", "Tasmania Standard Time", "(UTC+10:00) Hobart",
|
||||
"Tasmania Daylight Time", "Australia/Hobart" },
|
||||
{ "Vladivostok Standard Time", "Russia TZ 9 Standard Time", "(UTC+10:00) Vladivostok",
|
||||
"Russia TZ 9 Daylight Time", "Asia/Vladivostok" },
|
||||
{ "Lord Howe Standard Time", "Lord Howe Standard Time", "(UTC+10:30) Lord Howe Island",
|
||||
"Lord Howe Daylight Time", "Australia/Lord_Howe" },
|
||||
{ "Bougainville Standard Time", "Bougainville Standard Time", "(UTC+11:00) Bougainville Island",
|
||||
"Bougainville Daylight Time", "Pacific/Bougainville" },
|
||||
{ "Russia Time Zone 10", "Russia TZ 10 Standard Time", "(UTC+11:00) Chokurdakh",
|
||||
"Russia TZ 10 Daylight Time", "Asia/Srednekolymsk" },
|
||||
{ "Magadan Standard Time", "Magadan Standard Time", "(UTC+11:00) Magadan",
|
||||
"Magadan Daylight Time", "Asia/Magadan" },
|
||||
{ "Norfolk Standard Time", "Norfolk Standard Time", "(UTC+11:00) Norfolk Island",
|
||||
"Norfolk Daylight Time", "Pacific/Norfolk" },
|
||||
{ "Sakhalin Standard Time", "Sakhalin Standard Time", "(UTC+11:00) Sakhalin",
|
||||
"Sakhalin Daylight Time", "Asia/Sakhalin" },
|
||||
{ "Central Pacific Standard Time", "Central Pacific Standard Time",
|
||||
"(UTC+11:00) Solomon Is., New Caledonia", "Central Pacific Daylight Time",
|
||||
"Pacific/Guadalcanal" },
|
||||
{ "Russia Time Zone 11", "Russia TZ 11 Standard Time",
|
||||
"(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky", "Russia TZ 11 Daylight Time",
|
||||
"Asia/Kamchatka" },
|
||||
{ "New Zealand Standard Time", "New Zealand Standard Time", "(UTC+12:00) Auckland, Wellington",
|
||||
"New Zealand Daylight Time", "Pacific/Auckland" },
|
||||
{ "UTC+12", "UTC+12", "(UTC+12:00) Coordinated Universal Time+12", "UTC+12", "Etc/GMT-12" },
|
||||
{ "Fiji Standard Time", "Fiji Standard Time", "(UTC+12:00) Fiji", "Fiji Daylight Time",
|
||||
"Pacific/Fiji" },
|
||||
{ "Kamchatka Standard Time", "Kamchatka Standard Time",
|
||||
"(UTC+12:00) Petropavlovsk-Kamchatsky - Old", "Kamchatka Daylight Time", "" },
|
||||
{ "Chatham Islands Standard Time", "Chatham Islands Standard Time",
|
||||
"(UTC+12:45) Chatham Islands", "Chatham Islands Daylight Time", "Pacific/Chatham" },
|
||||
{ "UTC+13", "UTC+13", "(UTC+13:00) Coordinated Universal Time+13", "UTC+13", "Etc/GMT-13" },
|
||||
{ "Tonga Standard Time", "Tonga Standard Time", "(UTC+13:00) Nuku'alofa", "Tonga Daylight Time",
|
||||
"Pacific/Tongatapu" },
|
||||
{ "Samoa Standard Time", "Samoa Standard Time", "(UTC+13:00) Samoa", "Samoa Daylight Time",
|
||||
"Pacific/Apia" },
|
||||
{ "Line Islands Standard Time", "Line Islands Standard Time", "(UTC+14:00) Kiritimati Island",
|
||||
"Line Islands Daylight Time", "Pacific/Kiritimati" }
|
||||
};
|
||||
|
||||
static const size_t TimeZoneNameMapSize = ARRAYSIZE(TimeZoneNameMap);
|
||||
530
third_party/FreeRDP/winpr/libwinpr/timezone/WindowsZones.c
vendored
Normal file
530
third_party/FreeRDP/winpr/libwinpr/timezone/WindowsZones.c
vendored
Normal file
@@ -0,0 +1,530 @@
|
||||
/* Automatically generated by tzextract
|
||||
*
|
||||
* url https://raw.githubusercontent.com/unicode-org/cldr/main/common/supplemental/windowsZones.xml
|
||||
* version: $Revision$
|
||||
* mapTimezones: otherVersion: 7e11800, typeVersion: 2021a
|
||||
*/
|
||||
|
||||
#include "WindowsZones.h"
|
||||
|
||||
const WINDOWS_TZID_ENTRY WindowsZones[] = {
|
||||
{ "Etc/GMT+12", "Dateline Standard Time" }, // 001
|
||||
{ "Etc/GMT+12", "Dateline Standard Time" }, // ZZ
|
||||
{ "Etc/GMT+11", "UTC-11" }, // 001
|
||||
{ "Pacific/Pago_Pago", "UTC-11" }, // AS
|
||||
{ "Pacific/Niue", "UTC-11" }, // NU
|
||||
{ "Pacific/Midway", "UTC-11" }, // UM
|
||||
{ "Etc/GMT+11", "UTC-11" }, // ZZ
|
||||
{ "America/Adak", "Aleutian Standard Time" }, // 001
|
||||
{ "America/Adak", "Aleutian Standard Time" }, // US
|
||||
{ "Pacific/Honolulu", "Hawaiian Standard Time" }, // 001
|
||||
{ "Pacific/Rarotonga", "Hawaiian Standard Time" }, // CK
|
||||
{ "Pacific/Tahiti", "Hawaiian Standard Time" }, // PF
|
||||
{ "Pacific/Honolulu", "Hawaiian Standard Time" }, // US
|
||||
{ "Etc/GMT+10", "Hawaiian Standard Time" }, // ZZ
|
||||
{ "Pacific/Marquesas", "Marquesas Standard Time" }, // 001
|
||||
{ "Pacific/Marquesas", "Marquesas Standard Time" }, // PF
|
||||
{ "America/Anchorage", "Alaskan Standard Time" }, // 001
|
||||
{ "America/Anchorage America/Juneau America/Metlakatla America/Nome America/Sitka "
|
||||
"America/Yakutat",
|
||||
"Alaskan Standard Time" }, // US
|
||||
{ "Etc/GMT+9", "UTC-09" }, // 001
|
||||
{ "Pacific/Gambier", "UTC-09" }, // PF
|
||||
{ "Etc/GMT+9", "UTC-09" }, // ZZ
|
||||
{ "America/Tijuana", "Pacific Standard Time (Mexico)" }, // 001
|
||||
{ "America/Tijuana", "Pacific Standard Time (Mexico)" }, // MX
|
||||
{ "Etc/GMT+8", "UTC-08" }, // 001
|
||||
{ "Pacific/Pitcairn", "UTC-08" }, // PN
|
||||
{ "Etc/GMT+8", "UTC-08" }, // ZZ
|
||||
{ "America/Los_Angeles", "Pacific Standard Time" }, // 001
|
||||
{ "America/Vancouver", "Pacific Standard Time" }, // CA
|
||||
{ "America/Los_Angeles", "Pacific Standard Time" }, // US
|
||||
{ "America/Phoenix", "US Mountain Standard Time" }, // 001
|
||||
{ "America/Creston America/Dawson_Creek America/Fort_Nelson",
|
||||
"US Mountain Standard Time" }, // CA
|
||||
{ "America/Hermosillo", "US Mountain Standard Time" }, // MX
|
||||
{ "America/Phoenix", "US Mountain Standard Time" }, // US
|
||||
{ "Etc/GMT+7", "US Mountain Standard Time" }, // ZZ
|
||||
{ "America/Mazatlan", "Mountain Standard Time (Mexico)" }, // 001
|
||||
{ "America/Mazatlan", "Mountain Standard Time (Mexico)" }, // MX
|
||||
{ "America/Denver", "Mountain Standard Time" }, // 001
|
||||
{ "America/Edmonton America/Cambridge_Bay America/Inuvik", "Mountain Standard Time" }, // CA
|
||||
{ "America/Ciudad_Juarez", "Mountain Standard Time" }, // MX
|
||||
{ "America/Denver America/Boise", "Mountain Standard Time" }, // US
|
||||
{ "America/Whitehorse", "Yukon Standard Time" }, // 001
|
||||
{ "America/Whitehorse America/Dawson", "Yukon Standard Time" }, // CA
|
||||
{ "America/Guatemala", "Central America Standard Time" }, // 001
|
||||
{ "America/Belize", "Central America Standard Time" }, // BZ
|
||||
{ "America/Costa_Rica", "Central America Standard Time" }, // CR
|
||||
{ "Pacific/Galapagos", "Central America Standard Time" }, // EC
|
||||
{ "America/Guatemala", "Central America Standard Time" }, // GT
|
||||
{ "America/Tegucigalpa", "Central America Standard Time" }, // HN
|
||||
{ "America/Managua", "Central America Standard Time" }, // NI
|
||||
{ "America/El_Salvador", "Central America Standard Time" }, // SV
|
||||
{ "Etc/GMT+6", "Central America Standard Time" }, // ZZ
|
||||
{ "America/Chicago", "Central Standard Time" }, // 001
|
||||
{ "America/Winnipeg America/Rankin_Inlet America/Resolute", "Central Standard Time" }, // CA
|
||||
{ "America/Matamoros America/Ojinaga", "Central Standard Time" }, // MX
|
||||
{ "America/Chicago America/Indiana/Knox America/Indiana/Tell_City America/Menominee "
|
||||
"America/North_Dakota/Beulah America/North_Dakota/Center America/North_Dakota/New_Salem",
|
||||
"Central Standard Time" }, // US
|
||||
{ "Pacific/Easter", "Easter Island Standard Time" }, // 001
|
||||
{ "Pacific/Easter", "Easter Island Standard Time" }, // CL
|
||||
{ "America/Mexico_City", "Central Standard Time (Mexico)" }, // 001
|
||||
{ "America/Mexico_City America/Bahia_Banderas America/Merida America/Monterrey "
|
||||
"America/Chihuahua ",
|
||||
"Central Standard Time (Mexico)" }, // MX
|
||||
{ "America/Regina", "Canada Central Standard Time" }, // 001
|
||||
{ "America/Regina America/Swift_Current", "Canada Central Standard Time" }, // CA
|
||||
{ "America/Bogota", "SA Pacific Standard Time" }, // 001
|
||||
{ "America/Rio_Branco America/Eirunepe", "SA Pacific Standard Time" }, // BR
|
||||
{ "America/Coral_Harbour", "SA Pacific Standard Time" }, // CA
|
||||
{ "America/Bogota", "SA Pacific Standard Time" }, // CO
|
||||
{ "America/Guayaquil", "SA Pacific Standard Time" }, // EC
|
||||
{ "America/Jamaica", "SA Pacific Standard Time" }, // JM
|
||||
{ "America/Cayman", "SA Pacific Standard Time" }, // KY
|
||||
{ "America/Panama", "SA Pacific Standard Time" }, // PA
|
||||
{ "America/Lima", "SA Pacific Standard Time" }, // PE
|
||||
{ "Etc/GMT+5", "SA Pacific Standard Time" }, // ZZ
|
||||
{ "America/Cancun", "Eastern Standard Time (Mexico)" }, // 001
|
||||
{ "America/Cancun", "Eastern Standard Time (Mexico)" }, // MX
|
||||
{ "America/New_York", "Eastern Standard Time" }, // 001
|
||||
{ "America/Nassau", "Eastern Standard Time" }, // BS
|
||||
{ "America/Toronto America/Iqaluit", "Eastern Standard Time" }, // CA
|
||||
{ "America/New_York America/Detroit America/Indiana/Petersburg America/Indiana/Vincennes "
|
||||
"America/Indiana/Winamac America/Kentucky/Monticello America/Louisville",
|
||||
"Eastern Standard Time" }, // US
|
||||
{ "America/Port-au-Prince", "Haiti Standard Time" }, // 001
|
||||
{ "America/Port-au-Prince", "Haiti Standard Time" }, // HT
|
||||
{ "America/Havana", "Cuba Standard Time" }, // 001
|
||||
{ "America/Havana", "Cuba Standard Time" }, // CU
|
||||
{ "America/Indianapolis", "US Eastern Standard Time" }, // 001
|
||||
{ "America/Indianapolis America/Indiana/Marengo America/Indiana/Vevay",
|
||||
"US Eastern Standard Time" }, // US
|
||||
{ "America/Grand_Turk", "Turks And Caicos Standard Time" }, // 001
|
||||
{ "America/Grand_Turk", "Turks And Caicos Standard Time" }, // TC
|
||||
{ "America/Asuncion", "Paraguay Standard Time" }, // 001
|
||||
{ "America/Asuncion", "Paraguay Standard Time" }, // PY
|
||||
{ "America/Halifax", "Atlantic Standard Time" }, // 001
|
||||
{ "Atlantic/Bermuda", "Atlantic Standard Time" }, // BM
|
||||
{ "America/Halifax America/Glace_Bay America/Goose_Bay America/Moncton",
|
||||
"Atlantic Standard Time" }, // CA
|
||||
{ "America/Thule", "Atlantic Standard Time" }, // GL
|
||||
{ "America/Caracas", "Venezuela Standard Time" }, // 001
|
||||
{ "America/Caracas", "Venezuela Standard Time" }, // VE
|
||||
{ "America/Cuiaba", "Central Brazilian Standard Time" }, // 001
|
||||
{ "America/Cuiaba America/Campo_Grande", "Central Brazilian Standard Time" }, // BR
|
||||
{ "America/La_Paz", "SA Western Standard Time" }, // 001
|
||||
{ "America/Antigua", "SA Western Standard Time" }, // AG
|
||||
{ "America/Anguilla", "SA Western Standard Time" }, // AI
|
||||
{ "America/Aruba", "SA Western Standard Time" }, // AW
|
||||
{ "America/Barbados", "SA Western Standard Time" }, // BB
|
||||
{ "America/St_Barthelemy", "SA Western Standard Time" }, // BL
|
||||
{ "America/La_Paz", "SA Western Standard Time" }, // BO
|
||||
{ "America/Kralendijk", "SA Western Standard Time" }, // BQ
|
||||
{ "America/Manaus America/Boa_Vista America/Porto_Velho", "SA Western Standard Time" }, // BR
|
||||
{ "America/Blanc-Sablon", "SA Western Standard Time" }, // CA
|
||||
{ "America/Curacao", "SA Western Standard Time" }, // CW
|
||||
{ "America/Dominica", "SA Western Standard Time" }, // DM
|
||||
{ "America/Santo_Domingo", "SA Western Standard Time" }, // DO
|
||||
{ "America/Grenada", "SA Western Standard Time" }, // GD
|
||||
{ "America/Guadeloupe", "SA Western Standard Time" }, // GP
|
||||
{ "America/Guyana", "SA Western Standard Time" }, // GY
|
||||
{ "America/St_Kitts", "SA Western Standard Time" }, // KN
|
||||
{ "America/St_Lucia", "SA Western Standard Time" }, // LC
|
||||
{ "America/Marigot", "SA Western Standard Time" }, // MF
|
||||
{ "America/Martinique", "SA Western Standard Time" }, // MQ
|
||||
{ "America/Montserrat", "SA Western Standard Time" }, // MS
|
||||
{ "America/Puerto_Rico", "SA Western Standard Time" }, // PR
|
||||
{ "America/Lower_Princes", "SA Western Standard Time" }, // SX
|
||||
{ "America/Port_of_Spain", "SA Western Standard Time" }, // TT
|
||||
{ "America/St_Vincent", "SA Western Standard Time" }, // VC
|
||||
{ "America/Tortola", "SA Western Standard Time" }, // VG
|
||||
{ "America/St_Thomas", "SA Western Standard Time" }, // VI
|
||||
{ "Etc/GMT+4", "SA Western Standard Time" }, // ZZ
|
||||
{ "America/Santiago", "Pacific SA Standard Time" }, // 001
|
||||
{ "America/Santiago", "Pacific SA Standard Time" }, // CL
|
||||
{ "America/St_Johns", "Newfoundland Standard Time" }, // 001
|
||||
{ "America/St_Johns", "Newfoundland Standard Time" }, // CA
|
||||
{ "America/Araguaina", "Tocantins Standard Time" }, // 001
|
||||
{ "America/Araguaina", "Tocantins Standard Time" }, // BR
|
||||
{ "America/Sao_Paulo", "E. South America Standard Time" }, // 001
|
||||
{ "America/Sao_Paulo", "E. South America Standard Time" }, // BR
|
||||
{ "America/Cayenne", "SA Eastern Standard Time" }, // 001
|
||||
{ "Antarctica/Rothera Antarctica/Palmer", "SA Eastern Standard Time" }, // AQ
|
||||
{ "America/Fortaleza America/Belem America/Maceio America/Recife America/Santarem",
|
||||
"SA Eastern Standard Time" }, // BR
|
||||
{ "Atlantic/Stanley", "SA Eastern Standard Time" }, // FK
|
||||
{ "America/Cayenne", "SA Eastern Standard Time" }, // GF
|
||||
{ "America/Paramaribo", "SA Eastern Standard Time" }, // SR
|
||||
{ "Etc/GMT+3", "SA Eastern Standard Time" }, // ZZ
|
||||
{ "America/Buenos_Aires", "Argentina Standard Time" }, // 001
|
||||
{ "America/Buenos_Aires America/Argentina/La_Rioja America/Argentina/Rio_Gallegos "
|
||||
"America/Argentina/Salta America/Argentina/San_Juan America/Argentina/San_Luis "
|
||||
"America/Argentina/Tucuman America/Argentina/Ushuaia America/Catamarca America/Cordoba "
|
||||
"America/Jujuy America/Mendoza",
|
||||
"Argentina Standard Time" }, // AR
|
||||
{ "America/Godthab", "Greenland Standard Time" }, // 001
|
||||
{ "America/Godthab", "Greenland Standard Time" }, // GL
|
||||
{ "America/Montevideo", "Montevideo Standard Time" }, // 001
|
||||
{ "America/Montevideo", "Montevideo Standard Time" }, // UY
|
||||
{ "America/Punta_Arenas", "Magallanes Standard Time" }, // 001
|
||||
{ "America/Punta_Arenas America/Coyhaique", "Magallanes Standard Time" }, // CL
|
||||
{ "America/Miquelon", "Saint Pierre Standard Time" }, // 001
|
||||
{ "America/Miquelon", "Saint Pierre Standard Time" }, // PM
|
||||
{ "America/Bahia", "Bahia Standard Time" }, // 001
|
||||
{ "America/Bahia", "Bahia Standard Time" }, // BR
|
||||
{ "Etc/GMT+2", "UTC-02" }, // 001
|
||||
{ "America/Noronha", "UTC-02" }, // BR
|
||||
{ "Atlantic/South_Georgia", "UTC-02" }, // GS
|
||||
{ "Etc/GMT+2", "UTC-02" }, // ZZ
|
||||
{ "Atlantic/Azores", "Azores Standard Time" }, // 001
|
||||
{ "America/Scoresbysund", "Azores Standard Time" }, // GL
|
||||
{ "Atlantic/Azores", "Azores Standard Time" }, // PT
|
||||
{ "Atlantic/Cape_Verde", "Cape Verde Standard Time" }, // 001
|
||||
{ "Atlantic/Cape_Verde", "Cape Verde Standard Time" }, // CV
|
||||
{ "Etc/GMT+1", "Cape Verde Standard Time" }, // ZZ
|
||||
{ "Etc/UTC", "UTC" }, // 001
|
||||
{ "Etc/UTC Etc/GMT", "UTC" }, // ZZ
|
||||
{ "Europe/London", "GMT Standard Time" }, // 001
|
||||
{ "Atlantic/Canary", "GMT Standard Time" }, // ES
|
||||
{ "Atlantic/Faeroe", "GMT Standard Time" }, // FO
|
||||
{ "Europe/London", "GMT Standard Time" }, // GB
|
||||
{ "Europe/Guernsey", "GMT Standard Time" }, // GG
|
||||
{ "Europe/Dublin", "GMT Standard Time" }, // IE
|
||||
{ "Europe/Isle_of_Man", "GMT Standard Time" }, // IM
|
||||
{ "Europe/Jersey", "GMT Standard Time" }, // JE
|
||||
{ "Europe/Lisbon Atlantic/Madeira", "GMT Standard Time" }, // PT
|
||||
{ "Atlantic/Reykjavik", "Greenwich Standard Time" }, // 001
|
||||
{ "Africa/Ouagadougou", "Greenwich Standard Time" }, // BF
|
||||
{ "Africa/Abidjan", "Greenwich Standard Time" }, // CI
|
||||
{ "Africa/Accra", "Greenwich Standard Time" }, // GH
|
||||
{ "America/Danmarkshavn", "Greenwich Standard Time" }, // GL
|
||||
{ "Africa/Banjul", "Greenwich Standard Time" }, // GM
|
||||
{ "Africa/Conakry", "Greenwich Standard Time" }, // GN
|
||||
{ "Africa/Bissau", "Greenwich Standard Time" }, // GW
|
||||
{ "Atlantic/Reykjavik", "Greenwich Standard Time" }, // IS
|
||||
{ "Africa/Monrovia", "Greenwich Standard Time" }, // LR
|
||||
{ "Africa/Bamako", "Greenwich Standard Time" }, // ML
|
||||
{ "Africa/Nouakchott", "Greenwich Standard Time" }, // MR
|
||||
{ "Atlantic/St_Helena", "Greenwich Standard Time" }, // SH
|
||||
{ "Africa/Freetown", "Greenwich Standard Time" }, // SL
|
||||
{ "Africa/Dakar", "Greenwich Standard Time" }, // SN
|
||||
{ "Africa/Lome", "Greenwich Standard Time" }, // TG
|
||||
{ "Africa/Sao_Tome", "Sao Tome Standard Time" }, // 001
|
||||
{ "Africa/Sao_Tome", "Sao Tome Standard Time" }, // ST
|
||||
{ "Africa/Casablanca", "Morocco Standard Time" }, // 001
|
||||
{ "Africa/El_Aaiun", "Morocco Standard Time" }, // EH
|
||||
{ "Africa/Casablanca", "Morocco Standard Time" }, // MA
|
||||
{ "Europe/Berlin", "W. Europe Standard Time" }, // 001
|
||||
{ "Europe/Andorra", "W. Europe Standard Time" }, // AD
|
||||
{ "Europe/Vienna", "W. Europe Standard Time" }, // AT
|
||||
{ "Europe/Zurich", "W. Europe Standard Time" }, // CH
|
||||
{ "Europe/Berlin Europe/Busingen", "W. Europe Standard Time" }, // DE
|
||||
{ "Europe/Gibraltar", "W. Europe Standard Time" }, // GI
|
||||
{ "Europe/Rome", "W. Europe Standard Time" }, // IT
|
||||
{ "Europe/Vaduz", "W. Europe Standard Time" }, // LI
|
||||
{ "Europe/Luxembourg", "W. Europe Standard Time" }, // LU
|
||||
{ "Europe/Monaco", "W. Europe Standard Time" }, // MC
|
||||
{ "Europe/Malta", "W. Europe Standard Time" }, // MT
|
||||
{ "Europe/Amsterdam", "W. Europe Standard Time" }, // NL
|
||||
{ "Europe/Oslo", "W. Europe Standard Time" }, // NO
|
||||
{ "Europe/Stockholm", "W. Europe Standard Time" }, // SE
|
||||
{ "Arctic/Longyearbyen", "W. Europe Standard Time" }, // SJ
|
||||
{ "Europe/San_Marino", "W. Europe Standard Time" }, // SM
|
||||
{ "Europe/Vatican", "W. Europe Standard Time" }, // VA
|
||||
{ "Europe/Budapest", "Central Europe Standard Time" }, // 001
|
||||
{ "Europe/Tirane", "Central Europe Standard Time" }, // AL
|
||||
{ "Europe/Prague", "Central Europe Standard Time" }, // CZ
|
||||
{ "Europe/Budapest", "Central Europe Standard Time" }, // HU
|
||||
{ "Europe/Podgorica", "Central Europe Standard Time" }, // ME
|
||||
{ "Europe/Belgrade", "Central Europe Standard Time" }, // RS
|
||||
{ "Europe/Ljubljana", "Central Europe Standard Time" }, // SI
|
||||
{ "Europe/Bratislava", "Central Europe Standard Time" }, // SK
|
||||
{ "Europe/Paris", "Romance Standard Time" }, // 001
|
||||
{ "Europe/Brussels", "Romance Standard Time" }, // BE
|
||||
{ "Europe/Copenhagen", "Romance Standard Time" }, // DK
|
||||
{ "Europe/Madrid Africa/Ceuta", "Romance Standard Time" }, // ES
|
||||
{ "Europe/Paris", "Romance Standard Time" }, // FR
|
||||
{ "Europe/Warsaw", "Central European Standard Time" }, // 001
|
||||
{ "Europe/Sarajevo", "Central European Standard Time" }, // BA
|
||||
{ "Europe/Zagreb", "Central European Standard Time" }, // HR
|
||||
{ "Europe/Skopje", "Central European Standard Time" }, // MK
|
||||
{ "Europe/Warsaw", "Central European Standard Time" }, // PL
|
||||
{ "Africa/Lagos", "W. Central Africa Standard Time" }, // 001
|
||||
{ "Africa/Luanda", "W. Central Africa Standard Time" }, // AO
|
||||
{ "Africa/Porto-Novo", "W. Central Africa Standard Time" }, // BJ
|
||||
{ "Africa/Kinshasa", "W. Central Africa Standard Time" }, // CD
|
||||
{ "Africa/Bangui", "W. Central Africa Standard Time" }, // CF
|
||||
{ "Africa/Brazzaville", "W. Central Africa Standard Time" }, // CG
|
||||
{ "Africa/Douala", "W. Central Africa Standard Time" }, // CM
|
||||
{ "Africa/Algiers", "W. Central Africa Standard Time" }, // DZ
|
||||
{ "Africa/Libreville", "W. Central Africa Standard Time" }, // GA
|
||||
{ "Africa/Malabo", "W. Central Africa Standard Time" }, // GQ
|
||||
{ "Africa/Niamey", "W. Central Africa Standard Time" }, // NE
|
||||
{ "Africa/Lagos", "W. Central Africa Standard Time" }, // NG
|
||||
{ "Africa/Ndjamena", "W. Central Africa Standard Time" }, // TD
|
||||
{ "Africa/Tunis", "W. Central Africa Standard Time" }, // TN
|
||||
{ "Etc/GMT-1", "W. Central Africa Standard Time" }, // ZZ
|
||||
{ "Asia/Amman", "Jordan Standard Time" }, // 001
|
||||
{ "Asia/Amman", "Jordan Standard Time" }, // JO
|
||||
{ "Europe/Bucharest", "GTB Standard Time" }, // 001
|
||||
{ "Asia/Nicosia Asia/Famagusta", "GTB Standard Time" }, // CY
|
||||
{ "Europe/Athens", "GTB Standard Time" }, // GR
|
||||
{ "Europe/Bucharest", "GTB Standard Time" }, // RO
|
||||
{ "Asia/Beirut", "Middle East Standard Time" }, // 001
|
||||
{ "Asia/Beirut", "Middle East Standard Time" }, // LB
|
||||
{ "Africa/Cairo", "Egypt Standard Time" }, // 001
|
||||
{ "Africa/Cairo", "Egypt Standard Time" }, // EG
|
||||
{ "Europe/Chisinau", "E. Europe Standard Time" }, // 001
|
||||
{ "Europe/Chisinau", "E. Europe Standard Time" }, // MD
|
||||
{ "Asia/Damascus", "Syria Standard Time" }, // 001
|
||||
{ "Asia/Damascus", "Syria Standard Time" }, // SY
|
||||
{ "Asia/Hebron", "West Bank Standard Time" }, // 001
|
||||
{ "Asia/Hebron Asia/Gaza", "West Bank Standard Time" }, // PS
|
||||
{ "Africa/Johannesburg", "South Africa Standard Time" }, // 001
|
||||
{ "Africa/Bujumbura", "South Africa Standard Time" }, // BI
|
||||
{ "Africa/Gaborone", "South Africa Standard Time" }, // BW
|
||||
{ "Africa/Lubumbashi", "South Africa Standard Time" }, // CD
|
||||
{ "Africa/Maseru", "South Africa Standard Time" }, // LS
|
||||
{ "Africa/Blantyre", "South Africa Standard Time" }, // MW
|
||||
{ "Africa/Maputo", "South Africa Standard Time" }, // MZ
|
||||
{ "Africa/Kigali", "South Africa Standard Time" }, // RW
|
||||
{ "Africa/Mbabane", "South Africa Standard Time" }, // SZ
|
||||
{ "Africa/Johannesburg", "South Africa Standard Time" }, // ZA
|
||||
{ "Africa/Lusaka", "South Africa Standard Time" }, // ZM
|
||||
{ "Africa/Harare", "South Africa Standard Time" }, // ZW
|
||||
{ "Etc/GMT-2", "South Africa Standard Time" }, // ZZ
|
||||
{ "Europe/Kiev", "FLE Standard Time" }, // 001
|
||||
{ "Europe/Mariehamn", "FLE Standard Time" }, // AX
|
||||
{ "Europe/Sofia", "FLE Standard Time" }, // BG
|
||||
{ "Europe/Tallinn", "FLE Standard Time" }, // EE
|
||||
{ "Europe/Helsinki", "FLE Standard Time" }, // FI
|
||||
{ "Europe/Vilnius", "FLE Standard Time" }, // LT
|
||||
{ "Europe/Riga", "FLE Standard Time" }, // LV
|
||||
{ "Europe/Kiev", "FLE Standard Time" }, // UA
|
||||
{ "Asia/Jerusalem", "Israel Standard Time" }, // 001
|
||||
{ "Asia/Jerusalem", "Israel Standard Time" }, // IL
|
||||
{ "Africa/Juba", "South Sudan Standard Time" }, // 001
|
||||
{ "Africa/Juba", "South Sudan Standard Time" }, // SS
|
||||
{ "Europe/Kaliningrad", "Kaliningrad Standard Time" }, // 001
|
||||
{ "Europe/Kaliningrad", "Kaliningrad Standard Time" }, // RU
|
||||
{ "Africa/Khartoum", "Sudan Standard Time" }, // 001
|
||||
{ "Africa/Khartoum", "Sudan Standard Time" }, // SD
|
||||
{ "Africa/Tripoli", "Libya Standard Time" }, // 001
|
||||
{ "Africa/Tripoli", "Libya Standard Time" }, // LY
|
||||
{ "Africa/Windhoek", "Namibia Standard Time" }, // 001
|
||||
{ "Africa/Windhoek", "Namibia Standard Time" }, // NA
|
||||
{ "Asia/Baghdad", "Arabic Standard Time" }, // 001
|
||||
{ "Asia/Baghdad", "Arabic Standard Time" }, // IQ
|
||||
{ "Europe/Istanbul", "Turkey Standard Time" }, // 001
|
||||
{ "Europe/Istanbul", "Turkey Standard Time" }, // TR
|
||||
{ "Asia/Riyadh", "Arab Standard Time" }, // 001
|
||||
{ "Asia/Bahrain", "Arab Standard Time" }, // BH
|
||||
{ "Asia/Kuwait", "Arab Standard Time" }, // KW
|
||||
{ "Asia/Qatar", "Arab Standard Time" }, // QA
|
||||
{ "Asia/Riyadh", "Arab Standard Time" }, // SA
|
||||
{ "Asia/Aden", "Arab Standard Time" }, // YE
|
||||
{ "Europe/Minsk", "Belarus Standard Time" }, // 001
|
||||
{ "Europe/Minsk", "Belarus Standard Time" }, // BY
|
||||
{ "Europe/Moscow", "Russian Standard Time" }, // 001
|
||||
{ "Europe/Moscow Europe/Kirov", "Russian Standard Time" }, // RU
|
||||
{ "Europe/Simferopol", "Russian Standard Time" }, // UA
|
||||
{ "Africa/Nairobi", "E. Africa Standard Time" }, // 001
|
||||
{ "Antarctica/Syowa", "E. Africa Standard Time" }, // AQ
|
||||
{ "Africa/Djibouti", "E. Africa Standard Time" }, // DJ
|
||||
{ "Africa/Asmera", "E. Africa Standard Time" }, // ER
|
||||
{ "Africa/Addis_Ababa", "E. Africa Standard Time" }, // ET
|
||||
{ "Africa/Nairobi", "E. Africa Standard Time" }, // KE
|
||||
{ "Indian/Comoro", "E. Africa Standard Time" }, // KM
|
||||
{ "Indian/Antananarivo", "E. Africa Standard Time" }, // MG
|
||||
{ "Africa/Mogadishu", "E. Africa Standard Time" }, // SO
|
||||
{ "Africa/Dar_es_Salaam", "E. Africa Standard Time" }, // TZ
|
||||
{ "Africa/Kampala", "E. Africa Standard Time" }, // UG
|
||||
{ "Indian/Mayotte", "E. Africa Standard Time" }, // YT
|
||||
{ "Etc/GMT-3", "E. Africa Standard Time" }, // ZZ
|
||||
{ "Asia/Tehran", "Iran Standard Time" }, // 001
|
||||
{ "Asia/Tehran", "Iran Standard Time" }, // IR
|
||||
{ "Asia/Dubai", "Arabian Standard Time" }, // 001
|
||||
{ "Asia/Dubai", "Arabian Standard Time" }, // AE
|
||||
{ "Asia/Muscat", "Arabian Standard Time" }, // OM
|
||||
{ "Etc/GMT-4", "Arabian Standard Time" }, // ZZ
|
||||
{ "Europe/Astrakhan", "Astrakhan Standard Time" }, // 001
|
||||
{ "Europe/Astrakhan Europe/Ulyanovsk", "Astrakhan Standard Time" }, // RU
|
||||
{ "Asia/Baku", "Azerbaijan Standard Time" }, // 001
|
||||
{ "Asia/Baku", "Azerbaijan Standard Time" }, // AZ
|
||||
{ "Europe/Samara", "Russia Time Zone 3" }, // 001
|
||||
{ "Europe/Samara", "Russia Time Zone 3" }, // RU
|
||||
{ "Indian/Mauritius", "Mauritius Standard Time" }, // 001
|
||||
{ "Indian/Mauritius", "Mauritius Standard Time" }, // MU
|
||||
{ "Indian/Reunion", "Mauritius Standard Time" }, // RE
|
||||
{ "Indian/Mahe", "Mauritius Standard Time" }, // SC
|
||||
{ "Europe/Saratov", "Saratov Standard Time" }, // 001
|
||||
{ "Europe/Saratov", "Saratov Standard Time" }, // RU
|
||||
{ "Asia/Tbilisi", "Georgian Standard Time" }, // 001
|
||||
{ "Asia/Tbilisi", "Georgian Standard Time" }, // GE
|
||||
{ "Europe/Volgograd", "Volgograd Standard Time" }, // 001
|
||||
{ "Europe/Volgograd", "Volgograd Standard Time" }, // RU
|
||||
{ "Asia/Yerevan", "Caucasus Standard Time" }, // 001
|
||||
{ "Asia/Yerevan", "Caucasus Standard Time" }, // AM
|
||||
{ "Asia/Kabul", "Afghanistan Standard Time" }, // 001
|
||||
{ "Asia/Kabul", "Afghanistan Standard Time" }, // AF
|
||||
{ "Asia/Tashkent", "West Asia Standard Time" }, // 001
|
||||
{ "Antarctica/Mawson", "West Asia Standard Time" }, // AQ
|
||||
{ "Asia/Oral Asia/Almaty Asia/Aqtau Asia/Aqtobe Asia/Atyrau Asia/Qostanay",
|
||||
"West Asia Standard Time" }, // KZ
|
||||
{ "Indian/Maldives", "West Asia Standard Time" }, // MV
|
||||
{ "Indian/Kerguelen", "West Asia Standard Time" }, // TF
|
||||
{ "Asia/Dushanbe", "West Asia Standard Time" }, // TJ
|
||||
{ "Asia/Ashgabat", "West Asia Standard Time" }, // TM
|
||||
{ "Asia/Tashkent Asia/Samarkand", "West Asia Standard Time" }, // UZ
|
||||
{ "Etc/GMT-5", "West Asia Standard Time" }, // ZZ
|
||||
{ "Asia/Yekaterinburg", "Ekaterinburg Standard Time" }, // 001
|
||||
{ "Asia/Yekaterinburg", "Ekaterinburg Standard Time" }, // RU
|
||||
{ "Asia/Karachi", "Pakistan Standard Time" }, // 001
|
||||
{ "Asia/Karachi", "Pakistan Standard Time" }, // PK
|
||||
{ "Asia/Qyzylorda", "Qyzylorda Standard Time" }, // 001
|
||||
{ "Asia/Qyzylorda", "Qyzylorda Standard Time" }, // KZ
|
||||
{ "Asia/Calcutta", "India Standard Time" }, // 001
|
||||
{ "Asia/Calcutta", "India Standard Time" }, // IN
|
||||
{ "Asia/Colombo", "Sri Lanka Standard Time" }, // 001
|
||||
{ "Asia/Colombo", "Sri Lanka Standard Time" }, // LK
|
||||
{ "Asia/Katmandu", "Nepal Standard Time" }, // 001
|
||||
{ "Asia/Katmandu", "Nepal Standard Time" }, // NP
|
||||
{ "Asia/Bishkek", "Central Asia Standard Time" }, // 001
|
||||
{ "Antarctica/Vostok", "Central Asia Standard Time" }, // AQ
|
||||
{ "Asia/Urumqi", "Central Asia Standard Time" }, // CN
|
||||
{ "Indian/Chagos", "Central Asia Standard Time" }, // IO
|
||||
{ "Asia/Bishkek", "Central Asia Standard Time" }, // KG
|
||||
{ "Etc/GMT-6", "Central Asia Standard Time" }, // ZZ
|
||||
{ "Asia/Dhaka", "Bangladesh Standard Time" }, // 001
|
||||
{ "Asia/Dhaka", "Bangladesh Standard Time" }, // BD
|
||||
{ "Asia/Thimphu", "Bangladesh Standard Time" }, // BT
|
||||
{ "Asia/Omsk", "Omsk Standard Time" }, // 001
|
||||
{ "Asia/Omsk", "Omsk Standard Time" }, // RU
|
||||
{ "Asia/Rangoon", "Myanmar Standard Time" }, // 001
|
||||
{ "Indian/Cocos", "Myanmar Standard Time" }, // CC
|
||||
{ "Asia/Rangoon", "Myanmar Standard Time" }, // MM
|
||||
{ "Asia/Bangkok", "SE Asia Standard Time" }, // 001
|
||||
{ "Antarctica/Davis", "SE Asia Standard Time" }, // AQ
|
||||
{ "Indian/Christmas", "SE Asia Standard Time" }, // CX
|
||||
{ "Asia/Jakarta Asia/Pontianak", "SE Asia Standard Time" }, // ID
|
||||
{ "Asia/Phnom_Penh", "SE Asia Standard Time" }, // KH
|
||||
{ "Asia/Vientiane", "SE Asia Standard Time" }, // LA
|
||||
{ "Asia/Bangkok", "SE Asia Standard Time" }, // TH
|
||||
{ "Asia/Saigon", "SE Asia Standard Time" }, // VN
|
||||
{ "Etc/GMT-7", "SE Asia Standard Time" }, // ZZ
|
||||
{ "Asia/Barnaul", "Altai Standard Time" }, // 001
|
||||
{ "Asia/Barnaul", "Altai Standard Time" }, // RU
|
||||
{ "Asia/Hovd", "W. Mongolia Standard Time" }, // 001
|
||||
{ "Asia/Hovd", "W. Mongolia Standard Time" }, // MN
|
||||
{ "Asia/Krasnoyarsk", "North Asia Standard Time" }, // 001
|
||||
{ "Asia/Krasnoyarsk Asia/Novokuznetsk", "North Asia Standard Time" }, // RU
|
||||
{ "Asia/Novosibirsk", "N. Central Asia Standard Time" }, // 001
|
||||
{ "Asia/Novosibirsk", "N. Central Asia Standard Time" }, // RU
|
||||
{ "Asia/Tomsk", "Tomsk Standard Time" }, // 001
|
||||
{ "Asia/Tomsk", "Tomsk Standard Time" }, // RU
|
||||
{ "Asia/Shanghai", "China Standard Time" }, // 001
|
||||
{ "Asia/Shanghai", "China Standard Time" }, // CN
|
||||
{ "Asia/Hong_Kong", "China Standard Time" }, // HK
|
||||
{ "Asia/Macau", "China Standard Time" }, // MO
|
||||
{ "Asia/Irkutsk", "North Asia East Standard Time" }, // 001
|
||||
{ "Asia/Irkutsk", "North Asia East Standard Time" }, // RU
|
||||
{ "Asia/Singapore", "Singapore Standard Time" }, // 001
|
||||
{ "Asia/Brunei", "Singapore Standard Time" }, // BN
|
||||
{ "Asia/Makassar", "Singapore Standard Time" }, // ID
|
||||
{ "Asia/Kuala_Lumpur Asia/Kuching", "Singapore Standard Time" }, // MY
|
||||
{ "Asia/Manila", "Singapore Standard Time" }, // PH
|
||||
{ "Asia/Singapore", "Singapore Standard Time" }, // SG
|
||||
{ "Etc/GMT-8", "Singapore Standard Time" }, // ZZ
|
||||
{ "Australia/Perth", "W. Australia Standard Time" }, // 001
|
||||
{ "Australia/Perth", "W. Australia Standard Time" }, // AU
|
||||
{ "Asia/Taipei", "Taipei Standard Time" }, // 001
|
||||
{ "Asia/Taipei", "Taipei Standard Time" }, // TW
|
||||
{ "Asia/Ulaanbaatar", "Ulaanbaatar Standard Time" }, // 001
|
||||
{ "Asia/Ulaanbaatar", "Ulaanbaatar Standard Time" }, // MN
|
||||
{ "Australia/Eucla", "Aus Central W. Standard Time" }, // 001
|
||||
{ "Australia/Eucla", "Aus Central W. Standard Time" }, // AU
|
||||
{ "Asia/Chita", "Transbaikal Standard Time" }, // 001
|
||||
{ "Asia/Chita", "Transbaikal Standard Time" }, // RU
|
||||
{ "Asia/Tokyo", "Tokyo Standard Time" }, // 001
|
||||
{ "Asia/Jayapura", "Tokyo Standard Time" }, // ID
|
||||
{ "Asia/Tokyo", "Tokyo Standard Time" }, // JP
|
||||
{ "Pacific/Palau", "Tokyo Standard Time" }, // PW
|
||||
{ "Asia/Dili", "Tokyo Standard Time" }, // TL
|
||||
{ "Etc/GMT-9", "Tokyo Standard Time" }, // ZZ
|
||||
{ "Asia/Pyongyang", "North Korea Standard Time" }, // 001
|
||||
{ "Asia/Pyongyang", "North Korea Standard Time" }, // KP
|
||||
{ "Asia/Seoul", "Korea Standard Time" }, // 001
|
||||
{ "Asia/Seoul", "Korea Standard Time" }, // KR
|
||||
{ "Asia/Yakutsk", "Yakutsk Standard Time" }, // 001
|
||||
{ "Asia/Yakutsk Asia/Khandyga", "Yakutsk Standard Time" }, // RU
|
||||
{ "Australia/Adelaide", "Cen. Australia Standard Time" }, // 001
|
||||
{ "Australia/Adelaide Australia/Broken_Hill", "Cen. Australia Standard Time" }, // AU
|
||||
{ "Australia/Darwin", "AUS Central Standard Time" }, // 001
|
||||
{ "Australia/Darwin", "AUS Central Standard Time" }, // AU
|
||||
{ "Australia/Brisbane", "E. Australia Standard Time" }, // 001
|
||||
{ "Australia/Brisbane Australia/Lindeman", "E. Australia Standard Time" }, // AU
|
||||
{ "Australia/Sydney", "AUS Eastern Standard Time" }, // 001
|
||||
{ "Australia/Sydney Australia/Melbourne", "AUS Eastern Standard Time" }, // AU
|
||||
{ "Pacific/Port_Moresby", "West Pacific Standard Time" }, // 001
|
||||
{ "Antarctica/DumontDUrville", "West Pacific Standard Time" }, // AQ
|
||||
{ "Pacific/Truk", "West Pacific Standard Time" }, // FM
|
||||
{ "Pacific/Guam", "West Pacific Standard Time" }, // GU
|
||||
{ "Pacific/Saipan", "West Pacific Standard Time" }, // MP
|
||||
{ "Pacific/Port_Moresby", "West Pacific Standard Time" }, // PG
|
||||
{ "Etc/GMT-10", "West Pacific Standard Time" }, // ZZ
|
||||
{ "Australia/Hobart", "Tasmania Standard Time" }, // 001
|
||||
{ "Australia/Hobart Antarctica/Macquarie", "Tasmania Standard Time" }, // AU
|
||||
{ "Asia/Vladivostok", "Vladivostok Standard Time" }, // 001
|
||||
{ "Asia/Vladivostok Asia/Ust-Nera", "Vladivostok Standard Time" }, // RU
|
||||
{ "Australia/Lord_Howe", "Lord Howe Standard Time" }, // 001
|
||||
{ "Australia/Lord_Howe", "Lord Howe Standard Time" }, // AU
|
||||
{ "Pacific/Bougainville", "Bougainville Standard Time" }, // 001
|
||||
{ "Pacific/Bougainville", "Bougainville Standard Time" }, // PG
|
||||
{ "Asia/Srednekolymsk", "Russia Time Zone 10" }, // 001
|
||||
{ "Asia/Srednekolymsk", "Russia Time Zone 10" }, // RU
|
||||
{ "Asia/Magadan", "Magadan Standard Time" }, // 001
|
||||
{ "Asia/Magadan", "Magadan Standard Time" }, // RU
|
||||
{ "Pacific/Norfolk", "Norfolk Standard Time" }, // 001
|
||||
{ "Pacific/Norfolk", "Norfolk Standard Time" }, // NF
|
||||
{ "Asia/Sakhalin", "Sakhalin Standard Time" }, // 001
|
||||
{ "Asia/Sakhalin", "Sakhalin Standard Time" }, // RU
|
||||
{ "Pacific/Guadalcanal", "Central Pacific Standard Time" }, // 001
|
||||
{ "Antarctica/Casey", "Central Pacific Standard Time" }, // AQ
|
||||
{ "Pacific/Ponape Pacific/Kosrae", "Central Pacific Standard Time" }, // FM
|
||||
{ "Pacific/Noumea", "Central Pacific Standard Time" }, // NC
|
||||
{ "Pacific/Guadalcanal", "Central Pacific Standard Time" }, // SB
|
||||
{ "Pacific/Efate", "Central Pacific Standard Time" }, // VU
|
||||
{ "Etc/GMT-11", "Central Pacific Standard Time" }, // ZZ
|
||||
{ "Asia/Kamchatka", "Russia Time Zone 11" }, // 001
|
||||
{ "Asia/Kamchatka Asia/Anadyr", "Russia Time Zone 11" }, // RU
|
||||
{ "Pacific/Auckland", "New Zealand Standard Time" }, // 001
|
||||
{ "Antarctica/McMurdo", "New Zealand Standard Time" }, // AQ
|
||||
{ "Pacific/Auckland", "New Zealand Standard Time" }, // NZ
|
||||
{ "Etc/GMT-12", "UTC+12" }, // 001
|
||||
{ "Pacific/Tarawa", "UTC+12" }, // KI
|
||||
{ "Pacific/Majuro Pacific/Kwajalein", "UTC+12" }, // MH
|
||||
{ "Pacific/Nauru", "UTC+12" }, // NR
|
||||
{ "Pacific/Funafuti", "UTC+12" }, // TV
|
||||
{ "Pacific/Wake", "UTC+12" }, // UM
|
||||
{ "Pacific/Wallis", "UTC+12" }, // WF
|
||||
{ "Etc/GMT-12", "UTC+12" }, // ZZ
|
||||
{ "Pacific/Fiji", "Fiji Standard Time" }, // 001
|
||||
{ "Pacific/Fiji", "Fiji Standard Time" }, // FJ
|
||||
{ "Pacific/Chatham", "Chatham Islands Standard Time" }, // 001
|
||||
{ "Pacific/Chatham", "Chatham Islands Standard Time" }, // NZ
|
||||
{ "Etc/GMT-13", "UTC+13" }, // 001
|
||||
{ "Pacific/Enderbury", "UTC+13" }, // KI
|
||||
{ "Pacific/Fakaofo", "UTC+13" }, // TK
|
||||
{ "Etc/GMT-13", "UTC+13" }, // ZZ
|
||||
{ "Pacific/Tongatapu", "Tonga Standard Time" }, // 001
|
||||
{ "Pacific/Tongatapu", "Tonga Standard Time" }, // TO
|
||||
{ "Pacific/Apia", "Samoa Standard Time" }, // 001
|
||||
{ "Pacific/Apia", "Samoa Standard Time" }, // WS
|
||||
{ "Pacific/Kiritimati", "Line Islands Standard Time" }, // 001
|
||||
{ "Pacific/Kiritimati", "Line Islands Standard Time" }, // KI
|
||||
{ "Etc/GMT-14", "Line Islands Standard Time" }, // ZZ
|
||||
};
|
||||
|
||||
const size_t WindowsZonesNrElements = ARRAYSIZE(WindowsZones);
|
||||
18
third_party/FreeRDP/winpr/libwinpr/timezone/WindowsZones.h
vendored
Normal file
18
third_party/FreeRDP/winpr/libwinpr/timezone/WindowsZones.h
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Automatically generated with scripts/update-windows-zones.py
|
||||
*/
|
||||
#ifndef WINPR_WINDOWS_ZONES_H_
|
||||
#define WINPR_WINDOWS_ZONES_H_
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* tzid;
|
||||
const char* windows;
|
||||
} WINDOWS_TZID_ENTRY;
|
||||
|
||||
extern const WINDOWS_TZID_ENTRY WindowsZones[];
|
||||
extern const size_t WindowsZonesNrElements;
|
||||
|
||||
#endif /* WINPR_WINDOWS_ZONES_H_ */
|
||||
942
third_party/FreeRDP/winpr/libwinpr/timezone/timezone.c
vendored
Normal file
942
third_party/FreeRDP/winpr/libwinpr/timezone/timezone.c
vendored
Normal file
@@ -0,0 +1,942 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Time Zone
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/environment.h>
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/timezone.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/file.h>
|
||||
#include "../log.h"
|
||||
#include "timezone.h"
|
||||
|
||||
#define TAG WINPR_TAG("timezone")
|
||||
|
||||
#include "TimeZoneNameMap.h"
|
||||
#include "TimeZoneIanaAbbrevMap.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
static char* winpr_read_unix_timezone_identifier_from_file(FILE* fp)
|
||||
{
|
||||
const INT CHUNK_SIZE = 32;
|
||||
size_t rc = 0;
|
||||
size_t read = 0;
|
||||
size_t length = CHUNK_SIZE;
|
||||
|
||||
char* tzid = malloc(length);
|
||||
if (!tzid)
|
||||
return nullptr;
|
||||
|
||||
do
|
||||
{
|
||||
rc = fread(tzid + read, 1, length - read - 1UL, fp);
|
||||
if (rc > 0)
|
||||
read += rc;
|
||||
|
||||
if (read < (length - 1UL))
|
||||
break;
|
||||
|
||||
if (read > length - 1UL)
|
||||
{
|
||||
free(tzid);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
length += CHUNK_SIZE;
|
||||
char* tmp = (char*)realloc(tzid, length);
|
||||
if (!tmp)
|
||||
{
|
||||
free(tzid);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tzid = tmp;
|
||||
} while (rc > 0);
|
||||
|
||||
if (ferror(fp))
|
||||
{
|
||||
free(tzid);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tzid[read] = '\0';
|
||||
if (read > 0)
|
||||
{
|
||||
if (tzid[read - 1] == '\n')
|
||||
tzid[read - 1] = '\0';
|
||||
}
|
||||
|
||||
return tzid;
|
||||
}
|
||||
|
||||
static char* winpr_get_timezone_from_link(const char* links[], size_t count)
|
||||
{
|
||||
const char* _links[] = { "/etc/localtime", "/etc/TZ" };
|
||||
|
||||
if (links == nullptr)
|
||||
{
|
||||
links = _links;
|
||||
count = ARRAYSIZE(_links);
|
||||
}
|
||||
|
||||
/*
|
||||
* On linux distros such as Redhat or Archlinux, a symlink at /etc/localtime
|
||||
* will point to /usr/share/zoneinfo/region/place where region/place could be
|
||||
* America/Montreal for example.
|
||||
* Some distributions do have to symlink at /etc/TZ.
|
||||
*/
|
||||
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
char* tzid = nullptr;
|
||||
const char* link = links[x];
|
||||
char* buf = realpath(link, nullptr);
|
||||
|
||||
if (buf)
|
||||
{
|
||||
size_t sep = 0;
|
||||
size_t alloc = 0;
|
||||
size_t pos = 0;
|
||||
size_t len = pos = strlen(buf);
|
||||
|
||||
/* find the position of the 2nd to last "/" */
|
||||
for (size_t i = 1; i <= len; i++)
|
||||
{
|
||||
const size_t curpos = len - i;
|
||||
const char cur = buf[curpos];
|
||||
|
||||
if (cur == '/')
|
||||
sep++;
|
||||
if (sep >= 2)
|
||||
{
|
||||
alloc = i;
|
||||
pos = len - i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((len == 0) || (sep != 2))
|
||||
goto end;
|
||||
|
||||
tzid = (char*)calloc(alloc + 1, sizeof(char));
|
||||
|
||||
if (!tzid)
|
||||
goto end;
|
||||
|
||||
strncpy(tzid, &buf[pos], alloc);
|
||||
WLog_DBG(TAG, "tzid: %s", tzid);
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
free(buf);
|
||||
if (tzid)
|
||||
return tzid;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(ANDROID)
|
||||
#include "../utils/android.h"
|
||||
|
||||
static char* winpr_get_android_timezone_identifier(void)
|
||||
{
|
||||
char* tzid = nullptr;
|
||||
JNIEnv* jniEnv;
|
||||
|
||||
/* Preferred: Try to get identifier from java TimeZone class */
|
||||
if (jniVm && ((*jniVm)->GetEnv(jniVm, (void**)&jniEnv, JNI_VERSION_1_6) == JNI_OK))
|
||||
{
|
||||
const char* raw;
|
||||
jclass jObjClass;
|
||||
jobject jObj;
|
||||
jmethodID jDefaultTimezone;
|
||||
jmethodID jTimezoneIdentifier;
|
||||
jstring tzJId;
|
||||
jboolean attached = (*jniVm)->AttachCurrentThread(jniVm, &jniEnv, nullptr);
|
||||
jObjClass = (*jniEnv)->FindClass(jniEnv, "java/util/TimeZone");
|
||||
|
||||
if (!jObjClass)
|
||||
goto fail;
|
||||
|
||||
jDefaultTimezone =
|
||||
(*jniEnv)->GetStaticMethodID(jniEnv, jObjClass, "getDefault", "()Ljava/util/TimeZone;");
|
||||
|
||||
if (!jDefaultTimezone)
|
||||
goto fail;
|
||||
|
||||
jObj = (*jniEnv)->CallStaticObjectMethod(jniEnv, jObjClass, jDefaultTimezone);
|
||||
|
||||
if (!jObj)
|
||||
goto fail;
|
||||
|
||||
jTimezoneIdentifier =
|
||||
(*jniEnv)->GetMethodID(jniEnv, jObjClass, "getID", "()Ljava/lang/String;");
|
||||
|
||||
if (!jTimezoneIdentifier)
|
||||
goto fail;
|
||||
|
||||
tzJId = (*jniEnv)->CallObjectMethod(jniEnv, jObj, jTimezoneIdentifier);
|
||||
|
||||
if (!tzJId)
|
||||
goto fail;
|
||||
|
||||
raw = (*jniEnv)->GetStringUTFChars(jniEnv, tzJId, 0);
|
||||
|
||||
if (raw)
|
||||
tzid = _strdup(raw);
|
||||
|
||||
(*jniEnv)->ReleaseStringUTFChars(jniEnv, tzJId, raw);
|
||||
fail:
|
||||
|
||||
if (attached)
|
||||
(*jniVm)->DetachCurrentThread(jniVm);
|
||||
}
|
||||
|
||||
/* Fall back to property, might not be available. */
|
||||
if (!tzid)
|
||||
{
|
||||
FILE* fp = popen("getprop persist.sys.timezone", "r");
|
||||
|
||||
if (fp)
|
||||
{
|
||||
tzid = winpr_read_unix_timezone_identifier_from_file(fp);
|
||||
pclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
return tzid;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char* winpr_get_unix_timezone_identifier_from_file(void)
|
||||
{
|
||||
#if defined(ANDROID)
|
||||
return winpr_get_android_timezone_identifier();
|
||||
#else
|
||||
FILE* fp = nullptr;
|
||||
char* tzid = nullptr;
|
||||
#if !defined(WINPR_TIMEZONE_FILE)
|
||||
#error \
|
||||
"Please define WINPR_TIMEZONE_FILE with the path to your timezone file (e.g. /etc/timezone or similar)"
|
||||
#else
|
||||
fp = winpr_fopen(WINPR_TIMEZONE_FILE, "r");
|
||||
#endif
|
||||
|
||||
if (nullptr == fp)
|
||||
return nullptr;
|
||||
|
||||
tzid = winpr_read_unix_timezone_identifier_from_file(fp);
|
||||
(void)fclose(fp);
|
||||
if (tzid != nullptr)
|
||||
WLog_DBG(TAG, "tzid: %s", tzid);
|
||||
return tzid;
|
||||
#endif
|
||||
}
|
||||
|
||||
static char* winpr_time_zone_from_env(void)
|
||||
{
|
||||
LPCSTR tz = "TZ";
|
||||
char* tzid = nullptr;
|
||||
|
||||
DWORD nSize = GetEnvironmentVariableA(tz, nullptr, 0);
|
||||
if (nSize > 0)
|
||||
{
|
||||
tzid = (char*)calloc(nSize, sizeof(char));
|
||||
if (!tzid)
|
||||
goto fail;
|
||||
if (!GetEnvironmentVariableA(tz, tzid, nSize))
|
||||
goto fail;
|
||||
else if (tzid[0] == ':')
|
||||
{
|
||||
/* Remove leading colon, see tzset(3) */
|
||||
memmove(tzid, tzid + 1, nSize - sizeof(char));
|
||||
}
|
||||
}
|
||||
|
||||
return tzid;
|
||||
|
||||
fail:
|
||||
free(tzid);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static char* winpr_translate_time_zone(const char* tzid)
|
||||
{
|
||||
const char* zipath = "/usr/share/zoneinfo/";
|
||||
char* buf = nullptr;
|
||||
const char* links[] = { buf };
|
||||
|
||||
if (!tzid)
|
||||
return nullptr;
|
||||
|
||||
if (tzid[0] == '/')
|
||||
{
|
||||
/* Full path given in TZ */
|
||||
links[0] = tzid;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bsize = 0;
|
||||
winpr_asprintf(&buf, &bsize, "%s%s", zipath, tzid);
|
||||
links[0] = buf;
|
||||
}
|
||||
|
||||
char* ntzid = winpr_get_timezone_from_link(links, 1);
|
||||
free(buf);
|
||||
return ntzid;
|
||||
}
|
||||
|
||||
static char* winpr_guess_time_zone(void)
|
||||
{
|
||||
char* tzid = winpr_time_zone_from_env();
|
||||
if (tzid)
|
||||
goto end;
|
||||
tzid = winpr_get_unix_timezone_identifier_from_file();
|
||||
if (tzid)
|
||||
goto end;
|
||||
tzid = winpr_get_timezone_from_link(nullptr, 0);
|
||||
if (tzid)
|
||||
goto end;
|
||||
|
||||
end:
|
||||
{
|
||||
char* ntzid = winpr_translate_time_zone(tzid);
|
||||
if (ntzid)
|
||||
{
|
||||
free(tzid);
|
||||
return ntzid;
|
||||
}
|
||||
return tzid;
|
||||
}
|
||||
}
|
||||
|
||||
static SYSTEMTIME tm2systemtime(const struct tm* t)
|
||||
{
|
||||
SYSTEMTIME st = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (t)
|
||||
{
|
||||
st.wYear = (WORD)(1900 + t->tm_year);
|
||||
st.wMonth = (WORD)t->tm_mon + 1;
|
||||
st.wDay = (WORD)t->tm_mday;
|
||||
st.wDayOfWeek = (WORD)t->tm_wday;
|
||||
st.wHour = (WORD)t->tm_hour;
|
||||
st.wMinute = (WORD)t->tm_min;
|
||||
st.wSecond = (WORD)t->tm_sec;
|
||||
st.wMilliseconds = 0;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
static struct tm systemtime2tm(const SYSTEMTIME* st)
|
||||
{
|
||||
struct tm t = WINPR_C_ARRAY_INIT;
|
||||
if (st)
|
||||
{
|
||||
if (st->wYear >= 1900)
|
||||
t.tm_year = st->wYear - 1900;
|
||||
if (st->wMonth > 0)
|
||||
t.tm_mon = st->wMonth - 1;
|
||||
t.tm_mday = st->wDay;
|
||||
t.tm_wday = st->wDayOfWeek;
|
||||
t.tm_hour = st->wHour;
|
||||
t.tm_min = st->wMinute;
|
||||
t.tm_sec = st->wSecond;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
static LONG get_gmtoff_min(const struct tm* t)
|
||||
{
|
||||
WINPR_ASSERT(t);
|
||||
return -(LONG)(t->tm_gmtoff / 60l);
|
||||
}
|
||||
|
||||
static struct tm next_day(const struct tm* start)
|
||||
{
|
||||
struct tm cur = *start;
|
||||
cur.tm_hour = 0;
|
||||
cur.tm_min = 0;
|
||||
cur.tm_sec = 0;
|
||||
cur.tm_isdst = -1;
|
||||
cur.tm_mday++;
|
||||
const time_t t = mktime(&cur);
|
||||
(void)localtime_r(&t, &cur);
|
||||
return cur;
|
||||
}
|
||||
|
||||
static struct tm adjust_time(const struct tm* start, int hour, int minute)
|
||||
{
|
||||
struct tm cur = *start;
|
||||
cur.tm_hour = hour;
|
||||
cur.tm_min = minute;
|
||||
cur.tm_sec = 0;
|
||||
cur.tm_isdst = -1;
|
||||
const time_t t = mktime(&cur);
|
||||
(void)localtime_r(&t, &cur);
|
||||
return cur;
|
||||
}
|
||||
|
||||
/* [MS-RDPBCGR] 2.2.1.11.1.1.1.1.1 System Time (TS_SYSTEMTIME) */
|
||||
static WORD get_transition_weekday_occurrence(const SYSTEMTIME* st)
|
||||
{
|
||||
WORD count = 0;
|
||||
struct tm start = systemtime2tm(st);
|
||||
|
||||
WORD last = 0;
|
||||
struct tm next = start;
|
||||
next.tm_mday = 1;
|
||||
next.tm_isdst = -1;
|
||||
do
|
||||
{
|
||||
|
||||
const time_t t = mktime(&next);
|
||||
next.tm_mday++;
|
||||
|
||||
struct tm cur = WINPR_C_ARRAY_INIT;
|
||||
(void)localtime_r(&t, &cur);
|
||||
|
||||
if (cur.tm_mon + 1 != st->wMonth)
|
||||
break;
|
||||
|
||||
if (cur.tm_wday == st->wDayOfWeek)
|
||||
{
|
||||
if (cur.tm_mday <= st->wDay)
|
||||
count++;
|
||||
last++;
|
||||
}
|
||||
|
||||
} while (TRUE);
|
||||
|
||||
if (count == last)
|
||||
count = 5;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static SYSTEMTIME tm2transitiontime(const struct tm* cur)
|
||||
{
|
||||
SYSTEMTIME t = tm2systemtime(cur);
|
||||
if (cur)
|
||||
{
|
||||
t.wDay = get_transition_weekday_occurrence(&t);
|
||||
t.wYear = 0;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static SYSTEMTIME get_transition_time(const struct tm* start, BOOL toDst)
|
||||
{
|
||||
BOOL toggled = FALSE;
|
||||
struct tm first = adjust_time(start, 0, 0);
|
||||
for (int hour = 0; hour < 24; hour++)
|
||||
{
|
||||
struct tm cur = adjust_time(start, hour, 0);
|
||||
if (cur.tm_isdst != first.tm_isdst)
|
||||
toggled = TRUE;
|
||||
|
||||
if (toggled)
|
||||
{
|
||||
if (toDst && (cur.tm_isdst > 0))
|
||||
return tm2transitiontime(&cur);
|
||||
else if (!toDst && (cur.tm_isdst == 0))
|
||||
return tm2transitiontime(&cur);
|
||||
}
|
||||
}
|
||||
return tm2transitiontime(start);
|
||||
}
|
||||
|
||||
static BOOL get_transition_date(const struct tm* start, BOOL toDst, SYSTEMTIME* pdate)
|
||||
{
|
||||
WINPR_ASSERT(start);
|
||||
WINPR_ASSERT(pdate);
|
||||
|
||||
*pdate = tm2transitiontime(nullptr);
|
||||
|
||||
if (start->tm_isdst < 0)
|
||||
return FALSE;
|
||||
|
||||
BOOL val = start->tm_isdst > 0; // the year starts with DST or not
|
||||
BOOL toggled = FALSE;
|
||||
struct tm cur = *start;
|
||||
struct tm last = cur;
|
||||
for (int day = 1; day <= 365; day++)
|
||||
{
|
||||
last = cur;
|
||||
cur = next_day(&cur);
|
||||
const BOOL curDst = (cur.tm_isdst > 0);
|
||||
if ((val != curDst) && !toggled)
|
||||
toggled = TRUE;
|
||||
|
||||
if (toggled)
|
||||
{
|
||||
if (toDst && curDst)
|
||||
{
|
||||
*pdate = get_transition_time(&last, toDst);
|
||||
return TRUE;
|
||||
}
|
||||
if (!toDst && !curDst)
|
||||
{
|
||||
*pdate = get_transition_time(&last, toDst);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static LONG get_bias(const struct tm* start, BOOL dstBias)
|
||||
{
|
||||
if ((start->tm_isdst > 0) && dstBias)
|
||||
return get_gmtoff_min(start);
|
||||
if ((start->tm_isdst == 0) && !dstBias)
|
||||
return get_gmtoff_min(start);
|
||||
if (start->tm_isdst < 0)
|
||||
return get_gmtoff_min(start);
|
||||
|
||||
struct tm cur = *start;
|
||||
for (int day = 1; day <= 365; day++)
|
||||
{
|
||||
cur = next_day(&cur);
|
||||
if ((cur.tm_isdst > 0) && dstBias)
|
||||
return get_gmtoff_min(&cur);
|
||||
else if ((cur.tm_isdst == 0) && !dstBias)
|
||||
return get_gmtoff_min(&cur);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL map_iana_id(const char* iana, LPDYNAMIC_TIME_ZONE_INFORMATION tz)
|
||||
{
|
||||
const char* winId = TimeZoneIanaToWindows(iana, TIME_ZONE_NAME_ID);
|
||||
const char* winStd = TimeZoneIanaToWindows(iana, TIME_ZONE_NAME_STANDARD);
|
||||
const char* winDst = TimeZoneIanaToWindows(iana, TIME_ZONE_NAME_DAYLIGHT);
|
||||
|
||||
if (winStd)
|
||||
(void)ConvertUtf8ToWChar(winStd, tz->StandardName, ARRAYSIZE(tz->StandardName));
|
||||
if (winDst)
|
||||
(void)ConvertUtf8ToWChar(winDst, tz->DaylightName, ARRAYSIZE(tz->DaylightName));
|
||||
if (winId)
|
||||
(void)ConvertUtf8ToWChar(winId, tz->TimeZoneKeyName, ARRAYSIZE(tz->TimeZoneKeyName));
|
||||
|
||||
return winId != nullptr;
|
||||
}
|
||||
|
||||
static const char* weekday2str(WORD wDayOfWeek)
|
||||
{
|
||||
switch (wDayOfWeek)
|
||||
{
|
||||
case 0:
|
||||
return "SUNDAY";
|
||||
case 1:
|
||||
return "MONDAY";
|
||||
case 2:
|
||||
return "TUESDAY";
|
||||
case 3:
|
||||
return "WEDNESDAY";
|
||||
case 4:
|
||||
return "THURSDAY";
|
||||
case 5:
|
||||
return "FRIDAY";
|
||||
case 6:
|
||||
return "SATURDAY";
|
||||
default:
|
||||
return "DAY-OF-MAGIC";
|
||||
}
|
||||
}
|
||||
|
||||
static char* systemtime2str(const SYSTEMTIME* t, char* buffer, size_t len)
|
||||
{
|
||||
const SYSTEMTIME empty = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (memcmp(t, &empty, sizeof(SYSTEMTIME)) == 0)
|
||||
(void)_snprintf(buffer, len, "{ not set }");
|
||||
else
|
||||
{
|
||||
(void)_snprintf(buffer, len,
|
||||
"{ %" PRIu16 "-%" PRIu16 "-%" PRIu16 " [%s] %" PRIu16 ":%" PRIu16
|
||||
":%" PRIu16 ".%" PRIu16 "}",
|
||||
t->wYear, t->wMonth, t->wDay, weekday2str(t->wDayOfWeek), t->wHour,
|
||||
t->wMinute, t->wSecond, t->wMilliseconds);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
WINPR_ATTR_FORMAT_ARG(6, 7)
|
||||
static void log_print(wLog* log, DWORD level, const char* file, const char* fkt, size_t line,
|
||||
WINPR_FORMAT_ARG const char* fmt, ...)
|
||||
{
|
||||
if (!WLog_IsLevelActive(log, level))
|
||||
return;
|
||||
|
||||
va_list ap = WINPR_C_ARRAY_INIT;
|
||||
va_start(ap, fmt);
|
||||
WLog_PrintTextMessageVA(log, level, line, file, fkt, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#define log_timezone(tzif, result) log_timezone_((tzif), (result), __FILE__, __func__, __LINE__)
|
||||
static void log_timezone_(const DYNAMIC_TIME_ZONE_INFORMATION* tzif, DWORD result, const char* file,
|
||||
const char* fkt, size_t line)
|
||||
{
|
||||
WINPR_ASSERT(tzif);
|
||||
|
||||
char buffer[130] = WINPR_C_ARRAY_INIT;
|
||||
DWORD level = WLOG_TRACE;
|
||||
wLog* log = WLog_Get(TAG);
|
||||
log_print(log, level, file, fkt, line, "DYNAMIC_TIME_ZONE_INFORMATION {");
|
||||
|
||||
log_print(log, level, file, fkt, line, " Bias=%" PRId32, tzif->Bias);
|
||||
(void)ConvertWCharNToUtf8(tzif->StandardName, ARRAYSIZE(tzif->StandardName), buffer,
|
||||
ARRAYSIZE(buffer));
|
||||
log_print(log, level, file, fkt, line, " StandardName=%s", buffer);
|
||||
log_print(log, level, file, fkt, line, " StandardDate=%s",
|
||||
systemtime2str(&tzif->StandardDate, buffer, sizeof(buffer)));
|
||||
log_print(log, level, file, fkt, line, " StandardBias=%" PRId32, tzif->StandardBias);
|
||||
|
||||
(void)ConvertWCharNToUtf8(tzif->DaylightName, ARRAYSIZE(tzif->DaylightName), buffer,
|
||||
ARRAYSIZE(buffer));
|
||||
log_print(log, level, file, fkt, line, " DaylightName=%s", buffer);
|
||||
log_print(log, level, file, fkt, line, " DaylightDate=%s",
|
||||
systemtime2str(&tzif->DaylightDate, buffer, sizeof(buffer)));
|
||||
log_print(log, level, file, fkt, line, " DaylightBias=%" PRId32, tzif->DaylightBias);
|
||||
(void)ConvertWCharNToUtf8(tzif->TimeZoneKeyName, ARRAYSIZE(tzif->TimeZoneKeyName), buffer,
|
||||
ARRAYSIZE(buffer));
|
||||
log_print(log, level, file, fkt, line, " TimeZoneKeyName=%s", buffer);
|
||||
log_print(log, level, file, fkt, line, " DynamicDaylightTimeDisabled=DST-%s",
|
||||
tzif->DynamicDaylightTimeDisabled ? "disabled" : "enabled");
|
||||
switch (result)
|
||||
{
|
||||
case TIME_ZONE_ID_DAYLIGHT:
|
||||
log_print(log, level, file, fkt, line, " DaylightDate in use");
|
||||
break;
|
||||
case TIME_ZONE_ID_STANDARD:
|
||||
log_print(log, level, file, fkt, line, " StandardDate in use");
|
||||
break;
|
||||
default:
|
||||
log_print(log, level, file, fkt, line, " UnknownDate in use");
|
||||
break;
|
||||
}
|
||||
log_print(log, level, file, fkt, line, "}");
|
||||
}
|
||||
|
||||
DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
|
||||
{
|
||||
DYNAMIC_TIME_ZONE_INFORMATION dyn = WINPR_C_ARRAY_INIT;
|
||||
DWORD rc = GetDynamicTimeZoneInformation(&dyn);
|
||||
lpTimeZoneInformation->Bias = dyn.Bias;
|
||||
lpTimeZoneInformation->DaylightBias = dyn.DaylightBias;
|
||||
lpTimeZoneInformation->DaylightDate = dyn.DaylightDate;
|
||||
lpTimeZoneInformation->StandardBias = dyn.StandardBias;
|
||||
lpTimeZoneInformation->StandardDate = dyn.StandardDate;
|
||||
memcpy(lpTimeZoneInformation->StandardName, dyn.StandardName,
|
||||
sizeof(lpTimeZoneInformation->StandardName));
|
||||
memcpy(lpTimeZoneInformation->DaylightName, dyn.DaylightName,
|
||||
sizeof(lpTimeZoneInformation->DaylightName));
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL SetTimeZoneInformation(const TIME_ZONE_INFORMATION* lpTimeZoneInformation)
|
||||
{
|
||||
WINPR_UNUSED(lpTimeZoneInformation);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime, LPFILETIME lpFileTime)
|
||||
{
|
||||
WINPR_UNUSED(lpSystemTime);
|
||||
WINPR_UNUSED(lpFileTime);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL FileTimeToSystemTime(const FILETIME* lpFileTime, LPSYSTEMTIME lpSystemTime)
|
||||
{
|
||||
WINPR_UNUSED(lpFileTime);
|
||||
WINPR_UNUSED(lpSystemTime);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SystemTimeToTzSpecificLocalTime(LPTIME_ZONE_INFORMATION lpTimeZone,
|
||||
LPSYSTEMTIME lpUniversalTime, LPSYSTEMTIME lpLocalTime)
|
||||
{
|
||||
WINPR_UNUSED(lpTimeZone);
|
||||
WINPR_UNUSED(lpUniversalTime);
|
||||
WINPR_UNUSED(lpLocalTime);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation,
|
||||
LPSYSTEMTIME lpLocalTime, LPSYSTEMTIME lpUniversalTime)
|
||||
{
|
||||
WINPR_UNUSED(lpTimeZoneInformation);
|
||||
WINPR_UNUSED(lpLocalTime);
|
||||
WINPR_UNUSED(lpUniversalTime);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GetDynamicTimeZoneInformation is provided by the SDK if _WIN32_WINNT >= 0x0600 in SDKs above 7.1A
|
||||
* and incorrectly if _WIN32_WINNT >= 0x0501 in older SDKs
|
||||
*/
|
||||
#if !defined(_WIN32) || \
|
||||
(defined(_WIN32) && (defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0600 || \
|
||||
!defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0501)) /* Windows Vista */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
HAVE_TRANSITION_DATES = 0,
|
||||
HAVE_NO_STANDARD_TRANSITION_DATE = 1,
|
||||
HAVE_NO_DAYLIGHT_TRANSITION_DATE = 2
|
||||
} dyn_transition_result;
|
||||
|
||||
static int dynamic_time_zone_from_localtime(const struct tm* local_time,
|
||||
PDYNAMIC_TIME_ZONE_INFORMATION tz)
|
||||
{
|
||||
WINPR_ASSERT(local_time);
|
||||
WINPR_ASSERT(tz);
|
||||
int rc = HAVE_TRANSITION_DATES;
|
||||
|
||||
tz->Bias = get_bias(local_time, FALSE);
|
||||
|
||||
/* If the current time has (or had) DST */
|
||||
if (local_time->tm_isdst >= 0)
|
||||
{
|
||||
/* DST bias is the difference between standard time and DST in minutes */
|
||||
const LONG d = get_bias(local_time, TRUE);
|
||||
tz->DaylightBias = -1 * (tz->Bias - d);
|
||||
if (!get_transition_date(local_time, FALSE, &tz->StandardDate))
|
||||
{
|
||||
rc |= HAVE_NO_STANDARD_TRANSITION_DATE;
|
||||
tz->StandardBias = 0;
|
||||
}
|
||||
if (!get_transition_date(local_time, TRUE, &tz->DaylightDate))
|
||||
{
|
||||
rc |= HAVE_NO_DAYLIGHT_TRANSITION_DATE;
|
||||
tz->DaylightBias = 0;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
DWORD GetDynamicTimeZoneInformation(PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation)
|
||||
{
|
||||
const char** list = nullptr;
|
||||
char* tzid = nullptr;
|
||||
const char* defaultName = "Client Local Time";
|
||||
DWORD res = TIME_ZONE_ID_UNKNOWN;
|
||||
const DYNAMIC_TIME_ZONE_INFORMATION empty = WINPR_C_ARRAY_INIT;
|
||||
|
||||
WINPR_ASSERT(pTimeZoneInformation);
|
||||
|
||||
*pTimeZoneInformation = empty;
|
||||
(void)ConvertUtf8ToWChar(defaultName, pTimeZoneInformation->StandardName,
|
||||
ARRAYSIZE(pTimeZoneInformation->StandardName));
|
||||
|
||||
const time_t t = time(nullptr);
|
||||
struct tm tres = WINPR_C_ARRAY_INIT;
|
||||
struct tm* local_time = localtime_r(&t, &tres);
|
||||
if (!local_time)
|
||||
goto out_error;
|
||||
|
||||
pTimeZoneInformation->Bias = get_bias(local_time, FALSE);
|
||||
if (local_time->tm_isdst >= 0)
|
||||
dynamic_time_zone_from_localtime(local_time, pTimeZoneInformation);
|
||||
|
||||
tzid = winpr_guess_time_zone();
|
||||
if (!map_iana_id(tzid, pTimeZoneInformation))
|
||||
{
|
||||
const size_t len = TimeZoneIanaAbbrevGet(local_time->tm_zone, nullptr, 0);
|
||||
list = (const char**)calloc(len, sizeof(const char*));
|
||||
if (!list)
|
||||
goto out_error;
|
||||
const size_t size = TimeZoneIanaAbbrevGet(local_time->tm_zone, list, len);
|
||||
for (size_t x = 0; x < size; x++)
|
||||
{
|
||||
const char* id = list[x];
|
||||
if (map_iana_id(id, pTimeZoneInformation))
|
||||
{
|
||||
res = (local_time->tm_isdst) ? TIME_ZONE_ID_DAYLIGHT : TIME_ZONE_ID_STANDARD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
res = (local_time->tm_isdst) ? TIME_ZONE_ID_DAYLIGHT : TIME_ZONE_ID_STANDARD;
|
||||
|
||||
out_error:
|
||||
free(tzid);
|
||||
free((void*)list);
|
||||
|
||||
log_timezone(pTimeZoneInformation, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOL SetDynamicTimeZoneInformation(const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation)
|
||||
{
|
||||
WINPR_UNUSED(lpTimeZoneInformation);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL GetTimeZoneInformationForYear(USHORT wYear, PDYNAMIC_TIME_ZONE_INFORMATION pdtzi,
|
||||
LPTIME_ZONE_INFORMATION ptzi)
|
||||
{
|
||||
WINPR_UNUSED(wYear);
|
||||
WINPR_UNUSED(pdtzi);
|
||||
WINPR_UNUSED(ptzi);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) || (defined(_WIN32) && (_WIN32_WINNT < 0x0601)) /* Windows 7 */
|
||||
|
||||
BOOL SystemTimeToTzSpecificLocalTimeEx(const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation,
|
||||
const SYSTEMTIME* lpUniversalTime, LPSYSTEMTIME lpLocalTime)
|
||||
{
|
||||
WINPR_UNUSED(lpTimeZoneInformation);
|
||||
WINPR_UNUSED(lpUniversalTime);
|
||||
WINPR_UNUSED(lpLocalTime);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL TzSpecificLocalTimeToSystemTimeEx(const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation,
|
||||
const SYSTEMTIME* lpLocalTime, LPSYSTEMTIME lpUniversalTime)
|
||||
{
|
||||
WINPR_UNUSED(lpTimeZoneInformation);
|
||||
WINPR_UNUSED(lpLocalTime);
|
||||
WINPR_UNUSED(lpUniversalTime);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
DWORD EnumDynamicTimeZoneInformation(DWORD dwIndex,
|
||||
PDYNAMIC_TIME_ZONE_INFORMATION lpTimeZoneInformation)
|
||||
{
|
||||
if (!lpTimeZoneInformation)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
const DYNAMIC_TIME_ZONE_INFORMATION empty = WINPR_C_ARRAY_INIT;
|
||||
*lpTimeZoneInformation = empty;
|
||||
|
||||
const TimeZoneNameMapEntry* entry = TimeZoneGetAt(dwIndex);
|
||||
if (!entry)
|
||||
return ERROR_NO_MORE_ITEMS;
|
||||
|
||||
if (entry->DaylightName)
|
||||
(void)ConvertUtf8ToWChar(entry->DaylightName, lpTimeZoneInformation->DaylightName,
|
||||
ARRAYSIZE(lpTimeZoneInformation->DaylightName));
|
||||
if (entry->StandardName)
|
||||
(void)ConvertUtf8ToWChar(entry->StandardName, lpTimeZoneInformation->StandardName,
|
||||
ARRAYSIZE(lpTimeZoneInformation->StandardName));
|
||||
if (entry->Id)
|
||||
(void)ConvertUtf8ToWChar(entry->Id, lpTimeZoneInformation->TimeZoneKeyName,
|
||||
ARRAYSIZE(lpTimeZoneInformation->TimeZoneKeyName));
|
||||
|
||||
const time_t t = time(nullptr);
|
||||
struct tm tres = WINPR_C_ARRAY_INIT;
|
||||
|
||||
char* tzcopy = entry->Iana ? setNewAndSaveOldTZ(entry->Iana) : nullptr;
|
||||
|
||||
struct tm* local_time = localtime_r(&t, &tres);
|
||||
|
||||
if (local_time)
|
||||
dynamic_time_zone_from_localtime(local_time, lpTimeZoneInformation);
|
||||
|
||||
if (entry->Iana)
|
||||
restoreSavedTZ(tzcopy);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// NOLINTBEGIN(readability-non-const-parameter)
|
||||
DWORD GetDynamicTimeZoneInformationEffectiveYears(
|
||||
const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation, LPDWORD FirstYear, LPDWORD LastYear)
|
||||
// NOLINTEND(readability-non-const-parameter)
|
||||
{
|
||||
WINPR_UNUSED(lpTimeZoneInformation);
|
||||
WINPR_UNUSED(FirstYear);
|
||||
WINPR_UNUSED(LastYear);
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
#elif _WIN32_WINNT < 0x0602 /* Windows 8 */
|
||||
DWORD EnumDynamicTimeZoneInformation(DWORD dwIndex,
|
||||
PDYNAMIC_TIME_ZONE_INFORMATION lpTimeZoneInformation)
|
||||
{
|
||||
WINPR_UNUSED(dwIndex);
|
||||
WINPR_UNUSED(lpTimeZoneInformation);
|
||||
return ERROR_NO_MORE_ITEMS;
|
||||
}
|
||||
|
||||
DWORD GetDynamicTimeZoneInformationEffectiveYears(
|
||||
const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation, LPDWORD FirstYear, LPDWORD LastYear)
|
||||
{
|
||||
WINPR_UNUSED(lpTimeZoneInformation);
|
||||
WINPR_UNUSED(FirstYear);
|
||||
WINPR_UNUSED(LastYear);
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
char* setNewAndSaveOldTZ(const char* val)
|
||||
{
|
||||
// NOLINTBEGIN(concurrency-mt-unsafe)
|
||||
const char* otz = getenv("TZ");
|
||||
char* oldtz = nullptr;
|
||||
if (otz)
|
||||
oldtz = _strdup(otz);
|
||||
setenv("TZ", val, 1);
|
||||
tzset();
|
||||
// NOLINTEND(concurrency-mt-unsafe)
|
||||
return oldtz;
|
||||
}
|
||||
|
||||
void restoreSavedTZ(char* saved)
|
||||
{
|
||||
// NOLINTBEGIN(concurrency-mt-unsafe)
|
||||
if (saved)
|
||||
{
|
||||
setenv("TZ", saved, 1);
|
||||
free(saved);
|
||||
}
|
||||
else
|
||||
unsetenv("TZ");
|
||||
tzset();
|
||||
// NOLINTEND(concurrency-mt-unsafe)
|
||||
}
|
||||
#endif
|
||||
26
third_party/FreeRDP/winpr/libwinpr/timezone/timezone.h
vendored
Normal file
26
third_party/FreeRDP/winpr/libwinpr/timezone/timezone.h
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Time Zone
|
||||
*
|
||||
* Copyright 2025 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2025 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(_WIN32)
|
||||
char* setNewAndSaveOldTZ(const char* val);
|
||||
void restoreSavedTZ(char* saved);
|
||||
#endif
|
||||
31
third_party/FreeRDP/winpr/libwinpr/timezone/utils/CMakeLists.txt
vendored
Normal file
31
third_party/FreeRDP/winpr/libwinpr/timezone/utils/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif()
|
||||
|
||||
project(tzextract VERSION 1.0.0 LANGUAGES CSharp)
|
||||
|
||||
set(CMAKE_CSharp_FLAGS "/langversion:10")
|
||||
set(CMAKE_DOTNET_TARGET_FRAMEWORK "net8.0")
|
||||
set(CMAKE_DOTNET_SDK "Microsoft.NET.Sdk")
|
||||
|
||||
add_executable(${PROJECT_NAME} tzextract.cs)
|
||||
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY WIN32_EXECUTABLE FALSE)
|
||||
|
||||
set_property(
|
||||
TARGET ${PROJECT_NAME}
|
||||
PROPERTY VS_DOTNET_REFERENCES
|
||||
"System"
|
||||
"System.Collections.Generic"
|
||||
"System.IO"
|
||||
"System.Net.Http"
|
||||
"System.Linq"
|
||||
"System.Threading"
|
||||
"System.Threading.Tasks"
|
||||
)
|
||||
install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBRARY_DIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBRARY_DIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINARY_DIR} INCLUDES
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDE_DIR}
|
||||
)
|
||||
220
third_party/FreeRDP/winpr/libwinpr/timezone/utils/tzextract.cs
vendored
Normal file
220
third_party/FreeRDP/winpr/libwinpr/timezone/utils/tzextract.cs
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.Schema;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
private static string app = AppDomain.CurrentDomain.FriendlyName;
|
||||
private static TextWriter stderr = Console.Error;
|
||||
private static TextWriter stdout = Console.Out;
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
stderr.WriteLine("Usage:");
|
||||
stderr.WriteLine(app + " <path to output files>");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
private static bool writeZoneMapC(string path)
|
||||
{
|
||||
string fname = "TimeZoneNameMap";
|
||||
string fpath = Path.Combine(path, fname + "_static.h");
|
||||
|
||||
using (StreamWriter fs = new StreamWriter(fpath))
|
||||
{
|
||||
fs.WriteLine("/* Automatically generated by " + app + " */");
|
||||
fs.WriteLine("");
|
||||
fs.WriteLine("#include \"" + fname + ".h\"");
|
||||
fs.WriteLine("");
|
||||
fs.WriteLine("static const " + fname + "Entry " + fname + "[] ={");
|
||||
|
||||
bool first = true;
|
||||
foreach (System.TimeZoneInfo tz in System.TimeZoneInfo.GetSystemTimeZones())
|
||||
{
|
||||
string iana;
|
||||
System.TimeZoneInfo.TryConvertWindowsIdToIanaId(tz.Id, out iana);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!first)
|
||||
sb.Append(",");
|
||||
first = false;
|
||||
sb.Append("{ \"");
|
||||
sb.Append(tz.Id);
|
||||
sb.Append("\", \"");
|
||||
sb.Append(tz.StandardName);
|
||||
sb.Append("\", \"");
|
||||
sb.Append(tz.DisplayName);
|
||||
sb.Append("\", \"");
|
||||
sb.Append(tz.DaylightName);
|
||||
sb.Append("\", \"");
|
||||
sb.Append(iana);
|
||||
sb.Append("\" }");
|
||||
fs.WriteLine(sb.ToString());
|
||||
}
|
||||
|
||||
fs.WriteLine("};");
|
||||
fs.WriteLine("");
|
||||
fs.WriteLine("static const size_t " + fname + "Size = ARRAYSIZE(" + fname + ");");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool writeZoneMapJSON(string path)
|
||||
{
|
||||
string fname = "TimeZoneNameMap";
|
||||
string fpath = Path.Combine(path, fname + ".json");
|
||||
|
||||
using (StreamWriter fs = new StreamWriter(fpath))
|
||||
{
|
||||
fs.WriteLine("{");
|
||||
fs.WriteLine("\"TimeZoneNameMap\": [");
|
||||
|
||||
bool first = true;
|
||||
foreach (System.TimeZoneInfo tz in System.TimeZoneInfo.GetSystemTimeZones())
|
||||
{
|
||||
string iana;
|
||||
System.TimeZoneInfo.TryConvertWindowsIdToIanaId(tz.Id, out iana);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!first)
|
||||
sb.Append(",");
|
||||
first = false;
|
||||
sb.Append("{ ");
|
||||
sb.Append("\"Id\": \"");
|
||||
sb.Append(tz.Id);
|
||||
sb.Append("\", \"StandardName\": \"");
|
||||
sb.Append(tz.StandardName);
|
||||
sb.Append("\", \"DisplayName\": \"");
|
||||
sb.Append(tz.DisplayName);
|
||||
sb.Append("\", \"DaylightName\": \"");
|
||||
sb.Append(tz.DaylightName);
|
||||
sb.Append("\", \"Iana\": \"");
|
||||
sb.Append(iana);
|
||||
sb.Append("\" }");
|
||||
fs.WriteLine(sb.ToString());
|
||||
}
|
||||
|
||||
fs.WriteLine("]");
|
||||
fs.WriteLine("}");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool writeZoneMap(string path)
|
||||
{
|
||||
if (!writeZoneMapC(path))
|
||||
return false;
|
||||
if (!writeZoneMapJSON(path))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void onValidation(object sender, ValidationEventArgs e)
|
||||
{
|
||||
switch (e.Severity)
|
||||
{
|
||||
case XmlSeverityType.Warning:
|
||||
case XmlSeverityType.Error:
|
||||
stderr.WriteLine(e.ToString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private static bool updateWindowsIanaMap(string path)
|
||||
{
|
||||
string url =
|
||||
"https://raw.githubusercontent.com/unicode-org/cldr/main/common/supplemental/windowsZones.xml";
|
||||
string fname = "WindowsZones";
|
||||
string fpath = Path.Combine(path, fname + ".c");
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(url);
|
||||
|
||||
stdout.WriteLine("Downloaded and parsed XML from '" + url + "'");
|
||||
|
||||
ValidationEventHandler handler = new ValidationEventHandler(onValidation);
|
||||
// doc.Validate(handler);
|
||||
|
||||
XmlNodeList versions = doc.SelectNodes("//supplementalData/version");
|
||||
XmlNodeList zones = doc.SelectNodes("//supplementalData/windowsZones/mapTimezones");
|
||||
XmlNodeList mzones =
|
||||
doc.SelectNodes("//supplementalData/windowsZones/mapTimezones/mapZone");
|
||||
|
||||
using (StreamWriter fs = new StreamWriter(fpath))
|
||||
{
|
||||
fs.WriteLine("/* Automatically generated by " + app);
|
||||
fs.WriteLine(" *");
|
||||
fs.WriteLine(" * url " + url);
|
||||
|
||||
foreach (XmlNode version in versions)
|
||||
{
|
||||
XmlNode nr = version.Attributes.GetNamedItem("number");
|
||||
fs.WriteLine(" * version: " + nr.InnerText);
|
||||
}
|
||||
|
||||
foreach (XmlNode node in zones)
|
||||
{
|
||||
XmlNode over = node.Attributes.GetNamedItem("otherVersion");
|
||||
XmlNode tver = node.Attributes.GetNamedItem("typeVersion");
|
||||
fs.WriteLine(" * mapTimezones: otherVersion: " + over.InnerText +
|
||||
", typeVersion: " + tver.InnerText);
|
||||
}
|
||||
|
||||
fs.WriteLine(" */");
|
||||
fs.WriteLine("");
|
||||
fs.WriteLine("#include \"" + fname + ".h\"");
|
||||
fs.WriteLine("");
|
||||
fs.WriteLine("const WINDOWS_TZID_ENTRY " + fname + "[] = {");
|
||||
|
||||
foreach (XmlNode mzone in mzones)
|
||||
{
|
||||
XmlAttributeCollection attrs = mzone.Attributes;
|
||||
XmlNode wzid = attrs.GetNamedItem("other");
|
||||
XmlNode territory = attrs.GetNamedItem("territory");
|
||||
XmlNode iana = attrs.GetNamedItem("type");
|
||||
fs.WriteLine("\t{ \"" + iana.InnerText + "\", \"" + wzid.InnerText + "\" }, // " +
|
||||
territory.InnerText);
|
||||
}
|
||||
|
||||
fs.WriteLine("};");
|
||||
fs.WriteLine("");
|
||||
fs.WriteLine("const size_t " + fname + "NrElements = ARRAYSIZE(" + fname + ");");
|
||||
}
|
||||
stdout.WriteLine("Finished update");
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (args.Length == 0)
|
||||
{
|
||||
stderr.WriteLine("Missing arguments!");
|
||||
usage();
|
||||
}
|
||||
|
||||
DirectoryInfo info = new DirectoryInfo(args[0]);
|
||||
if (!info.Exists)
|
||||
{
|
||||
stderr.WriteLine("Path '" + info.FullName + "' does not exist");
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!writeZoneMap(info.FullName))
|
||||
return;
|
||||
|
||||
updateWindowsIanaMap(info.FullName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
stderr.WriteLine(e.ToString());
|
||||
Environment.Exit(-23);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user