feat:[TD-32642] add timezone support in windows
This commit is contained in:
parent
61f11ddb4e
commit
adff8a60d1
|
@ -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 *);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue