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

This commit is contained in:
wangmm0220 2024-12-02 18:49:06 +08:00
parent 61f11ddb4e
commit adff8a60d1
10 changed files with 77 additions and 112 deletions

View File

@ -26,7 +26,7 @@ extern "C" {
extern void* pTimezoneNameMap;
#ifdef WINDOWS
typedef struct void *timezone_t;
typedef void *timezone_t;
#else
typedef struct state *timezone_t;
struct tm *localtime_rz(timezone_t , time_t const *, struct tm *);

View File

@ -1027,7 +1027,7 @@ int32_t taosGetErrSize();
#define TSDB_CODE_AUDIT_FAIL_GENERATE_JSON TAOS_DEF_ERROR_CODE(0, 0x6102)
//TIMEZONE
#define TSDB_CODE_INVALID_TIMEZONE TAOS_DEF_ERROR_CODE(0, 0x6200)
#define TSDB_CODE_NOT_SUPPORTTED_IN_WINDOWS TAOS_DEF_ERROR_CODE(0, 0x6200)
#ifdef __cplusplus
}

View File

@ -56,6 +56,12 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) {
return ret;
}
#ifndef WINDOWS
static void freeTz(void *p){
timezone_t tz = *(timezone_t *)p;
tzfree(tz);
}
static timezone_t setConnnectionTz(const char* val){
timezone_t tz = NULL;
static int32_t lock_c = 0;
@ -73,7 +79,7 @@ static timezone_t setConnnectionTz(const char* val){
atomic_store_32(&lock_c, 0);
goto END;
}
taosHashSetFreeFp(pTimezoneMap, (_hash_free_fn_t)tzfree);
taosHashSetFreeFp(pTimezoneMap, freeTz);
}
if (pTimezoneNameMap == NULL){
@ -94,10 +100,9 @@ static timezone_t setConnnectionTz(const char* val){
tz = tzalloc(val);
if (tz == NULL) {
tscWarn("%s unknown timezone %s change to UTC", __func__, val);
val = "UTC";
tz = tzalloc(val);
tz = tzalloc("UTC");
if (tz == NULL) {
tscError("%s set timezone %s error", __func__, val);
tscError("%s set timezone UTC error", __func__);
terrno = TAOS_SYSTEM_ERROR(errno);
goto END;
}
@ -120,11 +125,19 @@ END:
atomic_store_32(&lock_c, 0);
return tz;
}
#endif
static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, const char* val){
if (taos == NULL) {
return TSDB_CODE_INVALID_PARA;
}
#ifdef WINDOWS
if (option == TSDB_OPTION_CONNECTION_TIMEZONE){
return TSDB_CODE_NOT_SUPPORTTED_IN_WINDOWS;
}
#endif
if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION){
return TSDB_CODE_INVALID_PARA;
}
@ -163,7 +176,11 @@ static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, co
}
if (option == TSDB_OPTION_CONNECTION_TIMEZONE || option == TSDB_OPTION_CONNECTION_CLEAR) {
#ifndef WINDOWS
if (val != NULL){
if (val[0] == 0){
val = "UTC";
}
timezone_t tz = setConnnectionTz(val);
if (tz == NULL){
code = terrno;
@ -173,6 +190,7 @@ static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, co
} else {
pObj->optionInfo.timezone = NULL;
}
#endif
}
if (option == TSDB_OPTION_CONNECTION_USER_APP || option == TSDB_OPTION_CONNECTION_CLEAR) {

View File

@ -225,7 +225,9 @@ TEST(timezoneCase, setConnectionOption_Test) {
// test timezone
code = taos_options_connection(pConn, TSDB_OPTION_CONNECTION_TIMEZONE, "");
ASSERT(code != 0);
ASSERT(code == 0);
CHECK_TAOS_OPTION_POINTER(pConn, timezone, false);
check_sql_result(pConn, "select timezone()", "UTC (UTC, +0000)");
code = taos_options_connection(pConn, TSDB_OPTION_CONNECTION_TIMEZONE, NULL);
ASSERT(code == 0);
@ -243,7 +245,9 @@ TEST(timezoneCase, setConnectionOption_Test) {
check_sql_result(pConn, "select timezone()", "Asia/Kolkata (IST, +0530)");
code = taos_options_connection(pConn, TSDB_OPTION_CONNECTION_TIMEZONE, "adbc");
ASSERT(code != 0);
ASSERT(code == 0);
CHECK_TAOS_OPTION_POINTER(pConn, timezone, false);
check_sql_result(pConn, "select timezone()", "adbc (UTC, +0000)");
// test user APP
code = taos_options_connection(pConn, TSDB_OPTION_CONNECTION_USER_APP, "");
@ -593,6 +597,19 @@ TEST(timezoneCase, func_timezone_Test) {
execQuery(pConn, "insert into db1.ntb1 values(1704070200000, '2023-12-31 23:50:00', 11)"); // 2023-12-31 23:50:00-0100
checkRows(pConn, "select a.ts,b.ts from db1.ntb a join db1.ntb1 b on timetruncate(a.ts, 1d) = timetruncate(b.ts, 1d)", 1);
// operator +1n +1y
check_sql_result(pConn, "select TO_ISO8601(CAST('2023-01-31T00:00:00.000-01' as timestamp) + 1n)", "2023-02-28T00:00:00.000-0100");
check_sql_result(pConn, "select TO_ISO8601(CAST('2024-01-31T00:00:00.000-01' as timestamp) + 1n)", "2024-02-29T00:00:00.000-0100");
check_sql_result(pConn, "select TO_ISO8601(CAST('2024-02-29T00:00:00.000-01' as timestamp) + 1y)", "2025-02-28T00:00:00.000-0100");
check_sql_result(pConn, "select TO_ISO8601(CAST('2024-01-31T00:00:00.000-01' as timestamp) + 1y)", "2025-01-31T00:00:00.000-0100");
check_sql_result(pConn, "select TO_ISO8601(CAST('2024-01-01T00:00:00.000+01' as timestamp) + 1n)", "2024-01-31T22:00:00.000-0100");
check_sql_result(pConn, "select TO_ISO8601(CAST('2024-01-01T00:00:00.000+01' as timestamp) + 1y)", "2024-12-31T22:00:00.000-0100");
// case when
check_sql_result_integer(pConn, "select case CAST('2024-01-01T00:00:00.000+01' as timestamp) when 1704063600000 then 1 end", 1);
check_sql_result_integer(pConn, "select case CAST('2024-01-01T00:00:00.000' as timestamp) when 1704070800000 then 1 end", 1);
taos_close(pConn);
}

View File

@ -1408,11 +1408,17 @@ static int32_t tm2char(const SArray* formats, const struct STm* tm, char* s, int
(void)sprintf(s, "%09" PRId64, tm->fsec);
s += 9;
break;
case TSFKW_TZH:
(void)sprintf(s, "%c%02d", (tm->tm.tm_gmtoff >= 0) ? '+' : '-',
abs((int) tm->tm.tm_gmtoff) / 3600);
case TSFKW_TZH:{
#ifdef WINDOWS
int32_t gmtoff = -_timezone;
#else
int32_t gmtoff = tm->tm.tm_gmtoff;
#endif
(void)sprintf(s, "%c%02d", (gmtoff >= 0) ? '+' : '-',
abs(gmtoff) / 3600);
s += strlen(s);
break;
}
case TSFKW_YYYY:
(void)sprintf(s, "%04d", tm->tm.tm_year + 1900);
s += strlen(s);
@ -1832,7 +1838,12 @@ static int32_t char2ts(const char* s, SArray* formats, int64_t* ts, int32_t prec
tm.fsec = ms * 1000000 + us * 1000 + ns;
int32_t ret = taosTm2Ts(&tm, ts, precision, tz);
if (tzHour != 0) {
*ts += (tm.tm.tm_gmtoff - tzHour * 3600) * TICK_PER_SECOND[precision];
#ifdef WINDOWS
int32_t gmtoff = -_timezone;
#else
int32_t gmtoff = tm.tm.tm_gmtoff;
#endif
*ts += (gmtoff - tzHour * 3600) * TICK_PER_SECOND[precision];
}
return ret;
}

View File

@ -422,56 +422,18 @@ int64_t user_mktime64(const uint32_t year, const uint32_t mon, const uint32_t da
time_t taosMktime(struct tm *timep, timezone_t tz) {
#ifdef WINDOWS
#if 0
struct tm tm1 = {0};
LARGE_INTEGER t;
FILETIME f;
SYSTEMTIME s;
FILETIME ff;
SYSTEMTIME ss;
LARGE_INTEGER offset;
time_t tt = 0;
localtime_s(&tm1, &tt);
ss.wYear = tm1.tm_year + 1900;
ss.wMonth = tm1.tm_mon + 1;
ss.wDay = tm1.tm_mday;
ss.wHour = tm1.tm_hour;
ss.wMinute = tm1.tm_min;
ss.wSecond = tm1.tm_sec;
ss.wMilliseconds = 0;
SystemTimeToFileTime(&ss, &ff);
offset.QuadPart = ff.dwHighDateTime;
offset.QuadPart <<= 32;
offset.QuadPart |= ff.dwLowDateTime;
s.wYear = timep->tm_year + 1900;
s.wMonth = timep->tm_mon + 1;
s.wDay = timep->tm_mday;
s.wHour = timep->tm_hour;
s.wMinute = timep->tm_min;
s.wSecond = timep->tm_sec;
s.wMilliseconds = 0;
SystemTimeToFileTime(&s, &f);
t.QuadPart = f.dwHighDateTime;
t.QuadPart <<= 32;
t.QuadPart |= f.dwLowDateTime;
t.QuadPart -= offset.QuadPart;
return (time_t)(t.QuadPart / 10000000);
#else
time_t result = mktime(timep);
if (result != -1) {
return result;
}
#ifdef _MSC_VER
#if _MSC_VER >= 1900
int64_t tz = _timezone;
#endif
#endif
int64_t tzw = 0;
#ifdef _MSC_VER
#if _MSC_VER >= 1900
tzw = _timezone;
#endif
#endif
return user_mktime64(timep->tm_year + 1900, timep->tm_mon + 1, timep->tm_mday, timep->tm_hour, timep->tm_min,
timep->tm_sec, tz);
#endif
timep->tm_sec, tzw);
#else
time_t r = tz != NULL ? mktime_z(tz, timep) : mktime(timep);
if (r == (time_t)-1) {
@ -486,56 +448,7 @@ struct tm *taosGmTimeR(const time_t *timep, struct tm *result){
return NULL;
}
#ifdef WINDOWS
if (*timep < -2208988800LL) {
if (buf != NULL) {
snprintf(buf, bufSize, "NaN");
}
return NULL;
} else if (*timep < 0) {
SYSTEMTIME ss, s;
FILETIME ff, f;
LARGE_INTEGER offset;
struct tm tm1;
time_t tt = 0;
if (localtime_s(&tm1, &tt) != 0) {
if (buf != NULL) {
snprintf(buf, bufSize, "NaN");
}
return NULL;
}
ss.wYear = tm1.tm_year + 1900;
ss.wMonth = tm1.tm_mon + 1;
ss.wDay = tm1.tm_mday;
ss.wHour = tm1.tm_hour;
ss.wMinute = tm1.tm_min;
ss.wSecond = tm1.tm_sec;
ss.wMilliseconds = 0;
SystemTimeToFileTime(&ss, &ff);
offset.QuadPart = ff.dwHighDateTime;
offset.QuadPart <<= 32;
offset.QuadPart |= ff.dwLowDateTime;
offset.QuadPart += *timep * 10000000;
f.dwLowDateTime = offset.QuadPart & 0xffffffff;
f.dwHighDateTime = (offset.QuadPart >> 32) & 0xffffffff;
FileTimeToSystemTime(&f, &s);
result->tm_sec = s.wSecond;
result->tm_min = s.wMinute;
result->tm_hour = s.wHour;
result->tm_mday = s.wDay;
result->tm_mon = s.wMonth - 1;
result->tm_year = s.wYear - 1900;
result->tm_wday = s.wDayOfWeek;
result->tm_yday = 0;
result->tm_isdst = 0;
} else {
if (localtime_s(result, timep) != 0) {
if (buf != NULL) {
snprintf(buf, bufSize, "NaN");
}
return NULL;
}
}
return gmtime_s(result, timep);
#else
return gmtime_r(timep, result);
#endif
@ -545,7 +458,11 @@ time_t taosTimeGm(struct tm *tmp){
if (tmp == NULL) {
return -1;
}
#ifdef WINDOWS
return _mkgmtime(tmp);
#else
return timegm(tmp);
#endif
}
struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf, int32_t bufSize, timezone_t tz) {

View File

@ -790,7 +790,11 @@ int32_t taosGetLocalTimezoneOffset() {
uError("%s failed to get local time: code:%d", __FUNCTION__, errno);
return TSDB_CODE_TIME_ERROR;
}
#ifdef WINDOWS
return -_timezone;
#else
return (int32_t)(tm1.tm_gmtoff);
#endif
}
int32_t taosFormatTimezoneStr(time_t t, const char* tz, timezone_t sp, char *outTimezoneStr){

View File

@ -871,7 +871,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_AUDIT_FAIL_SEND_AUDIT_RECORD, "Failed to send out
TAOS_DEFINE_ERROR(TSDB_CODE_AUDIT_FAIL_GENERATE_JSON, "Failed to generate json")
//TIMEZONE
TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_TIMEZONE, "Invalid timezone")
TAOS_DEFINE_ERROR(TSDB_CODE_NOT_SUPPORTTED_IN_WINDOWS,"Operation not supported in windows")
#ifdef TAOS_ERROR_C
};
#endif

View File

@ -225,7 +225,7 @@ class TDTestCase:
tdSql.checkEqual(True, len(tdSql.queryResult) in range(282, 283))
tdSql.query("select * from information_schema.ins_columns where db_name ='performance_schema'")
tdSql.checkEqual(56, len(tdSql.queryResult))
tdSql.checkEqual(60, len(tdSql.queryResult))
def ins_dnodes_check(self):
tdSql.execute('drop database if exists db2')

View File

@ -142,9 +142,7 @@ class TDTestCase:
tdSql.query(f"select ts from {self.dbname}.d5")
tdSql.checkData(0, 0, "2021-07-01 20:00:00.000")
tdSql.execute(f"insert into {self.dbname}.d6 using {self.dbname}.stb tags (1) values ('2021-07-01T00:00:00.000-115',1)")
tdSql.query(f"select ts from {self.dbname}.d6")
tdSql.checkData(0, 0, "2021-07-01 19:05:00.000")
tdSql.error(f"insert into {self.dbname}.d6 using {self.dbname}.stb tags (1) values ('2021-07-01T00:00:00.000-115',1)")
tdSql.execute(f"insert into {self.dbname}.d7 using {self.dbname}.stb tags (1) values ('2021-07-01T00:00:00.000-1105',1)")
tdSql.query(f"select ts from {self.dbname}.d7")