feat:[TD-32642] add timezone support in windows

This commit is contained in:
wangmm0220 2024-12-02 10:22:48 +08:00
parent d52e9a1c5c
commit 9cfd293793
9 changed files with 105 additions and 121 deletions

View File

@ -106,7 +106,9 @@ cat("${TD_SUPPORT_DIR}/zlib_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
# cJson
cat("${TD_SUPPORT_DIR}/cjson_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
cat("${TD_SUPPORT_DIR}/tz_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
if(NOT ${TD_WINDOWS})
cat("${TD_SUPPORT_DIR}/tz_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
endif(NOT ${TD_WINDOWS})
# xz
# cat("${TD_SUPPORT_DIR}/xz_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
@ -653,16 +655,18 @@ if(${TD_LINUX} AND ${BUILD_WITH_S3})
add_subdirectory(azure-cmake EXCLUDE_FROM_ALL)
endif()
execute_process(
COMMAND make TZDIR=${TZ_OUTPUT_PATH}/ clean zic posix_only
WORKING_DIRECTORY "${TD_CONTRIB_DIR}/tz"
)
if(NOT ${TD_WINDOWS})
execute_process(
COMMAND make TZDIR=${TZ_OUTPUT_PATH}/ clean zic posix_only
WORKING_DIRECTORY "${TD_CONTRIB_DIR}/tz"
)
set(TZ_SRC_DIR "${TD_SOURCE_DIR}/source/os/src/timezone")
file(MAKE_DIRECTORY ${TZ_SRC_DIR})
file(COPY ${TD_CONTRIB_DIR}/tz/private.h ${TD_CONTRIB_DIR}/tz/tzdir.h ${TD_CONTRIB_DIR}/tz/tzfile.h
${TD_CONTRIB_DIR}/tz/localtime.c ${TD_CONTRIB_DIR}/tz/strftime.c
DESTINATION ${TZ_SRC_DIR})
set(TZ_SRC_DIR "${TD_SOURCE_DIR}/source/os/src/timezone")
file(MAKE_DIRECTORY ${TZ_SRC_DIR})
file(COPY ${TD_CONTRIB_DIR}/tz/private.h ${TD_CONTRIB_DIR}/tz/tzdir.h ${TD_CONTRIB_DIR}/tz/tzfile.h
${TD_CONTRIB_DIR}/tz/localtime.c ${TD_CONTRIB_DIR}/tz/strftime.c
DESTINATION ${TZ_SRC_DIR})
endif(NOT ${TD_WINDOWS})
# ================================================================================================
# Build test
# ================================================================================================

View File

@ -25,18 +25,23 @@ extern "C" {
extern void* pTimezoneNameMap;
#ifdef WINDOWS
typedef struct void *timezone_t;
#else
typedef struct state *timezone_t;
struct tm *localtime_rz(timezone_t , time_t const *, struct tm *);
time_t mktime_z(timezone_t, struct tm *);
timezone_t tzalloc(char const *);
void tzfree(timezone_t);
void getTimezoneStr(char *tz);
#endif
int32_t taosGetLocalTimezoneOffset();
int32_t taosGetSystemTimezone(char *outTimezone);
int32_t taosSetGlobalTimezone(const char *tz);
int32_t taosFormatTimezoneStr(time_t t, const char* tzStr, timezone_t sp, char *outTimezoneStr);
int32_t taosIsValidateTimezone(const char *tz);
#ifdef __cplusplus
}
#endif

View File

@ -93,9 +93,14 @@ static timezone_t setConnnectionTz(const char* val){
tscDebug("set timezone to %s", val);
tz = tzalloc(val);
if (tz == NULL) {
tscError("%s unknown timezone %s", __func__, val);
terrno = TAOS_SYSTEM_ERROR(errno);
goto END;
tscWarn("%s unknown timezone %s change to UTC", __func__, val);
val = "UTC";
tz = tzalloc(val);
if (tz == NULL) {
tscError("%s set timezone %s error", __func__, val);
terrno = TAOS_SYSTEM_ERROR(errno);
goto END;
}
}
int32_t code = taosHashPut(pTimezoneMap, val, strlen(val), &tz, sizeof(timezone_t));
if (code != 0){
@ -159,11 +164,6 @@ static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, co
if (option == TSDB_OPTION_CONNECTION_TIMEZONE || option == TSDB_OPTION_CONNECTION_CLEAR) {
if (val != NULL){
if (strlen(val) == 0){
tscError("%s empty timezone %s", __func__, val);
code = TSDB_CODE_INVALID_PARA;
goto END;
}
timezone_t tz = setConnnectionTz(val);
if (tz == NULL){
code = terrno;

View File

@ -1,6 +1,8 @@
aux_source_directory(src OS_SRC)
aux_source_directory(src/timezone OS_TZ)
add_library(os STATIC ${OS_SRC} ${OS_TZ})
if(NOT ${TD_WINDOWS})
aux_source_directory(src/timezone OS_TZ)
add_library(os STATIC ${OS_SRC} ${OS_TZ})
endif(NOT ${TD_WINDOWS})
target_include_directories(
os
PUBLIC "${TD_SOURCE_DIR}/include/os"

View File

@ -33,7 +33,8 @@
#include <DbgHelp.h>
#pragma warning(pop)
char *win_tz[139][2] = {{"China Standard Time", "Asia/Shanghai"},
#define W_TZ_NUM 139
char *win_tz[W_TZ_NUM][2] = {{"China Standard Time", "Asia/Shanghai"},
{"AUS Central Standard Time", "Australia/Darwin"},
{"AUS Eastern Standard Time", "Australia/Sydney"},
{"Afghanistan Standard Time", "Asia/Kabul"},
@ -172,7 +173,8 @@ char *win_tz[139][2] = {{"China Standard Time", "Asia/Shanghai"},
{"West Pacific Standard Time", "Pacific/Port_Moresby"},
{"Yakutsk Standard Time", "Asia/Yakutsk"},
{"Yukon Standard Time", "America/Whitehorse"}};
char *tz_win[554][2] = {{"Asia/Shanghai", "China Standard Time"},
#define W_TZ_CITY_NUM 554
char *tz_win[W_TZ_CITY_NUM][2] = {{"Asia/Shanghai", "China Standard Time"},
{"Africa/Abidjan", "Greenwich Standard Time"},
{"Africa/Accra", "Greenwich Standard Time"},
{"Africa/Addis_Ababa", "E. Africa Standard Time"},
@ -740,38 +742,19 @@ char *tz_win[554][2] = {{"Asia/Shanghai", "China Standard Time"},
#include <unistd.h>
#endif
void parseTimeStr(char *p, char to[5]) {
for (int i = 0; i < 5; ++i) {
if (strlen(p) > i) {
to[i] = p[i];
} else {
to[i] = '0';
}
}
if (strlen(p) == 2) {
to[1] = '0';
to[2] = p[1];
}
}
int32_t taosIsValidateTimezone(const char *tz) {
return true;
}
int32_t taosSetGlobalTimezone(const char *tz) {
if (tz == NULL || tz[0] == 0) {
if (tz == NULL) {
terrno = TSDB_CODE_INVALID_PARA;
return terrno;
}
int32_t code = TSDB_CODE_SUCCESS;
uDebug("[tz]set timezone to %s", tz)
#ifdef WINDOWS
char winStr[TD_LOCALE_LEN * 2];
memset(winStr, 0, sizeof(winStr));
for (size_t i = 0; i < 554; i++) {
if (strcmp(tz_win[i][0], buf) == 0) {
char keyPath[256];
char keyValue[100];
char winStr[TD_TIMEZONE_LEN * 2] = {0};
for (size_t i = 0; i < W_TZ_CITY_NUM; i++) {
if (strcmp(tz_win[i][0], tz) == 0) {
char keyPath[256] = {0};
char keyValue[100] = {0};
DWORD keyValueSize = sizeof(keyValue);
snprintf(keyPath, sizeof(keyPath), "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\%s", tz_win[i][1]);
RegGetValue(HKEY_LOCAL_MACHINE, keyPath, "Display", RRF_RT_ANY, NULL, (PVOID)&keyValue, &keyValueSize);
@ -779,40 +762,13 @@ int32_t taosSetGlobalTimezone(const char *tz) {
keyValue[4] = (keyValue[4] == '+' ? '-' : '+');
keyValue[10] = 0;
snprintf(winStr, sizeof(winStr), "TZ=%s:00", &(keyValue[1]));
*tsTimezone = -taosStr2Int32(&keyValue[4], NULL, 10);
}
break;
}
}
if (winStr[0] == 0) {
char *p = strchr(inTimezoneStr, '+');
if (p == NULL) p = strchr(inTimezoneStr, '-');
if (p != NULL) {
char *pp = strchr(inTimezoneStr, '(');
char *ppp = strchr(inTimezoneStr, ',');
int indexStr;
if (pp == NULL || ppp == NULL) {
indexStr = tsnprintf(winStr, sizeof(winStr), "TZ=UTC");
} else {
memcpy(winStr, "TZ=", 3);
pp++;
memcpy(&winStr[3], pp, ppp - pp);
indexStr = ppp - pp + 3;
}
char to[5];
parseTimeStr(p, to);
snprintf(&winStr[indexStr], sizeof(winStr) - indexStr, "%c%c%c:%c%c:00", (to[0] == '+' ? '+' : '-'), to[1], to[2], to[3], to[4]);
*tsTimezone = -taosStr2Int32(p, NULL, 10);
} else {
*tsTimezone = 0;
}
}
_putenv(winStr);
_tzset();
if (outTimezoneStr != inTimezoneStr) {
tstrncpy(outTimezoneStr, inTimezoneStr, TD_TIMEZONE_LEN);
}
// *outDaylight = 0;
#else
code = setenv("TZ", tz, 1);
if (-1 == code) {
@ -821,11 +777,10 @@ int32_t taosSetGlobalTimezone(const char *tz) {
}
tzset();
#endif
time_t tx1 = taosGetTimestampSec();
return taosFormatTimezoneStr(tx1, tz, NULL, tsTimezoneStr);
#endif
}
int32_t taosGetLocalTimezoneOffset() {
@ -869,6 +824,7 @@ int32_t taosFormatTimezoneStr(time_t t, const char* tz, timezone_t sp, char *out
return 0;
}
#ifndef WINDOWS
void getTimezoneStr(char *tz) {
do {
int n = readlink("/etc/localtime", tz, TD_TIMEZONE_LEN - 1);
@ -909,21 +865,20 @@ END:
}
uDebug("[tz] system timezone:%s", tz);
}
#endif
int32_t taosGetSystemTimezone(char *outTimezoneStr) {
#ifdef WINDOWS
char value[100];
char keyPath[100];
char value[100] = {0};
char keyPath[100] = {0};
DWORD bufferSize = sizeof(value);
LONG result = RegGetValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", "TimeZoneKeyName",
RRF_RT_ANY, NULL, (PVOID)&value, &bufferSize);
if (result != ERROR_SUCCESS) {
return TAOS_SYSTEM_WINAPI_ERROR(result);
}
tstrncpy(outTimezoneStr, "not configured", TD_TIMEZONE_LEN);
*tsTimezone = 0;
if (bufferSize > 0) {
for (size_t i = 0; i < 139; i++) {
for (size_t i = 0; i < W_TZ_NUM; i++) {
if (strcmp(win_tz[i][0], value) == 0) {
tstrncpy(outTimezoneStr, win_tz[i][1], TD_TIMEZONE_LEN);
bufferSize = sizeof(value);
@ -932,11 +887,9 @@ int32_t taosGetSystemTimezone(char *outTimezoneStr) {
if (result != ERROR_SUCCESS) {
return TAOS_SYSTEM_WINAPI_ERROR(result);
}
if (bufferSize > 0) {
// value[4] = (value[4] == '+' ? '-' : '+');
snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (UTC, %c%c%c%c%c)", outTimezoneStr, value[4], value[5], value[6], value[8],
value[9]);
*tsTimezone = taosStr2Int32(&value[4], NULL, 10);
if (bufferSize > 0) { // value like (UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi
snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (UTC, %c%c%c%c%c)", outTimezoneStr,
value[4], value[5], value[6], value[8], value[9]);
}
break;
}

View File

@ -145,10 +145,31 @@ static char const *utc = etc_utc + sizeof "Etc/" - 1;
# define TZDEFRULESTRING ",M3.2.0,M11.1.0"
#endif
/* Limit to time zone abbreviation length in proleptic TZ strings.
This is distinct from TZ_MAX_CHARS, which limits TZif file contents.
It defaults to 254, not 255, so that desigidx_type can be an unsigned char.
unsigned char suffices for TZif files, so the only reason to increase
TZNAME_MAXIMUM is to support TZ strings specifying abbreviations
longer than 254 bytes. There is little reason to do that, though,
as strings that long are hardly "abbreviations". */
#ifndef TZNAME_MAXIMUM
# define TZNAME_MAXIMUM 254
#endif
#if TZNAME_MAXIMUM < UCHAR_MAX
typedef unsigned char desigidx_type;
#elif TZNAME_MAXIMUM < INT_MAX
typedef int desigidx_type;
#elif TZNAME_MAXIMUM < PTRDIFF_MAX
typedef ptrdiff_t desigidx_type;
#else
# error "TZNAME_MAXIMUM too large"
#endif
struct ttinfo { /* time type information */
int_fast32_t tt_utoff; /* UT offset in seconds */
int_least32_t tt_utoff; /* UT offset in seconds */
desigidx_type tt_desigidx; /* abbreviation list index */
bool tt_isdst; /* used to set tm_isdst */
int tt_desigidx; /* abbreviation list index */
bool tt_ttisstd; /* transition is std time */
bool tt_ttisut; /* transition is UT */
};
@ -167,12 +188,6 @@ static char const UNSPEC[] = "-00";
for ttunspecified to work without crashing. */
enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 };
/* Limit to time zone abbreviation length in proleptic TZ strings.
This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */
#ifndef TZNAME_MAXIMUM
# define TZNAME_MAXIMUM 255
#endif
/* A representation of the contents of a TZif file. Ideally this
would have no size limits; the following sizes should suffice for
practical use. This struct should not be too large, as instances
@ -273,7 +288,8 @@ long altzone;
/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */
static void
init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst,
desigidx_type desigidx)
{
s->tt_utoff = utoff;
s->tt_isdst = isdst;

View File

@ -88,11 +88,11 @@
#if !defined HAVE_GETTEXT && defined __has_include
# if __has_include(<libintl.h>)
# define HAVE_GETTEXT true
# define HAVE_GETTEXT 1
# endif
#endif
#ifndef HAVE_GETTEXT
# define HAVE_GETTEXT false
# define HAVE_GETTEXT 0
#endif
#ifndef HAVE_INCOMPATIBLE_CTIME_R
@ -125,20 +125,20 @@
#if !defined HAVE_SYS_STAT_H && defined __has_include
# if !__has_include(<sys/stat.h>)
# define HAVE_SYS_STAT_H false
# define HAVE_SYS_STAT_H 0
# endif
#endif
#ifndef HAVE_SYS_STAT_H
# define HAVE_SYS_STAT_H true
# define HAVE_SYS_STAT_H 1
#endif
#if !defined HAVE_UNISTD_H && defined __has_include
# if !__has_include(<unistd.h>)
# define HAVE_UNISTD_H false
# define HAVE_UNISTD_H 0
# endif
#endif
#ifndef HAVE_UNISTD_H
# define HAVE_UNISTD_H true
# define HAVE_UNISTD_H 1
#endif
#ifndef NETBSD_INSPIRED
@ -263,6 +263,10 @@
# endif
#endif
#ifndef HAVE_SNPRINTF
# define HAVE_SNPRINTF (!PORT_TO_C89 || 199901 <= __STDC_VERSION__)
#endif
#ifndef HAVE_STRFTIME_L
# if _POSIX_VERSION < 200809
# define HAVE_STRFTIME_L 0
@ -308,7 +312,7 @@
** stdint.h, even with pre-C99 compilers.
*/
#if !defined HAVE_STDINT_H && defined __has_include
# define HAVE_STDINT_H true /* C23 __has_include implies C99 stdint.h. */
# define HAVE_STDINT_H 1 /* C23 __has_include implies C99 stdint.h. */
#endif
#ifndef HAVE_STDINT_H
# define HAVE_STDINT_H \
@ -378,11 +382,15 @@ typedef int int_fast32_t;
# endif
#endif
#ifndef INT_LEAST32_MAX
typedef int_fast32_t int_least32_t;
#endif
#ifndef INTMAX_MAX
# ifdef LLONG_MAX
typedef long long intmax_t;
# ifndef HAVE_STRTOLL
# define HAVE_STRTOLL true
# define HAVE_STRTOLL 1
# endif
# if HAVE_STRTOLL
# define strtoimax strtoll
@ -462,7 +470,7 @@ typedef unsigned long uintmax_t;
hosts, unless compiled with -DHAVE_STDCKDINT_H=0 or with pre-C23 EDG. */
#if !defined HAVE_STDCKDINT_H && defined __has_include
# if __has_include(<stdckdint.h>)
# define HAVE_STDCKDINT_H true
# define HAVE_STDCKDINT_H 1
# endif
#endif
#ifdef HAVE_STDCKDINT_H
@ -630,9 +638,9 @@ typedef unsigned long uintmax_t;
** typical platforms.
*/
#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
# define TZ_TIME_T 1
# define TZ_TIME_T true
#else
# define TZ_TIME_T 0
# define TZ_TIME_T false
#endif
#if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T
@ -749,9 +757,9 @@ void tzset(void);
|| defined __GLIBC__ || defined __tm_zone /* musl */ \
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|| (defined __APPLE__ && defined __MACH__))
# define HAVE_DECL_TIMEGM true
# define HAVE_DECL_TIMEGM 1
# else
# define HAVE_DECL_TIMEGM false
# define HAVE_DECL_TIMEGM 0
# endif
#endif
#if !HAVE_DECL_TIMEGM && !defined timegm

View File

@ -79,9 +79,9 @@
!defined __NetBSD_Version__ || __NetBSD_Version__ < 600000000) \
&& (/* OpenBSD 5.5 (2014-05-01) and later has 64-bit time_t. */ \
!defined OpenBSD || OpenBSD < 201405)))
# define MKTIME_MIGHT_OVERFLOW true
# define MKTIME_MIGHT_OVERFLOW 1
# else
# define MKTIME_MIGHT_OVERFLOW false
# define MKTIME_MIGHT_OVERFLOW 0
# endif
#endif
/* Check that MKTIME_MIGHT_OVERFLOW is consistent with time_t's range. */
@ -95,7 +95,7 @@ static_assert(MKTIME_MIGHT_OVERFLOW
#endif
#ifndef DEPRECATE_TWO_DIGIT_YEARS
# define DEPRECATE_TWO_DIGIT_YEARS false
# define DEPRECATE_TWO_DIGIT_YEARS 0
#endif
struct lc_time_T {

View File

@ -251,13 +251,9 @@ static int32_t cfgSetTimezone(SConfigItem *pItem, const char *value, ECfgSrcType
TAOS_RETURN(TSDB_CODE_INVALID_CFG);
}
if(!taosIsValidateTimezone(value)){
uError("invalid timezone:%s", value);
TAOS_RETURN(TSDB_CODE_INVALID_TIMEZONE);
}
if (value == NULL || strlen(value) == 0) {
uError("cfg:%s, type:%s src:%s, value:%s, skip to set timezone", pItem->name, cfgDtypeStr(pItem->dtype),
cfgStypeStr(stype), value);
if (value == NULL) {
uError("cfg:%s, type:%s src:%s, value is null, skip to set timezone", pItem->name, cfgDtypeStr(pItem->dtype),
cfgStypeStr(stype));
TAOS_RETURN(TSDB_CODE_INVALID_CFG);
}
TAOS_CHECK_RETURN(osSetTimezone(value));