feat:[TD-32642] add timezone logic

This commit is contained in:
wangmm0220 2024-11-22 18:31:51 +08:00
parent 7aef49638e
commit 69da972796
39 changed files with 1438 additions and 679 deletions

View File

@ -58,19 +58,7 @@ static FORCE_INLINE int64_t taosGetTimestamp(int32_t precision) {
* precision == TSDB_TIME_PRECISION_MILLI, it returns timestamp in millisecond.
* precision == TSDB_TIME_PRECISION_NANO, it returns timestamp in nanosecond.
*/
static FORCE_INLINE int64_t taosGetTimestampToday(int32_t precision) {
int64_t factor = (precision == TSDB_TIME_PRECISION_MILLI) ? 1000
: (precision == TSDB_TIME_PRECISION_MICRO) ? 1000000
: 1000000000;
time_t t = taosTime(NULL);
struct tm tm;
(void) taosLocalTime(&t, &tm, NULL, 0); //tztodo
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
return (int64_t)taosMktime(&tm) * factor;
}
int64_t taosGetTimestampToday(int32_t precision, timezone_t tz);
int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision);
@ -81,13 +69,12 @@ int32_t taosTimeCountIntervalForFill(int64_t skey, int64_t ekey, int64_t interva
int32_t parseAbsoluteDuration(const char* token, int32_t tokenlen, int64_t* ts, char* unit, int32_t timePrecision);
int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit, int32_t timePrecision, bool negativeAllow);
int32_t taosParseTime(const char* timestr, int64_t* pTime, int32_t len, int32_t timePrec);
void deltaToUtcInitOnce();
int32_t taosParseTime(const char* timestr, int64_t* pTime, int32_t len, int32_t timePrec, timezone_t tz);
char getPrecisionUnit(int32_t precision);
int64_t convertTimePrecision(int64_t ts, int32_t fromPrecision, int32_t toPrecision);
int32_t convertTimeFromPrecisionToUnit(int64_t time, int32_t fromPrecision, char toUnit, int64_t* pRes);
int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec, int64_t* timeVal);
int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec, int64_t* timeVal, timezone_t tz);
int32_t getDuration(int64_t val, char unit, int64_t* result, int32_t timePrecision);
int32_t taosFormatUtcTime(char* buf, int32_t bufLen, int64_t ts, int32_t precision);
@ -97,8 +84,8 @@ struct STm {
int64_t fsec; // in NANOSECOND
};
int32_t taosTs2Tm(int64_t ts, int32_t precision, struct STm* tm);
int32_t taosTm2Ts(struct STm* tm, int64_t* ts, int32_t precision);
int32_t taosTs2Tm(int64_t ts, int32_t precision, struct STm* tm, timezone_t tz);
int32_t taosTm2Ts(struct STm* tm, int64_t* ts, int32_t precision, timezone_t tz);
/// @brief convert a timestamp to a formatted string
/// @param format the timestamp format, must null terminated
@ -107,7 +94,7 @@ int32_t taosTm2Ts(struct STm* tm, int64_t* ts, int32_t precision);
/// formats array; If not NULL, [formats] will be used instead of [format] to skip parse formats again.
/// @param out output buffer, should be initialized by memset
/// @notes remember to free the generated formats
int32_t taosTs2Char(const char* format, SArray** formats, int64_t ts, int32_t precision, char* out, int32_t outLen);
int32_t taosTs2Char(const char* format, SArray** formats, int64_t ts, int32_t precision, char* out, int32_t outLen, timezone_t tz);
/// @brief convert a formatted timestamp string to a timestamp
/// @param format must null terminated
/// @param [in, out] formats, see taosTs2Char
@ -115,7 +102,7 @@ int32_t taosTs2Char(const char* format, SArray** formats, int64_t ts, int32_t pr
/// @retval 0 for success, otherwise error occured
/// @notes remember to free the generated formats even when error occured
int32_t taosChar2Ts(const char* format, SArray** formats, const char* tsStr, int64_t* ts, int32_t precision, char* errMsg,
int32_t errMsgLen);
int32_t errMsgLen, timezone_t tz);
int32_t TEST_ts2char(const char* format, int64_t ts, int32_t precision, char* out, int32_t outLen);
int32_t TEST_char2ts(const char* format, int64_t* ts, int32_t precision, const char* tsStr);

View File

@ -292,6 +292,7 @@ struct SScalarParam {
void *param; // other parameter, such as meta handle from vnode, to extract table name/tag value
int32_t numOfRows;
int32_t numOfQualified; // number of qualified elements in the final results
timezone_t tz;
};
#define cleanupResultRowEntry(p) p->initialized = false

View File

@ -129,8 +129,9 @@ typedef struct SValueNode {
double d;
char* p;
} datum;
int64_t typeData;
int8_t unit;
int64_t typeData;
int8_t unit;
timezone_t tz;
} SValueNode;
typedef struct SLeftValueNode {
@ -159,6 +160,7 @@ typedef struct SOperatorNode {
EOperatorType opType;
SNode* pLeft;
SNode* pRight;
timezone_t tz;
} SOperatorNode;
typedef struct SLogicConditionNode {
@ -191,6 +193,8 @@ typedef struct SFunctionNode {
int32_t originalFuncId;
ETrimType trimType;
bool dual; // whether select stmt without from stmt, true for without.
// char timezone[TD_TIMEZONE_LEN];
timezone_t tz;
} SFunctionNode;
typedef struct STableNode {
@ -399,6 +403,7 @@ typedef struct SCaseWhenNode {
SNode* pCase;
SNode* pElse;
SNodeList* pWhenThenList;
timezone_t tz;
} SCaseWhenNode;
typedef struct SWindowOffsetNode {

View File

@ -101,6 +101,7 @@ typedef struct SParseContext {
int8_t biMode;
SArray* pSubMetaList;
setQueryFn setQueryFp;
timezone_t timezone;
} SParseContext;
int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery);

View File

@ -92,15 +92,16 @@ static FORCE_INLINE int64_t taosGetMonoTimestampMs() {
}
char *taosStrpTime(const char *buf, const char *fmt, struct tm *tm);
struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf, int32_t bufSize);
struct tm *taosLocalTimeNolock(struct tm *result, const time_t *timep, int dst);
struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf, int32_t bufSize, timezone_t tz);
struct tm *taosGmTimeR(const time_t *timep, struct tm *result);
time_t taosTimeGm(struct tm *tmp);
time_t taosTime(time_t *t);
time_t taosMktime(struct tm *timep);
time_t taosMktime(struct tm *timep, timezone_t tz);
int64_t user_mktime64(const uint32_t year, const uint32_t mon, const uint32_t day, const uint32_t hour,
const uint32_t min, const uint32_t sec, int64_t time_zone);
struct tm *taosLocalTimeRz(timezone_t state, const time_t *timep, struct tm *result);
time_t taosMktimeRz(timezone_t state, struct tm *timep);
//struct tm *taosLocalTimeRz(timezone_t state, const time_t *timep, struct tm *result);
//time_t taosMktimeRz(timezone_t state, struct tm *timep);
#ifdef __cplusplus
}
#endif

View File

@ -300,7 +300,8 @@ int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtC
.svrVer = pTscObj->sVer,
.nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes),
.isStmtBind = pRequest->isStmtBind,
.setQueryFp = setQueryRequest};
.setQueryFp = setQueryRequest,
.timezone = pTscObj->optionInfo.timezone,};
cxt.mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
int32_t code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &cxt.pCatalog);

View File

@ -1342,7 +1342,8 @@ int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SS
.allocatorId = pRequest->allocatorRefId,
.parseSqlFp = clientParseSql,
.parseSqlParam = pWrapper,
.setQueryFp = setQueryRequest};
.setQueryFp = setQueryRequest,
.timezone = pTscObj->optionInfo.timezone};
int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
(*pCxt)->biMode = biMode;
return TSDB_CODE_SUCCESS;

View File

@ -35,12 +35,12 @@ TARGET_INCLUDE_DIRECTORIES(
PRIVATE "${TD_SOURCE_DIR}/source/client/inc"
)
IF(${TD_LINUX})
#IF(${TD_LINUX})
add_test(
NAME clientTest
COMMAND clientTest
)
ENDIF ()
#ENDIF ()
TARGET_INCLUDE_DIRECTORIES(
tmqTest

View File

@ -1489,127 +1489,352 @@ TEST(clientCase, sub_tb_mt_test) {
}
}
TEST(clientCase, timezone_Test) {
{
// taos_options( TSDB_OPTION_TIMEZONE, "UTC-8");
int code = taos_options(TSDB_OPTION_TIMEZONE, "UTC-8");
ASSERT_TRUE(code == 0);
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
TAOS* getConnWithGlobalOption(const char *tz){
int code = taos_options(TSDB_OPTION_TIMEZONE, tz);
ASSERT(code == 0);
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT(pConn != nullptr);
return pConn;
}
TAOS_RES* pRes = taos_query(pConn, "drop database if exists db1");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
TAOS* getConnWithOption(const char *tz){
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT(pConn != nullptr);
if (tz != NULL){
int code = taos_options_connection(pConn, TSDB_OPTION_CONNECTION_TIMEZONE, tz);
ASSERT(code == 0);
}
return pConn;
}
pRes = taos_query(pConn, "create database db1");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
void execQuery(TAOS* pConn, const char *sql){
TAOS_RES* pRes = taos_query(pConn, sql);
ASSERT(taos_errno(pRes) == TSDB_CODE_SUCCESS);
taos_free_result(pRes);
}
pRes = taos_query(pConn, "create table db1.t1 (ts timestamp, v int)");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
void execQueryFail(TAOS* pConn, const char *sql){
TAOS_RES* pRes = taos_query(pConn, sql);
ASSERT(taos_errno(pRes) != TSDB_CODE_SUCCESS);
taos_free_result(pRes);
}
char sql[256] = {0};
(void)sprintf(sql, "insert into db1.t1 values('2023-09-16 17:00:00', 1)");
pRes = taos_query(pConn, sql);
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
void checkRows(TAOS* pConn, const char *sql, int32_t expectedRows){
TAOS_RES* pRes = taos_query(pConn, sql);
ASSERT(taos_errno(pRes) == TSDB_CODE_SUCCESS);
TAOS_ROW pRow = NULL;
int rows = 0;
while ((pRow = taos_fetch_row(pRes)) != NULL) {
rows++;
}
ASSERT(rows == expectedRows);
taos_free_result(pRes);
}
pRes = taos_query(pConn, "select * from db1.t1 where ts == '2023-09-16 17:00:00'");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
TAOS_ROW pRow = NULL;
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
int32_t numOfFields = taos_num_fields(pRes);
char str[512] = {0};
int rows = 0;
while ((pRow = taos_fetch_row(pRes)) != NULL) {
rows++;
void check_timezone(TAOS* pConn, const char *sql, const char* tz){
TAOS_RES *pRes = taos_query(pConn, sql);
ASSERT(taos_errno(pRes) == 0);
TAOS_ROW row = NULL;
while ((row = taos_fetch_row(pRes)) != NULL) {
if (strcmp((const char*)row[0], "timezone") == 0){
ASSERT(strstr((const char*)row[1], tz) != NULL);
}
ASSERT_TRUE(rows == 1);
}
taos_free_result(pRes);
}
taos_free_result(pRes);
void check_sql_result_partial(TAOS* pConn, const char *sql, const char* result){
TAOS_RES *pRes = taos_query(pConn, sql);
ASSERT(taos_errno(pRes) == 0);
TAOS_ROW row = NULL;
while ((row = taos_fetch_row(pRes)) != NULL) {
ASSERT(strstr((const char*)row[0], result) != NULL);
}
taos_free_result(pRes);
}
int64_t get_sql_result(TAOS* pConn, const char *sql){
int64_t ts = 0;
TAOS_RES *pRes = taos_query(pConn, sql);
ASSERT(taos_errno(pRes) == 0);
TAOS_ROW row = NULL;
while ((row = taos_fetch_row(pRes)) != NULL) {
ts = *(int64_t*)row[0];
}
taos_free_result(pRes);
return ts;
}
void check_sql_result(TAOS* pConn, const char *sql, const char* result){
TAOS_RES *pRes = taos_query(pConn, sql);
ASSERT(taos_errno(pRes) == 0);
TAOS_ROW row = NULL;
while ((row = taos_fetch_row(pRes)) != NULL) {
ASSERT (strcmp((const char*)row[0], result) == 0);
}
taos_free_result(pRes);
}
void check_sql_result_integer(TAOS* pConn, const char *sql, int64_t result){
TAOS_RES *pRes = taos_query(pConn, sql);
ASSERT(taos_errno(pRes) == 0);
TAOS_ROW row = NULL;
while ((row = taos_fetch_row(pRes)) != NULL) {
ASSERT (*(int64_t*)row[0] == result);
}
taos_free_result(pRes);
}
void check_set_timezone(TAOS* optionFunc(const char *tz)){
{
TAOS* pConn = optionFunc("UTC-8");
check_timezone(pConn, "show local variables", "UTC-8");
execQuery(pConn, "drop database if exists db1");
execQuery(pConn, "create database db1");
execQuery(pConn, "create table db1.t1 (ts timestamp, v int)");
execQuery(pConn, "insert into db1.t1 values('2023-09-16 17:00:00', 1)");
checkRows(pConn, "select * from db1.t1 where ts == '2023-09-16 17:00:00'", 1);
taos_close(pConn);
}
{
// taos_options( TSDB_OPTION_TIMEZONE, "UTC+8");
int code = taos_options(TSDB_OPTION_TIMEZONE, "UTC+8");
ASSERT_TRUE(code == 0);
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
TAOS_RES* pRes = taos_query(pConn, "select * from db1.t1 where ts == '2023-09-16 01:00:00'");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
TAOS_ROW pRow = NULL;
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
int32_t numOfFields = taos_num_fields(pRes);
int rows = 0;
char str[512] = {0};
while ((pRow = taos_fetch_row(pRes)) != NULL) {
rows++;
}
ASSERT_TRUE(rows == 1);
taos_free_result(pRes);
char sql[256] = {0};
(void)sprintf(sql, "insert into db1.t1 values('2023-09-16 17:00:01', 1)");
pRes = taos_query(pConn, sql);
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
TAOS* pConn = optionFunc("UTC+8");
check_timezone(pConn, "show local variables", "UTC+8");
checkRows(pConn, "select * from db1.t1 where ts == '2023-09-16 01:00:00'", 1);
execQuery(pConn, "insert into db1.t1 values('2023-09-16 17:00:01', 1)");
taos_close(pConn);
}
{
// taos_options( TSDB_OPTION_TIMEZONE, "UTC+0");
int code = taos_options(TSDB_OPTION_TIMEZONE, "UTC+0");
ASSERT_TRUE(code == 0);
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
TAOS_RES* pRes = taos_query(pConn, "select * from db1.t1 where ts == '2023-09-16 09:00:00'");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
TAOS_ROW pRow = NULL;
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
int32_t numOfFields = taos_num_fields(pRes);
int rows = 0;
char str[512] = {0};
while ((pRow = taos_fetch_row(pRes)) != NULL) {
rows++;
}
ASSERT_TRUE(rows == 1);
taos_free_result(pRes);
{
TAOS_RES* pRes = taos_query(pConn, "select * from db1.t1 where ts == '2023-09-17 01:00:01'");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
TAOS_ROW pRow = NULL;
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
int32_t numOfFields = taos_num_fields(pRes);
int rows = 0;
char str[512] = {0};
while ((pRow = taos_fetch_row(pRes)) != NULL) {
rows++;
}
ASSERT_TRUE(rows == 1);
taos_free_result(pRes);
}
TAOS* pConn = optionFunc("UTC+0");
check_timezone(pConn, "show local variables", "UTC+0");
checkRows(pConn, "select * from db1.t1 where ts == '2023-09-16 09:00:00'", 1);
checkRows(pConn, "select * from db1.t1 where ts == '2023-09-17 01:00:01'", 1);
taos_close(pConn);
}
}
TEST(clientCase, set_timezone_Test) {
check_set_timezone(getConnWithGlobalOption);
check_set_timezone(getConnWithOption);
}
TEST(clientCase, alter_timezone_Test) {
TAOS* pConn = getConnWithGlobalOption("UTC-8");
check_timezone(pConn, "show local variables", "UTC-8");
execQuery(pConn, "alter local 'timezone Asia/Kolkata'");
check_timezone(pConn, "show local variables", "Asia/Kolkata");
execQueryFail(pConn, "alter dnode 1 'timezone Asia/Kolkata'");
}
struct insert_params
{
const char *tz;
const char *tbname;
const char *t1;
const char *t2;
};
struct insert_params params1[] = {
{"UTC", "ntb", "2023-09-16 17:00:00", "2023-09-16 17:00:00+08:00"},
{"UTC", "ctb1", "2023-09-16 17:00:00", "2023-09-16 17:00:00+08:00"},
};
struct insert_params params2[] = {
{"UTC+9", "ntb", "2023-09-16 08:00:00", "2023-09-16 08:00:00-01:00"},
{"UTC+9", "ctb1", "2023-09-16 08:00:00", "2023-09-16 11:00:00+02:00"},
};
void do_insert(struct insert_params params){
TAOS* pConn = getConnWithOption(params.tz);
char sql[1024] = {0};
(void)snprintf(sql, sizeof(sql), "insert into db1.%s values('%s', '%s', 1)", params.tbname, params.t1, params.t2);
execQuery(pConn, sql);
taos_close(pConn);
}
void do_select(struct insert_params params){
TAOS* pConn = getConnWithOption(params.tz);
char sql[1024] = {0};
(void)snprintf(sql, sizeof(sql), "select * from db1.%s where ts == '%s' and c1 == '%s'", params.tbname, params.t1, params.t2);
checkRows(pConn, sql, 1);
taos_close(pConn);
}
// test insert string and integer to timestamp both normal table and child table(and tag)
TEST(clientCase, insert_with_timezone_Test) {
/*
* 1. prepare data, create db and tables
*/
TAOS* pConn1 = getConnWithOption("UTC+2");
execQuery(pConn1, "drop database if exists db1");
execQuery(pConn1, "create database db1");
execQuery(pConn1, "create table db1.ntb (ts timestamp, c1 timestamp, c2 int)");
execQuery(pConn1, "create table db1.stb (ts timestamp, c1 timestamp, c2 int) tags(t1 timestamp, t2 timestamp, t3 int)");
execQuery(pConn1, "create table db1.ctb1 using db1.stb tags(\"2023-09-16 17:00:00+05:00\", \"2023-09-16 17:00:00\", 1)");
execQuery(pConn1, "create table db1.ctb2 using db1.stb tags(1732178775000, 1732178775000, 1)");
execQuery(pConn1, "insert into db1.ntb values(1732178775133, 1732178775133, 1)");
execQuery(pConn1, "insert into db1.ctb1 values(1732178775133, 1732178775133, 1)");
execQuery(pConn1, "insert into db1.ctb2 values(1732178775133, 1732178775133, 1)");
/*
* 2. test tag and timestamp with integer format
*/
TAOS* pConn2 = getConnWithOption("UTC-2");
checkRows(pConn2, "select * from db1.stb where t1 == '2023-09-16 17:00:00+05:00' and t2 == '2023-09-16 21:00:00'", 1);
checkRows(pConn2, "select * from db1.stb where t1 == '2024-11-21 16:46:15+08:00' and t2 == '2024-11-21 09:46:15+01:00'", 1);
checkRows(pConn2, "select * from db1.ntb where ts == '2024-11-21 09:46:15.133+01:00' and c1 == '2024-11-21 10:46:15.133'", 1);
checkRows(pConn2, "select * from db1.ctb1 where ts == '2024-11-21 09:46:15.133+01:00' and c1 == '2024-11-21 10:46:15.133'", 1);
check_sql_result(pConn2, "select TO_ISO8601(ts) from db1.ctb1", "2024-11-21T10:46:15.133+0200"); // 2024-01-01 23:00:00+0200
/*
* 3. test timestamp with string format
*/
for (unsigned int i = 0; i < sizeof (params1) / sizeof (params1[0]); ++i){
do_insert(params1[i]);
do_select(params1[i]);
do_select(params2[i]);
}
/*
* 4. test NULL timezone, use default timezone UTC-8
*/
TAOS* pConn3 = getConnWithOption(NULL);
checkRows(pConn3, "select * from db1.stb where t1 == '2023-09-16 20:00:00' and t2 == '2023-09-17 03:00:00'", 2);
checkRows(pConn3, "select * from db1.stb where t1 == 1732178775000 and t2 == 1732178775000", 1);
checkRows(pConn3, "select * from db1.ntb where ts == '2024-11-21 16:46:15.133' and c1 == '2024-11-21 16:46:15.133'", 1);
checkRows(pConn3, "select * from db1.ctb1 where ts == '2023-09-17 01:00:00' and c1 == '2023-09-16 17:00:00'", 1);
/*
* 5. test multi connection with different timezone
*/
checkRows(pConn2, "select * from db1.ctb1 where ts == '2024-11-21 09:46:15.133+01:00' and c1 == '2024-11-21 10:46:15.133'", 1);
checkRows(pConn1, "select * from db1.ctb1 where ts == '2024-11-21 09:46:15.133+01:00' and c1 == '2024-11-21 06:46:15.133'", 1);
taos_close(pConn1);
taos_close(pConn2);
taos_close(pConn3);
}
TEST(clientCase, func_timezone_Test) {
TAOS* pConn = getConnWithGlobalOption("UTC+8");
check_sql_result(pConn, "select timezone()", "UTC+8 (UTC, -0800)");
taos_close(pConn);
pConn = getConnWithOption("UTC-2");
execQuery(pConn, "drop database if exists db1");
execQuery(pConn, "create database db1");
execQuery(pConn, "create table db1.ntb (ts timestamp, c1 binary(32), c2 int)");
execQuery(pConn, "insert into db1.ntb values(1704142800000, '2024-01-01 23:00:00', 1)"); // 2024-01-01 23:00:00+0200
// test timezone
check_sql_result(pConn, "select timezone()", "UTC-test (UTC, +0200)");
// test timetruncate
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-01 23:00:00', 1d, 0))", "2024-01-01T02:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-01 01:00:00', 1d, 0))", "2023-12-31T02:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-01 01:00:00+0300', 1d, 0))", "2023-12-31T02:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-01 01:00:00-0300', 1d, 0))", "2024-01-01T02:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-04 23:00:00', 1w, 0))", "2024-01-04T02:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-04 01:00:00', 1w, 0))", "2023-12-28T02:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-04 01:00:00+0300', 1w, 0))", "2023-12-28T02:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-04 01:00:00-0300', 1w, 0))", "2024-01-04T02:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-01 23:00:00', 1d, 1))", "2024-01-01T00:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-01 01:00:00', 1d, 1))", "2024-01-01T00:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-01 01:00:00+0500', 1d, 1))", "2023-12-31T00:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-01 01:00:00-0300', 1d, 1))", "2024-01-01T00:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-04 23:00:00', 1w, 1))", "2024-01-04T00:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-04 01:00:00', 1w, 1))", "2024-01-04T00:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-04 01:00:00+0500', 1w, 1))", "2023-12-28T00:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE('2024-01-04 01:00:00-0300', 1w, 1))", "2024-01-04T00:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE(1704142800000, 1d, 0))", "2024-01-01T02:00:00.000+0200"); // 2024-01-01 23:00:00+0200
check_sql_result(pConn, "select TO_ISO8601(TIMETRUNCATE(ts, 1w, 1)) from db1.ntb", "2023-12-28T00:00:00.000+0200"); // 2024-01-01 23:00:00+0200
// int64_t now = get_sql_result(pConn, "select now(),now() + 2d");
// int64_t locationNow = now + 2 * 3600;
// check_sql_result_partial(pConn, "select TO_ISO8601(today())", "T00:00:00.000+0200"); // 2024-01-01 23:00:00+0200
// check_sql_result_partial(pConn, "select TO_ISO8601(now())", "+0200"); // 2024-01-01 23:00:00+0200
// WEEKDAY
check_sql_result_integer(pConn, "select WEEKDAY('2024-01-01')", 0);
check_sql_result_integer(pConn, "select WEEKDAY('2024-01-01 03:00:00')", 0);
check_sql_result_integer(pConn, "select WEEKDAY('2024-01-01 23:00:00+0200')", 0);
check_sql_result_integer(pConn, "select WEEKDAY('2024-01-01 23:00:00-1100')", 1);
check_sql_result_integer(pConn, "select WEEKDAY(1704142800000)", 0);
check_sql_result_integer(pConn, "select WEEKDAY(ts) from db1.ntb", 1);
// DAYOFWEEK
check_sql_result_integer(pConn, "select DAYOFWEEK('2024-01-01')", 2);
check_sql_result_integer(pConn, "select DAYOFWEEK('2024-01-01 03:00:00')", 2);
check_sql_result_integer(pConn, "select DAYOFWEEK('2024-01-01 23:00:00+0200')", 2);
check_sql_result_integer(pConn, "select DAYOFWEEK('2024-01-01 23:00:00-1100')", 3);
check_sql_result_integer(pConn, "select DAYOFWEEK(1704142800000)", 2);
check_sql_result_integer(pConn, "select DAYOFWEEK(ts) from db1.ntb", 3);
// WEEK
check_sql_result_integer(pConn, "select WEEK('2024-01-07')", 1);
check_sql_result_integer(pConn, "select WEEK('2024-01-07 02:00:00')", 1);
check_sql_result_integer(pConn, "select WEEK('2024-01-07 02:00:00+0200')", 1);
check_sql_result_integer(pConn, "select WEEK('2024-01-07 02:00:00+1100')", 0);
check_sql_result_integer(pConn, "select WEEK(1704142800000)", 0); // 2024-01-01 23:00:00+0200
check_sql_result_integer(pConn, "select WEEK(ts) from db1.ntb", 0); // 2024-01-01 23:00:00+0200
check_sql_result_integer(pConn, "select WEEK('2024-01-07', 3)", 1);
check_sql_result_integer(pConn, "select WEEK('2024-01-07 02:00:00', 3)", 1);
check_sql_result_integer(pConn, "select WEEK('2024-01-07 02:00:00+0200', 3)", 1);
check_sql_result_integer(pConn, "select WEEK('2024-01-01 02:00:00+1100', 3)", 52);
check_sql_result_integer(pConn, "select WEEK(1704142800000, 3)", 1); // 2024-01-01 23:00:00+0200
check_sql_result_integer(pConn, "select WEEK(ts, 3) from db1.ntb", 1); // 2024-01-01 23:00:00+0200
// WEEKOFYEAR
check_sql_result_integer(pConn, "select WEEKOFYEAR('2024-01-07')", 1);
check_sql_result_integer(pConn, "select WEEKOFYEAR('2024-01-07 02:00:00')", 1);
check_sql_result_integer(pConn, "select WEEKOFYEAR('2024-01-07 02:00:00+0200')", 1);
check_sql_result_integer(pConn, "select WEEKOFYEAR('2024-01-01 02:00:00+1100')", 52);
check_sql_result_integer(pConn, "select WEEKOFYEAR(1704142800000)", 1); // 2024-01-01 23:00:00+0200
check_sql_result_integer(pConn, "select WEEKOFYEAR(ts) from db1.ntb", 1); // 2024-01-01 23:00:00+0200
// TO_ISO8601
check_sql_result(pConn, "select TO_ISO8601(ts) from db1.ntb", "2024-01-01T23:00:00.000+0200");
check_sql_result(pConn, "select TO_ISO8601(ts,'-08') from db1.ntb", "2024-01-01T13:00:00.000-08");
check_sql_result(pConn, "select TO_ISO8601(1)", "1970-01-01T02:00:00.001+0200");
check_sql_result(pConn, "select TO_ISO8601(1,'+0800')", "1970-01-01T08:00:00.001+0800");
// TO_UNIXTIMESTAMP
check_sql_result_integer(pConn, "select TO_UNIXTIMESTAMP(c1) from db1.ntb", 1704121200000); // use timezone in server UTC-8
check_sql_result_integer(pConn, "select TO_UNIXTIMESTAMP('2024-01-01T23:00:00.000+0200')", 1704142800000);
check_sql_result_integer(pConn, "select TO_UNIXTIMESTAMP('2024-01-01T13:00:00.000-08')", 1704142800000);
check_sql_result_integer(pConn, "select TO_UNIXTIMESTAMP('2024-01-01T23:00:00.001')", 1704142800001);
// TO_TIMESTAMP
check_sql_result_integer(pConn, "select TO_TIMESTAMP(c1,'yyyy-mm-dd hh24:mi:ss') from db1.ntb", 1704121200000); // use timezone in server UTC-8
check_sql_result_integer(pConn, "select TO_TIMESTAMP('2024-01-01 23:00:00+02:00', 'yyyy-mm-dd hh24:mi:ss tzh')", 1704142800000);
check_sql_result_integer(pConn, "select TO_TIMESTAMP('2024-01-01T13:00:00-08', 'yyyy-mm-ddThh24:mi:ss tzh')", 1704142800000);
check_sql_result_integer(pConn, "select TO_TIMESTAMP('2024/01/01 23:00:00', 'yyyy/mm/dd hh24:mi:ss')", 1704142800000);
// TO_CHAR
check_sql_result(pConn, "select TO_CHAR(ts,'yyyy-mm-dd hh24:mi:ss') from db1.ntb", "2024-01-02 05:00:00"); // use timezone in server UTC-8
check_sql_result(pConn, "select TO_CHAR(cast(1704142800000 as timestamp), 'yyyy-mm-dd hh24:mi:ss tzh')", "2024-01-01 23:00:00 +02");
check_sql_result(pConn, "select TO_CHAR(cast(1704142800000 as timestamp), 'yyyy-mm-dd hh24:mi:ss')", "2024-01-01 23:00:00");
taos_close(pConn);
}
time_t time_winter = 1731323281; // 2024-11-11 19:08:01+0800
time_t time_summer = 1731323281 - 120 * 24 * 60 * 60;
@ -1697,7 +1922,7 @@ TEST(clientCase, mktime_Test){
for (unsigned int i = 0; i < sizeof (test_mk) / sizeof (test_mk[0]); ++i)
{
setenv ("TZ", test_mk[i].env, 1);
t = taosMktime (&tm);
t = taosMktime (&tm, NULL);
ASSERT (t == test_mk[i].expected);
}
}
@ -1719,7 +1944,7 @@ TEST(clientCase, mktime_rz_Test){
{
timezone_t tz = tzalloc(test_mk[i].env);
ASSERT(tz);
t = taosMktimeRz(tz, &tm);
t = taosMktime(&tm, tz);
ASSERT (t == test_mk[i].expected);
tzfree(tz);
}
@ -1739,13 +1964,12 @@ TEST(testCase, localtime_performance_Test) {
for (int j = 0; j < cnt; ++j) {
time_t t = time_winter - j;
struct tm tm1;
ASSERT (taosLocalTime(&t, &tm1, NULL, 0));
ASSERT (taosLocalTime(&t, &tm1, NULL, 0, NULL));
}
int64_t tmp = taosGetTimestampNs() - t1;
printf("localtime cost:%" PRId64 " ns, run %" PRId64 " times", tmp, cnt);
time_localtime += tmp/cnt;
timezone;
printf("\n");
@ -1754,7 +1978,7 @@ TEST(testCase, localtime_performance_Test) {
for (int j = 0; j < cnt; ++j) {
time_t t = time_winter - j;
struct tm tm1;
ASSERT (taosLocalTimeRz(sp, &t, &tm1));
ASSERT (taosLocalTime(&t, &tm1, NULL, 0, sp));
}
tmp = taosGetTimestampNs() - t2;
printf("localtime_rz cost:%" PRId64 " ns, run %" PRId64 " times", tmp, cnt);
@ -1765,4 +1989,5 @@ TEST(testCase, localtime_performance_Test) {
tzfree(sp);
}
#pragma GCC diagnostic pop

View File

@ -2473,7 +2473,7 @@ static int32_t formatTimestamp(char* buf, size_t cap, int64_t val, int precision
}
}
struct tm ptm = {0};
if (taosLocalTime(&tt, &ptm, buf, cap) == NULL) {
if (taosLocalTime(&tt, &ptm, buf, cap, NULL) == NULL) {
code = TSDB_CODE_INTERNAL_ERROR;
TSDB_CHECK_CODE(code, lino, _end);
}

View File

@ -2231,7 +2231,9 @@ static int32_t taosCfgDynamicOptionsForClient(SConfig *pCfg, const char *name) {
break;
}
case 't': {
if (strcasecmp("tempDir", name) == 0) {
if (strcasecmp("timezone", name) == 0) {
matched = true;
} else if (strcasecmp("tempDir", name) == 0) {
uInfo("%s set from %s to %s", name, tsTempDir, pItem->str);
tstrncpy(tsTempDir, pItem->str, PATH_MAX);
TAOS_CHECK_GOTO(taosExpandDir(tsTempDir, tsTempDir, PATH_MAX), &lino, _out);

View File

@ -292,7 +292,10 @@ int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol) {
char value[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0};
int32_t valueLen = 0;
TAOS_CHECK_GOTO(cfgDumpItemValue(pItem, &value[VARSTR_HEADER_SIZE], TSDB_CONFIG_VALUE_LEN, &valueLen), NULL, _exit);
if (pItem->dtype == CFG_DTYPE_TIMEZONE){
}
TAOS_CHECK_GOTO(cfgDumpItemValue(pItem, varDataVal(value), TSDB_CONFIG_VALUE_LEN, &valueLen), NULL, _exit);
varDataSetLen(value, valueLen);
pColInfo = taosArrayGet(pBlock->pDataBlock, col++);

View File

@ -20,73 +20,6 @@
#define VALID_NAME_TYPE(x) ((x) == TSDB_DB_NAME_T || (x) == TSDB_TABLE_NAME_T)
#if 0
int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, int64_t intervalTime, char timeUnit, int16_t precision) {
if (slidingTime == 0) {
return startTime;
}
int64_t start = startTime;
if (timeUnit == 'n' || timeUnit == 'y') {
start /= 1000;
if (precision == TSDB_TIME_PRECISION_MICRO) {
start /= 1000;
}
struct tm tm;
time_t t = (time_t)start;
taosLocalTime(&t, &tm, NULL, 0);
tm.tm_sec = 0;
tm.tm_min = 0;
tm.tm_hour = 0;
tm.tm_mday = 1;
if (timeUnit == 'y') {
tm.tm_mon = 0;
tm.tm_year = (int)(tm.tm_year / slidingTime * slidingTime);
} else {
int mon = tm.tm_year * 12 + tm.tm_mon;
mon = (int)(mon / slidingTime * slidingTime);
tm.tm_year = mon / 12;
tm.tm_mon = mon % 12;
}
start = mktime(&tm) * 1000L;
if (precision == TSDB_TIME_PRECISION_MICRO) {
start *= 1000L;
}
} else {
int64_t delta = startTime - intervalTime;
int32_t factor = delta > 0? 1:-1;
start = (delta / slidingTime + factor) * slidingTime;
if (timeUnit == 'd' || timeUnit == 'w') {
/*
* here we revised the start time of day according to the local time zone,
* but in case of DST, the start time of one day need to be dynamically decided.
*/
// todo refactor to extract function that is available for Linux/Windows/Mac platform
#if defined(WINDOWS) && _MSC_VER >= 1900
// see https://docs.microsoft.com/en-us/cpp/c-runtime-library/daylight-dstbias-timezone-and-tzname?view=vs-2019
int64_t timezone = _timezone;
int32_t daylight = _daylight;
char** tzname = _tzname;
#endif
int64_t t = (precision == TSDB_TIME_PRECISION_MILLI) ? MILLISECOND_PER_SECOND : MILLISECOND_PER_SECOND * 1000L;
start += timezone * t;
}
int64_t end = start + intervalTime - 1;
if (end < startTime) {
start += slidingTime;
}
}
return start;
}
#endif
void toName(int32_t acctId, const char* pDbName, const char* pTableName, SName* pName) {
if (pName == NULL){
return;

View File

@ -27,28 +27,24 @@
static int32_t parseFraction(char* str, char** end, int32_t timePrec, int64_t* pFraction);
static int32_t parseTimeWithTz(const char* timestr, int64_t* time, int32_t timePrec, char delim);
static int32_t parseLocaltime(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim);
static int32_t parseLocaltimeDst(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim);
static int32_t parseLocaltimeDst(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim, timezone_t tz);
static char* forwardToTimeStringEnd(char* str);
static bool checkTzPresent(const char* str, int32_t len);
static int32_t parseTimezone(char* str, int64_t* tzOffset);
static int32_t (*parseLocaltimeFp[])(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim) = {
parseLocaltime, parseLocaltimeDst};
int32_t taosParseTime(const char* timestr, int64_t* utime, int32_t len, int32_t timePrec) {
int32_t taosParseTime(const char* timestr, int64_t* utime, int32_t len, int32_t timePrec, timezone_t tz) {
/* parse datatime string in with tz */
if (strnchr(timestr, 'T', len, false) != NULL) {
if (checkTzPresent(timestr, len)) {
return parseTimeWithTz(timestr, utime, timePrec, 'T');
} else {
return parseLocaltimeDst((char*)timestr, len, utime, timePrec, 'T');
return parseLocaltimeDst((char*)timestr, len, utime, timePrec, 'T', tz);
}
} else {
if (checkTzPresent(timestr, len)) {
return parseTimeWithTz(timestr, utime, timePrec, 0);
} else {
return parseLocaltimeDst((char*)timestr, len, utime, timePrec, 0);
return parseLocaltimeDst((char*)timestr, len, utime, timePrec, 0, tz);
}
}
}
@ -165,7 +161,7 @@ int32_t parseTimezone(char* str, int64_t* tzOffset) {
i += 2;
}
if (hour > 12 || hour < 0) {
if (hour > 13 || hour < 0) {
TAOS_RETURN(TSDB_CODE_INVALID_PARA);
}
@ -176,7 +172,7 @@ int32_t parseTimezone(char* str, int64_t* tzOffset) {
}
int64_t minute = strnatoi(&str[i], 2);
if (minute > 59 || (hour == 12 && minute > 0)) {
if (minute > 59 || minute < 0) {
TAOS_RETURN(TSDB_CODE_INVALID_PARA);
}
@ -233,7 +229,10 @@ int32_t parseTimeWithTz(const char* timestr, int64_t* time, int32_t timePrec, ch
int64_t seconds = user_mktime64(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
// int64_t seconds = gmtime(&tm);
#else
int64_t seconds = timegm(&tm);
int64_t seconds = taosTimeGm(&tm);
if (seconds == -1){
TAOS_RETURN(TAOS_SYSTEM_ERROR(errno));
}
#endif
int64_t fraction = 0;
@ -298,48 +297,7 @@ static FORCE_INLINE bool validateTm(struct tm* pTm) {
return true;
}
int32_t parseLocaltime(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim) {
*utime = 0;
struct tm tm = {0};
char* str;
if (delim == 'T') {
str = taosStrpTime(timestr, "%Y-%m-%dT%H:%M:%S", &tm);
} else if (delim == 0) {
str = taosStrpTime(timestr, "%Y-%m-%d %H:%M:%S", &tm);
} else {
str = NULL;
}
if (str == NULL || (((str - timestr) < len) && (*str != '.')) || !validateTm(&tm)) {
// if parse failed, try "%Y-%m-%d" format
str = taosStrpTime(timestr, "%Y-%m-%d", &tm);
if (str == NULL || (((str - timestr) < len) && (*str != '.')) || !validateTm(&tm)) {
TAOS_RETURN(TSDB_CODE_INVALID_PARA);
}
}
#ifdef _MSC_VER
#if _MSC_VER >= 1900
int64_t timezone = _timezone;
#endif
#endif
int64_t seconds =
user_mktime64(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, timezone);
int64_t fraction = 0;
if (*str == '.') {
/* parse the second fraction part */
TAOS_CHECK_RETURN(parseFraction(str + 1, &str, timePrec, &fraction));
}
*utime = TSDB_TICK_PER_SECOND(timePrec) * seconds + fraction;
TAOS_RETURN(TSDB_CODE_SUCCESS);
}
int32_t parseLocaltimeDst(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim) {
int32_t parseLocaltimeDst(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim, timezone_t tz) {
*utime = 0;
struct tm tm = {0};
tm.tm_isdst = -1;
@ -361,8 +319,7 @@ int32_t parseLocaltimeDst(char* timestr, int32_t len, int64_t* utime, int32_t ti
}
}
/* mktime will be affected by TZ, set by using taos_options */
int64_t seconds = taosMktime(&tm); //tztodo
int64_t seconds = taosMktime(&tm, tz);
int64_t fraction = 0;
if (*str == '.') {
@ -523,7 +480,7 @@ int32_t convertTimeFromPrecisionToUnit(int64_t time, int32_t fromPrecision, char
TAOS_RETURN(TSDB_CODE_SUCCESS);
}
int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec, int64_t* timeVal) {
int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec, int64_t* timeVal, timezone_t tz) {
int32_t charLen = varDataLen(inputData);
char* newColData;
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_VARBINARY) {
@ -532,7 +489,7 @@ int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec
TAOS_RETURN(terrno);
}
(void)memcpy(newColData, varDataVal(inputData), charLen);
int32_t ret = taosParseTime(newColData, timeVal, charLen, (int32_t)timePrec);
int32_t ret = taosParseTime(newColData, timeVal, charLen, (int32_t)timePrec, tz);
if (ret != TSDB_CODE_SUCCESS) {
taosMemoryFree(newColData);
TAOS_RETURN(TSDB_CODE_INVALID_TIMESTAMP);
@ -549,7 +506,7 @@ int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec
TAOS_RETURN(TSDB_CODE_FAILED);
}
newColData[len] = 0;
int32_t ret = taosParseTime(newColData, timeVal, len, (int32_t)timePrec);
int32_t ret = taosParseTime(newColData, timeVal, len, (int32_t)timePrec, tz);
if (ret != TSDB_CODE_SUCCESS) {
taosMemoryFree(newColData);
TAOS_RETURN(ret);
@ -681,7 +638,10 @@ int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision) {
struct tm tm;
time_t tt = (time_t)(t / TSDB_TICK_PER_SECOND(precision));
struct tm* ptm = taosLocalTime(&tt, &tm, NULL, 0);
if(taosGmTimeR(&tt, &tm) == NULL) {
uError("failed to convert time to gm time, code:%d", errno);
return t;
}
int32_t mon = tm.tm_year * 12 + tm.tm_mon + (int32_t)numOfMonth;
tm.tm_year = mon / 12;
tm.tm_mon = mon % 12;
@ -692,7 +652,12 @@ int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision) {
if (tm.tm_mday > daysOfMonth[tm.tm_mon]) {
tm.tm_mday = daysOfMonth[tm.tm_mon];
}
return (int64_t)(taosMktime(&tm) * TSDB_TICK_PER_SECOND(precision) + fraction);
tt = taosTimeGm(&tm);
if (tt == -1){
uError("failed to convert gm time to time, code:%d", errno);
return t;
}
return (int64_t)(tt * TSDB_TICK_PER_SECOND(precision) + fraction);
}
/**
@ -731,7 +696,7 @@ int32_t taosTimeCountIntervalForFill(int64_t skey, int64_t ekey, int64_t interva
ekey = skey;
skey = tmp;
}
int32_t ret;
int32_t ret = 0;
if (unit != 'n' && unit != 'y') {
ret = (int32_t)((ekey - skey) / interval);
@ -742,11 +707,17 @@ int32_t taosTimeCountIntervalForFill(int64_t skey, int64_t ekey, int64_t interva
struct tm tm;
time_t t = (time_t)skey;
struct tm* ptm = taosLocalTime(&t, &tm, NULL, 0);
if (taosLocalTime(&t, &tm, NULL, 0, NULL) == NULL) {
uError("%s failed to convert time to local time, code:%d", __FUNCTION__, errno);
return ret;
}
int32_t smon = tm.tm_year * 12 + tm.tm_mon;
t = (time_t)ekey;
ptm = taosLocalTime(&t, &tm, NULL, 0);
if (taosLocalTime(&t, &tm, NULL, 0, NULL) == NULL) {
uError("%s failed to convert time to local time, code:%d", __FUNCTION__, errno);
return ret;
}
int32_t emon = tm.tm_year * 12 + tm.tm_mon;
if (unit == 'y') {
@ -770,7 +741,10 @@ int64_t taosTimeTruncate(int64_t ts, const SInterval* pInterval) {
start /= (int64_t)(TSDB_TICK_PER_SECOND(precision));
struct tm tm;
time_t tt = (time_t)start;
struct tm* ptm = taosLocalTime(&tt, &tm, NULL, 0);
if (taosLocalTime(&tt, &tm, NULL, 0, NULL) == NULL){
uError("%s failed to convert time to local time, code:%d", __FUNCTION__, errno);
return ts;
}
tm.tm_sec = 0;
tm.tm_min = 0;
tm.tm_hour = 0;
@ -786,7 +760,12 @@ int64_t taosTimeTruncate(int64_t ts, const SInterval* pInterval) {
tm.tm_mon = mon % 12;
}
start = (int64_t)(taosMktime(&tm) * TSDB_TICK_PER_SECOND(precision));
tt = taosMktime(&tm, NULL);
if (tt == -1){
uError("%s failed to convert local time to time, code:%d", __FUNCTION__, errno);
return ts;
}
start = (int64_t)(tt * TSDB_TICK_PER_SECOND(precision));
} else {
if (IS_CALENDAR_TIME_DURATION(pInterval->intervalUnit)) {
int64_t news = (ts / pInterval->sliding) * pInterval->sliding;
@ -931,7 +910,7 @@ int32_t taosFormatUtcTime(char* buf, int32_t bufLen, int64_t t, int32_t precisio
TAOS_RETURN(TSDB_CODE_INVALID_PARA);
}
if (NULL == taosLocalTime(&quot, &ptm, buf, bufLen)) {
if (NULL == taosLocalTime(&quot, &ptm, buf, bufLen, NULL)) {
TAOS_RETURN(TAOS_SYSTEM_ERROR(errno));
}
int32_t length = (int32_t)strftime(ts, 40, "%Y-%m-%dT%H:%M:%S", &ptm);
@ -942,17 +921,17 @@ int32_t taosFormatUtcTime(char* buf, int32_t bufLen, int64_t t, int32_t precisio
TAOS_RETURN(TSDB_CODE_SUCCESS);
}
int32_t taosTs2Tm(int64_t ts, int32_t precision, struct STm* tm) {
int32_t taosTs2Tm(int64_t ts, int32_t precision, struct STm* tm, timezone_t tz) {
tm->fsec = ts % TICK_PER_SECOND[precision] * (TICK_PER_SECOND[TSDB_TIME_PRECISION_NANO] / TICK_PER_SECOND[precision]);
time_t t = ts / TICK_PER_SECOND[precision];
if (NULL == taosLocalTime(&t, &tm->tm, NULL, 0)) { //tztodo
if (NULL == taosLocalTime(&t, &tm->tm, NULL, 0, tz)) {
TAOS_RETURN(TAOS_SYSTEM_ERROR(errno));
}
return TSDB_CODE_SUCCESS;
}
int32_t taosTm2Ts(struct STm* tm, int64_t* ts, int32_t precision) {
*ts = taosMktime(&tm->tm); //tztodo
int32_t taosTm2Ts(struct STm* tm, int64_t* ts, int32_t precision, timezone_t tz) {
*ts = taosMktime(&tm->tm, tz);
*ts *= TICK_PER_SECOND[precision];
*ts += tm->fsec / (TICK_PER_SECOND[TSDB_TIME_PRECISION_NANO] / TICK_PER_SECOND[precision]);
return TSDB_CODE_SUCCESS;
@ -1420,7 +1399,8 @@ static int32_t tm2char(const SArray* formats, const struct STm* tm, char* s, int
s += 9;
break;
case TSFKW_TZH:
(void)sprintf(s, "%s%02d", tsTimezone < 0 ? "-" : "+", tsTimezone);
(void)sprintf(s, "%c%02d", (tm->tm.tm_gmtoff >= 0) ? '+' : '-',
abs((int) tm->tm.tm_gmtoff) / 3600);
s += strlen(s);
break;
case TSFKW_YYYY:
@ -1552,13 +1532,13 @@ static bool needMoreDigits(SArray* formats, int32_t curIdx) {
/// @retval -2 if datetime err, like 2023-13-32 25:61:69
/// @retval -3 if not supported
static int32_t char2ts(const char* s, SArray* formats, int64_t* ts, int32_t precision, const char** sErrPos,
int32_t* fErrIdx) {
int32_t* fErrIdx, timezone_t tz) {
int32_t size = taosArrayGetSize(formats);
int32_t pm = 0; // default am
int32_t hour12 = 0; // default HH24
int32_t year = 0, mon = 0, yd = 0, md = 1, wd = 0;
int32_t hour = 0, min = 0, sec = 0, us = 0, ms = 0, ns = 0;
int32_t tzSign = 1, tz = tsTimezone;
int32_t tzHour = 0;
int32_t err = 0;
bool withYD = false, withMD = false;
@ -1685,8 +1665,7 @@ static int32_t char2ts(const char* s, SArray* formats, int64_t* ts, int32_t prec
}
} break;
case TSFKW_TZH: {
tzSign = *s == '-' ? -1 : 1;
const char* newPos = tsFormatStr2Int32(&tz, s, -1, needMoreDigits(formats, i));
const char* newPos = tsFormatStr2Int32(&tzHour, s, -1, needMoreDigits(formats, i));
if (NULL == newPos)
err = -1;
else {
@ -1839,14 +1818,16 @@ static int32_t char2ts(const char* s, SArray* formats, int64_t* ts, int32_t prec
tm.tm.tm_min = min;
tm.tm.tm_sec = sec;
if (!checkTm(&tm.tm)) return -2;
if (tz < -12 || tz > 12) return -2;
if (tzHour < -13 || tzHour > 13) return -2;
tm.fsec = ms * 1000000 + us * 1000 + ns;
int32_t ret = taosTm2Ts(&tm, ts, precision);
*ts += 60 * 60 * (tsTimezone - tz) * TICK_PER_SECOND[precision];
int32_t ret = taosTm2Ts(&tm, ts, precision, tz);
if (tzHour != 0) {
*ts += (tm.tm.tm_gmtoff - tzHour * 3600) * TICK_PER_SECOND[precision];
}
return ret;
}
int32_t taosTs2Char(const char* format, SArray** formats, int64_t ts, int32_t precision, char* out, int32_t outLen) {
int32_t taosTs2Char(const char* format, SArray** formats, int64_t ts, int32_t precision, char* out, int32_t outLen, timezone_t tz) {
if (!*formats) {
*formats = taosArrayInit(8, sizeof(TSFormatNode));
if (!*formats) {
@ -1855,12 +1836,12 @@ int32_t taosTs2Char(const char* format, SArray** formats, int64_t ts, int32_t pr
TAOS_CHECK_RETURN(parseTsFormat(format, *formats));
}
struct STm tm;
TAOS_CHECK_RETURN(taosTs2Tm(ts, precision, &tm));
TAOS_CHECK_RETURN(taosTs2Tm(ts, precision, &tm, tz));
return tm2char(*formats, &tm, out, outLen);
}
int32_t taosChar2Ts(const char* format, SArray** formats, const char* tsStr, int64_t* ts, int32_t precision,
char* errMsg, int32_t errMsgLen) {
char* errMsg, int32_t errMsgLen, timezone_t tz) {
const char* sErrPos;
int32_t fErrIdx;
if (!*formats) {
@ -1870,7 +1851,7 @@ int32_t taosChar2Ts(const char* format, SArray** formats, const char* tsStr, int
}
TAOS_CHECK_RETURN(parseTsFormat(format, *formats));
}
int32_t code = char2ts(tsStr, *formats, ts, precision, &sErrPos, &fErrIdx);
int32_t code = char2ts(tsStr, *formats, ts, precision, &sErrPos, &fErrIdx, tz);
if (code == -1) {
TSFormatNode* fNode = (taosArrayGet(*formats, fErrIdx));
snprintf(errMsg, errMsgLen, "mismatch format for: %s and %s", sErrPos,
@ -1895,7 +1876,7 @@ int32_t TEST_ts2char(const char* format, int64_t ts, int32_t precision, char* ou
}
TAOS_CHECK_RETURN(parseTsFormat(format, formats));
struct STm tm;
TAOS_CHECK_GOTO(taosTs2Tm(ts, precision, &tm), NULL, _exit);
TAOS_CHECK_GOTO(taosTs2Tm(ts, precision, &tm, NULL), NULL, _exit);
TAOS_CHECK_GOTO(tm2char(formats, &tm, out, outLen), NULL, _exit);
_exit:
@ -1908,7 +1889,7 @@ int32_t TEST_char2ts(const char* format, int64_t* ts, int32_t precision, const c
int32_t fErrIdx;
SArray* formats = taosArrayInit(4, sizeof(TSFormatNode));
TAOS_CHECK_RETURN(parseTsFormat(format, formats));
int32_t code = char2ts(tsStr, formats, ts, precision, &sErrPos, &fErrIdx);
int32_t code = char2ts(tsStr, formats, ts, precision, &sErrPos, &fErrIdx, NULL);
if (code == -1) {
(void)printf("failed position: %s\n", sErrPos);
(void)printf("failed format: %s\n", ((TSFormatNode*)taosArrayGet(formats, fErrIdx))->key->name);
@ -2024,3 +2005,26 @@ bool checkRecursiveTsmaInterval(int64_t baseInterval, int8_t baseUnit, int64_t i
}
return true;
}
int64_t taosGetTimestampToday(int32_t precision, timezone_t tz) {
int64_t factor = (precision == TSDB_TIME_PRECISION_SECONDS) ? 1
: (precision == TSDB_TIME_PRECISION_MILLI) ? 1000
: (precision == TSDB_TIME_PRECISION_MICRO) ? 1000000
: 1000000000;
time_t t = taosTime(NULL);
struct tm tm;
if (taosLocalTime(&t, &tm, NULL, 0, tz) == NULL){
uError("%s failed to get local time, code:%d", __FUNCTION__, errno);
return t;
}
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
time_t tmp = taosMktime(&tm, tz);
if (tmp == (time_t)-1) {
uError("%s failed to get timestamp of today, code:%d", __FUNCTION__, errno);
return t;
}
return (int64_t)tmp * factor;
}

View File

@ -429,9 +429,9 @@ void test_timestamp_tm_conversion(int64_t ts, int32_t precision, int32_t y, int3
struct STm tm;
taosFormatUtcTime(buf, 128, ts, precision);
printf("formated ts of %ld, precision: %d is: %s\n", ts, precision, buf);
taosTs2Tm(ts, precision, &tm);
taosTs2Tm(ts, precision, &tm, NULL);
check_tm(&tm, y, mon, d, h, m, s, fsec);
taosTm2Ts(&tm, &ts_tmp, precision);
taosTm2Ts(&tm, &ts_tmp, precision, NULL);
ASSERT_EQ(ts, ts_tmp);
}
@ -442,15 +442,15 @@ TEST(timeTest, timestamp2tm) {
int64_t ts, tmp_ts = 0;
struct STm tm;
ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_ns, &ts, strlen(ts_str_ns), TSDB_TIME_PRECISION_NANO));
ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_ns, &ts, strlen(ts_str_ns), TSDB_TIME_PRECISION_NANO, NULL));
test_timestamp_tm_conversion(ts, TSDB_TIME_PRECISION_NANO, 2023 - 1900, 9 /* mon start from 0*/, 12, 11, 29, 0,
775726171L);
ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_us, &ts, strlen(ts_str_us), TSDB_TIME_PRECISION_MICRO));
ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_us, &ts, strlen(ts_str_us), TSDB_TIME_PRECISION_MICRO, NULL));
test_timestamp_tm_conversion(ts, TSDB_TIME_PRECISION_MICRO, 2023 - 1900, 9 /* mon start from 0*/, 12, 11, 29, 0,
775726000L);
ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_ms, &ts, strlen(ts_str_ms), TSDB_TIME_PRECISION_MILLI));
ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_ms, &ts, strlen(ts_str_ms), TSDB_TIME_PRECISION_MILLI, NULL));
test_timestamp_tm_conversion(ts, TSDB_TIME_PRECISION_MILLI, 2023 - 1900, 9 /* mon start from 0*/, 12, 11, 29, 0,
775000000L);

View File

@ -198,7 +198,7 @@ void dmSendStatusReq(SDnodeMgmt *pMgmt) {
req.clusterCfg.monitorParas.tsSlowLogThresholdTest = tsSlowLogThresholdTest;
tstrncpy(req.clusterCfg.monitorParas.tsSlowLogExceptDb, tsSlowLogExceptDb, TSDB_DB_NAME_LEN);
char timestr[32] = "1970-01-01 00:00:00.00";
if (taosParseTime(timestr, &req.clusterCfg.checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI) != 0) {
if (taosParseTime(timestr, &req.clusterCfg.checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI, NULL) != 0) {
dError("failed to parse time since %s", tstrerror(code));
}
memcpy(req.clusterCfg.timezone, tsTimezoneStr, TD_TIMEZONE_LEN);

View File

@ -713,7 +713,7 @@ SMnode *mndOpen(const char *path, const SMnodeOpt *pOption) {
}
char timestr[24] = "1970-01-01 00:00:00.00";
code = taosParseTime(timestr, &pMnode->checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI);
code = taosParseTime(timestr, &pMnode->checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI, NULL);
if (code < 0) {
mError("failed to parse time since %s", tstrerror(code));
(void)taosThreadRwlockDestroy(&pMnode->lock);

View File

@ -186,11 +186,11 @@ static int32_t countTrailingSpaces(const SValueNode* pVal, bool isLtrim) {
return numOfSpaces;
}
static int32_t addTimezoneParam(SNodeList* pList) {
static int32_t addTimezoneParam(SNodeList* pList, timezone_t tz) {
char buf[TD_TIME_STR_LEN] = {0};
time_t t = taosTime(NULL);
struct tm tmInfo;
if (taosLocalTime(&t, &tmInfo, buf, sizeof(buf)) != NULL) {
if (taosLocalTime(&t, &tmInfo, buf, sizeof(buf), tz) != NULL) {
(void)strftime(buf, sizeof(buf), "%z", &tmInfo);
}
int32_t len = (int32_t)strlen(buf);
@ -1446,7 +1446,7 @@ static int32_t translateToIso8601(SFunctionNode* pFunc, char* pErrBuf, int32_t l
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "Invalid timzone format");
}
} else { // add default client timezone
int32_t code = addTimezoneParam(pFunc->pParameterList);
int32_t code = addTimezoneParam(pFunc->pParameterList, pFunc->tz);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
@ -1501,7 +1501,7 @@ static int32_t translateTimeTruncate(SFunctionNode* pFunc, char* pErrBuf, int32_
}
// add client timezone as param
code = addTimezoneParam(pFunc->pParameterList);
code = addTimezoneParam(pFunc->pParameterList, pFunc->tz);
if (code != TSDB_CODE_SUCCESS) {
return code;
}

View File

@ -135,7 +135,7 @@ int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen);
int32_t getVnodeSysTableTargetName(int32_t acctId, SNode* pWhere, SName* pName);
int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf, int8_t type);
int32_t parseTagValue(SMsgBuf* pMsgBuf, const char** pSql, uint8_t precision, SSchema* pTagSchema, SToken* pToken,
SArray* pTagName, SArray* pTagVals, STag** pTag);
SArray* pTagName, SArray* pTagVals, STag** pTag, timezone_t tz);
int32_t parseTbnameToken(SMsgBuf* pMsgBuf, char* tname, SToken* pToken, bool* pFoundCtbName);
int32_t buildCatalogReq(const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq);

View File

@ -420,6 +420,7 @@ SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken*
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
}
val->translate = false;
val->tz = pCxt->pQueryCxt->timezone;
return (SNode*)val;
_err:
return NULL;
@ -1041,6 +1042,7 @@ SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNod
CHECK_MAKE_NODE(func);
COPY_STRING_FORM_ID_TOKEN(func->functionName, pFuncName);
func->pParameterList = pParameterList;
func->tz = pCxt->pQueryCxt->timezone;
return (SNode*)func;
_err:
nodesDestroyList(pParameterList);
@ -1497,6 +1499,7 @@ SNode* createCaseWhenNode(SAstCreateContext* pCxt, SNode* pCase, SNodeList* pWhe
pCaseWhen->pCase = pCase;
pCaseWhen->pWhenThenList = pWhenThenList;
pCaseWhen->pElse = pElse;
pCaseWhen->tz = pCxt->pQueryCxt->timezone;
return (SNode*)pCaseWhen;
_err:
nodesDestroyNode(pCase);

View File

@ -247,13 +247,13 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, E
}
static int parseTimestampOrInterval(const char** end, SToken* pToken, int16_t timePrec, int64_t* ts, int64_t* interval,
SMsgBuf* pMsgBuf, bool* isTs) {
SMsgBuf* pMsgBuf, bool* isTs, timezone_t tz) {
if (pToken->type == TK_NOW) {
*isTs = true;
*ts = taosGetTimestamp(timePrec);
} else if (pToken->type == TK_TODAY) {
*isTs = true;
*ts = taosGetTimestampToday(timePrec);
*ts = taosGetTimestampToday(timePrec, tz);
} else if (pToken->type == TK_NK_INTEGER) {
*isTs = true;
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, ts)) {
@ -267,7 +267,7 @@ static int parseTimestampOrInterval(const char** end, SToken* pToken, int16_t ti
}
} else { // parse the RFC-3339/ISO-8601 timestamp format string
*isTs = true;
if (taosParseTime(pToken->z, ts, pToken->n, timePrec) != TSDB_CODE_SUCCESS) {
if (taosParseTime(pToken->z, ts, pToken->n, timePrec, tz) != TSDB_CODE_SUCCESS) {
if ((pToken->n == 0) ||
(pToken->type != TK_NK_STRING && pToken->type != TK_NK_HEX && pToken->type != TK_NK_BIN)) {
return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
@ -277,7 +277,7 @@ static int parseTimestampOrInterval(const char** end, SToken* pToken, int16_t ti
*ts = taosGetTimestamp(timePrec);
} else if (IS_TODAY_STR(pToken->z, pToken->n)) {
*isTs = true;
*ts = taosGetTimestampToday(timePrec);
*ts = taosGetTimestampToday(timePrec, tz);
} else if (TSDB_CODE_SUCCESS == toIntegerPure(pToken->z, pToken->n, 10, ts)) {
*isTs = true;
} else {
@ -289,7 +289,7 @@ static int parseTimestampOrInterval(const char** end, SToken* pToken, int16_t ti
return TSDB_CODE_SUCCESS;
}
static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t* time, SMsgBuf* pMsgBuf) {
static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t* time, SMsgBuf* pMsgBuf, timezone_t tz) {
int32_t index = 0, i = 0;
int64_t interval = 0, tempInterval = 0;
int64_t ts = 0, tempTs = 0;
@ -297,7 +297,7 @@ static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t
const char* pTokenEnd = *end;
if (TSDB_CODE_SUCCESS !=
parseTimestampOrInterval(&pTokenEnd, pToken, timePrec, &ts, &interval, pMsgBuf, &firstIsTS)) {
parseTimestampOrInterval(&pTokenEnd, pToken, timePrec, &ts, &interval, pMsgBuf, &firstIsTS, tz)) {
return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
}
@ -371,7 +371,7 @@ static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t
}
if (TSDB_CODE_SUCCESS !=
parseTimestampOrInterval(&pTokenEnd, &valueToken, timePrec, &tempTs, &tempInterval, pMsgBuf, &secondIsTs)) {
parseTimestampOrInterval(&pTokenEnd, &valueToken, timePrec, &tempTs, &tempInterval, pMsgBuf, &secondIsTs, tz)) {
return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
}
@ -477,7 +477,7 @@ static int32_t parseVarbinary(SToken* pToken, uint8_t** pData, uint32_t* nData,
}
static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val,
SMsgBuf* pMsgBuf) {
SMsgBuf* pMsgBuf, timezone_t tz) {
int64_t iv;
uint64_t uv;
char* endptr = NULL;
@ -700,7 +700,7 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
break;
}
case TSDB_DATA_TYPE_TIMESTAMP: {
if (parseTime(end, pToken, timePrec, &iv, pMsgBuf) != TSDB_CODE_SUCCESS) {
if (parseTime(end, pToken, timePrec, &iv, pMsgBuf, tz) != TSDB_CODE_SUCCESS) {
return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z);
}
@ -732,7 +732,7 @@ static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStm
}
int32_t parseTagValue(SMsgBuf* pMsgBuf, const char** pSql, uint8_t precision, SSchema* pTagSchema, SToken* pToken,
SArray* pTagName, SArray* pTagVals, STag** pTag) {
SArray* pTagName, SArray* pTagVals, STag** pTag, timezone_t tz) {
bool isNull = isNullValue(pTagSchema->type, pToken);
if (!isNull && pTagName) {
if (NULL == taosArrayPush(pTagName, pTagSchema->name)) {
@ -755,7 +755,7 @@ int32_t parseTagValue(SMsgBuf* pMsgBuf, const char** pSql, uint8_t precision, SS
if (isNull) return 0;
STagVal val = {0};
int32_t code = parseTagToken(pSql, pToken, pTagSchema, precision, &val, pMsgBuf);
int32_t code = parseTagToken(pSql, pToken, pTagSchema, precision, &val, pMsgBuf, tz);
if (TSDB_CODE_SUCCESS == code) {
if (NULL == taosArrayPush(pTagVals, &val)){
code = terrno;
@ -975,7 +975,7 @@ static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt
code = buildSyntaxErrMsg(&pCxt->msg, "not expected tags values ", token.z);
}
if (TSDB_CODE_SUCCESS == code) {
code = parseTagValue(&pCxt->msg, &pStmt->pSql, precision, pTagSchema, &token, pTagName, pTagVals, &pTag);
code = parseTagValue(&pCxt->msg, &pStmt->pSql, precision, pTagSchema, &token, pTagName, pTagVals, &pTag, pCxt->pComCxt->timezone);
}
}
@ -1672,7 +1672,7 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
break;
}
case TSDB_DATA_TYPE_TIMESTAMP: {
if (parseTime(pSql, pToken, timePrec, &pVal->value.val, &pCxt->msg) != TSDB_CODE_SUCCESS) {
if (parseTime(pSql, pToken, timePrec, &pVal->value.val, &pCxt->msg, pCxt->pComCxt->timezone) != TSDB_CODE_SUCCESS) {
return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z);
}
break;
@ -1785,7 +1785,7 @@ static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModif
if (code == TSDB_CODE_SUCCESS) {
code = parseTagValue(&pCxt->msg, NULL, precision, pTagSchema, pTagToken, pStbRowsCxt->aTagNames,
pStbRowsCxt->aTagVals, &pStbRowsCxt->pTag);
pStbRowsCxt->aTagVals, &pStbRowsCxt->pTag, pCxt->pComCxt->timezone);
}
}
if (code == TSDB_CODE_SUCCESS && !pStbRowsCxt->isJsonTag) {
@ -1844,7 +1844,7 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt*
}
if (code == TSDB_CODE_SUCCESS) {
code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken, pTagNames, pTagVals,
&pStbRowsCxt->pTag);
&pStbRowsCxt->pTag, pCxt->pComCxt->timezone);
}
}
} else if (pCols->pColIndex[i] == tbnameIdx) {

View File

@ -1949,7 +1949,7 @@ static int32_t parseTimeFromValueNode(STranslateContext* pCxt, SValueNode* pVal)
return TSDB_CODE_SUCCESS;
} else if (IS_VAR_DATA_TYPE(pVal->node.resType.type) || TSDB_DATA_TYPE_TIMESTAMP == pVal->node.resType.type) {
if (TSDB_CODE_SUCCESS == taosParseTime(pVal->literal, &pVal->datum.i, pVal->node.resType.bytes,
pVal->node.resType.precision)) {
pVal->node.resType.precision, pVal->tz)) {
return TSDB_CODE_SUCCESS;
}
char* pEnd = NULL;
@ -14008,7 +14008,7 @@ static int32_t buildKVRowForBindTags(STranslateContext* pCxt, SCreateSubTableCla
if (pSchema->type == TSDB_DATA_TYPE_JSON) {
isJson = true;
}
code = parseTagValue(&pCxt->msgBuf, &tagStr, precision, pSchema, &token, tagName, pTagArray, ppTag);
code = parseTagValue(&pCxt->msgBuf, &tagStr, precision, pSchema, &token, tagName, pTagArray, ppTag, pCxt->pParseCxt->timezone);
}
if (TSDB_CODE_SUCCESS == code) {
@ -14069,7 +14069,7 @@ static int32_t buildKVRowForAllTags(STranslateContext* pCxt, SCreateSubTableClau
if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
isJson = true;
}
code = parseTagValue(&pCxt->msgBuf, &tagStr, precision, pTagSchema, &token, tagName, pTagArray, ppTag);
code = parseTagValue(&pCxt->msgBuf, &tagStr, precision, pTagSchema, &token, tagName, pTagArray, ppTag, pCxt->pParseCxt->timezone);
}
if (TSDB_CODE_SUCCESS == code) {
@ -14265,7 +14265,7 @@ static int32_t fillVgroupInfo(SParseContext* pParseCxt, const SName* pName, SVgr
return code;
}
static int32_t parseOneStbRow(SMsgBuf* pMsgBuf, SParseFileContext* pParFileCxt) {
static int32_t parseOneStbRow(SMsgBuf* pMsgBuf, SParseFileContext* pParFileCxt, timezone_t tz) {
int32_t code = TSDB_CODE_SUCCESS;
int sz = taosArrayGetSize(pParFileCxt->aTagIndexs);
int32_t numOfTags = getNumOfTags(pParFileCxt->pStbMeta);
@ -14297,7 +14297,7 @@ static int32_t parseOneStbRow(SMsgBuf* pMsgBuf, SParseFileContext* pParFileCxt)
if (TSDB_CODE_SUCCESS == code) {
SArray* aTagNames = pParFileCxt->tagNameFilled ? NULL : pParFileCxt->aTagNames;
code = parseTagValue(pMsgBuf, &pParFileCxt->pSql, precision, (SSchema*)pTagSchema, &token, aTagNames,
pParFileCxt->aTagVals, &pParFileCxt->pTag);
pParFileCxt->aTagVals, &pParFileCxt->pTag, tz);
}
} else {
// parse tbname
@ -14363,7 +14363,7 @@ static int32_t parseCsvFile(SMsgBuf* pMsgBuf, SParseContext* pParseCxt, SParseFi
(void)strtolower(pLine, pLine);
pParFileCxt->pSql = pLine;
code = parseOneStbRow(pMsgBuf, pParFileCxt);
code = parseOneStbRow(pMsgBuf, pParFileCxt, pParseCxt->timezone);
if (TSDB_CODE_SUCCESS == code) {
code = fillVgroupInfo(pParseCxt, &pParFileCxt->ctbName, &pParFileCxt->vg);
@ -15064,7 +15064,7 @@ static int32_t buildUpdateTagValReq(STranslateContext* pCxt, SAlterTableStmt* pS
if (TSDB_CODE_SUCCESS == code) {
code = parseTagValue(&pCxt->msgBuf, &tagStr, pTableMeta->tableInfo.precision, pSchema, &token, NULL,
pReq->pTagArray, &pTag);
pReq->pTagArray, &pTag, pCxt->pParseCxt->timezone);
if (pSchema->type == TSDB_DATA_TYPE_JSON && token.type == TK_NULL && code == TSDB_CODE_SUCCESS) {
pReq->tagFree = true;
}

View File

@ -4694,33 +4694,6 @@ EDealRes fltReviseRewriter(SNode **pNode, void *pContext) {
stat->scalarMode = true;
return DEAL_RES_CONTINUE;
}
/*
if (!FILTER_GET_FLAG(stat->info->options, FLT_OPTION_TIMESTAMP)) {
return DEAL_RES_CONTINUE;
}
if (TSDB_DATA_TYPE_BINARY != valueNode->node.resType.type && TSDB_DATA_TYPE_NCHAR !=
valueNode->node.resType.type &&
TSDB_DATA_TYPE_GEOMETRY != valueNode->node.resType.type) { return DEAL_RES_CONTINUE;
}
if (stat->precision < 0) {
int32_t code = fltAddValueNodeToConverList(stat, valueNode);
if (code) {
stat->code = code;
return DEAL_RES_ERROR;
}
return DEAL_RES_CONTINUE;
}
int32_t code = sclConvertToTsValueNode(stat->precision, valueNode);
if (code) {
stat->code = code;
return DEAL_RES_ERROR;
}
*/
return DEAL_RES_CONTINUE;
}
@ -4887,15 +4860,6 @@ int32_t fltReviseNodes(SFilterInfo *pInfo, SNode **pNode, SFltTreeStat *pStat) {
FLT_ERR_JRET(pStat->code);
/*
int32_t nodeNum = taosArrayGetSize(pStat->nodeList);
for (int32_t i = 0; i < nodeNum; ++i) {
SValueNode *valueNode = *(SValueNode **)taosArrayGet(pStat->nodeList, i);
FLT_ERR_JRET(sclConvertToTsValueNode(pStat->precision, valueNode));
}
*/
_return:
taosArrayDestroy(pStat->nodeList);

View File

@ -24,7 +24,7 @@ int32_t scalarGetOperatorParamNum(EOperatorType type) {
int32_t sclConvertToTsValueNode(int8_t precision, SValueNode *valueNode) {
char *timeStr = valueNode->datum.p;
int64_t value = 0;
int32_t code = convertStringToTimestamp(valueNode->node.resType.type, valueNode->datum.p, precision, &value);
int32_t code = convertStringToTimestamp(valueNode->node.resType.type, valueNode->datum.p, precision, &value, valueNode->tz); //todo tz
if (code != TSDB_CODE_SUCCESS) {
return code;
}
@ -81,6 +81,8 @@ int32_t sclConvertValueToSclParam(SValueNode *pValueNode, SScalarParam *out, int
goto _exit;
}
in.tz = pValueNode->tz;
out->tz = pValueNode->tz;
code = vectorConvertSingleColImpl(&in, out, overflow, -1, -1);
_exit:
@ -586,6 +588,7 @@ int32_t sclInitOperatorParams(SScalarParam **pParams, SOperatorNode *node, SScal
SCL_ERR_JRET(sclSetOperatorValueType(node, ctx));
SCL_ERR_JRET(sclInitParam(node->pLeft, &paramList[0], ctx, rowNum));
paramList[0].tz = node->tz;
if (paramNum > 1) {
TSWAP(ctx->type.selfType, ctx->type.peerType);
SCL_ERR_JRET(sclInitParam(node->pRight, &paramList[1], ctx, rowNum));
@ -756,6 +759,7 @@ int32_t sclExecFunction(SFunctionNode *node, SScalarCtx *ctx, SScalarParam *outp
int32_t paramNum = 0;
int32_t code = 0;
SCL_ERR_RET(sclInitParamList(&params, node->pParameterList, ctx, &paramNum, &rowNum));
params->tz = node->tz;
if (fmIsUserDefinedFunc(node->funcId)) {
code = callUdfScalarFunc(node->functionName, params, paramNum, output);
@ -942,7 +946,7 @@ int32_t sclExecCaseWhen(SCaseWhenNode *node, SScalarCtx *ctx, SScalarParam *outp
SCL_ERR_JRET(sclGetNodeRes(node->pCase, ctx, &pCase));
SCL_ERR_JRET(sclGetNodeRes(node->pElse, ctx, &pElse));
pCase->tz = node->tz;
SDataType compType = {0};
compType.type = TSDB_DATA_TYPE_BOOL;
compType.bytes = tDataTypes[compType.type].bytes;

View File

@ -2053,7 +2053,7 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp
if (inputType == TSDB_DATA_TYPE_BINARY || inputType == TSDB_DATA_TYPE_NCHAR) {
int64_t timePrec;
GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
int32_t ret = convertStringToTimestamp(inputType, input, timePrec, &timeVal);
int32_t ret = convertStringToTimestamp(inputType, input, timePrec, &timeVal, pInput->tz);
if (ret != TSDB_CODE_SUCCESS) {
*(int64_t *)output = 0;
} else {
@ -2240,17 +2240,14 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *
if (0 != offsetOfTimezone(tz, &offset)) {
goto _end;
}
quot -= offset + 3600 * ((int64_t)tsTimezone);
quot -= offset;
struct tm tmInfo;
int32_t len = 0;
if (taosLocalTime((const time_t *)&quot, &tmInfo, buf, sizeof(buf)) == NULL) {
len = (int32_t)strlen(buf);
if (taosGmTimeR((const time_t *)&quot, &tmInfo) == NULL) {
goto _end;
}
len = (int32_t)strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tmInfo);
int32_t len = (int32_t)strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tmInfo);
len += tsnprintf(buf + len, fractionLen, format, mod);
@ -2286,7 +2283,7 @@ int32_t toUnixtimestampFunction(SScalarParam *pInput, int32_t inputNum, SScalarP
char *input = colDataGetData(pInput[0].columnData, i);
int64_t timeVal = 0;
int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal);
int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal, pInput->tz);
if (ret != TSDB_CODE_SUCCESS) {
colDataSetNULL(pOutput->columnData, i);
} else {
@ -2381,7 +2378,7 @@ int32_t toTimestampFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam
}
int32_t precision = pOutput->columnData->info.precision;
char errMsg[128] = {0};
code = taosChar2Ts(format, &formats, tsStr, &ts, precision, errMsg, 128);
code = taosChar2Ts(format, &formats, tsStr, &ts, precision, errMsg, 128, pInput->tz);
if (code) {
qError("func to_timestamp failed %s", errMsg);
SCL_ERR_JRET(code);
@ -2424,7 +2421,7 @@ int32_t toCharFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOu
}
}
int32_t precision = pInput[0].columnData->info.precision;
SCL_ERR_JRET(taosTs2Char(format, &formats, *(int64_t *)ts, precision, varDataVal(out), TS_FORMAT_MAX_LEN));
SCL_ERR_JRET(taosTs2Char(format, &formats, *(int64_t *)ts, precision, varDataVal(out), TS_FORMAT_MAX_LEN, pInput->tz));
varDataSetLen(out, strlen(varDataVal(out)));
SCL_ERR_JRET(colDataSetVal(pOutput->columnData, i, out, false));
}
@ -2437,11 +2434,11 @@ _return:
}
/** Time functions **/
int64_t offsetFromTz(char *timezone, int64_t factor) {
char *minStr = &timezone[3];
int64_t offsetFromTz(char *timezoneStr, int64_t factor) {
char *minStr = &timezoneStr[3];
int64_t minutes = taosStr2Int64(minStr, NULL, 10);
(void)memset(minStr, 0, strlen(minStr));
int64_t hours = taosStr2Int64(timezone, NULL, 10);
int64_t hours = taosStr2Int64(timezoneStr, NULL, 10);
int64_t seconds = hours * 3600 + minutes * 60;
return seconds * factor;
@ -2453,7 +2450,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara
int64_t timeUnit, timePrec, timeVal = 0;
bool ignoreTz = true;
char timezone[20] = {0};
char timezoneStr[20] = {0};
GET_TYPED_DATA(timeUnit, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
@ -2465,7 +2462,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara
}
GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[timePrecIdx]), pInput[timePrecIdx].columnData->pData);
(void)memcpy(timezone, varDataVal(pInput[timeZoneIdx].columnData->pData), varDataLen(pInput[timeZoneIdx].columnData->pData));
(void)memcpy(timezoneStr, varDataVal(pInput[timeZoneIdx].columnData->pData), varDataLen(pInput[timeZoneIdx].columnData->pData));
for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
if (colDataIsNull_s(pInput[0].columnData, i)) {
@ -2476,7 +2473,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara
char *input = colDataGetData(pInput[0].columnData, i);
if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal);
int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal, pInput->tz);
if (ret != TSDB_CODE_SUCCESS) {
colDataSetNULL(pOutput->columnData, i);
continue;
@ -2493,7 +2490,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara
// truncate the timestamp to time_unit precision
int64_t seconds = timeUnit / TSDB_TICK_PER_SECOND(timePrec);
if (ignoreTz && (seconds == 604800 || seconds == 86400)) {
timeVal = timeVal - (timeVal + offsetFromTz(timezone, TSDB_TICK_PER_SECOND(timePrec))) % timeUnit;
timeVal = timeVal - (timeVal + offsetFromTz(timezoneStr, TSDB_TICK_PER_SECOND(timePrec))) % timeUnit;
} else {
timeVal = timeVal / timeUnit * timeUnit;
}
@ -2536,7 +2533,7 @@ int32_t timeDiffFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p
int32_t type = GET_PARAM_TYPE(&pInput[k]);
if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
int32_t ret = convertStringToTimestamp(type, input[k], TSDB_TIME_PRECISION_NANO, &timeVal[k]);
int32_t ret = convertStringToTimestamp(type, input[k], TSDB_TIME_PRECISION_NANO, &timeVal[k], pInput->tz);
if (ret != TSDB_CODE_SUCCESS) {
hasNull = true;
break;
@ -2655,7 +2652,7 @@ int32_t todayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOut
int64_t timePrec;
GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[0]), pInput[0].columnData->pData);
int64_t ts = taosGetTimestampToday(timePrec);
int64_t ts = taosGetTimestampToday(timePrec, pInput->tz);
for (int32_t i = 0; i < pInput->numOfRows; ++i) {
colDataSetInt64(pOutput->columnData, i, &ts);
}
@ -2665,8 +2662,16 @@ int32_t todayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOut
int32_t timezoneFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
char output[TD_TIMEZONE_LEN + VARSTR_HEADER_SIZE] = {0};
(void)memcpy(varDataVal(output), tsTimezoneStr, TD_TIMEZONE_LEN);
varDataSetLen(output, strlen(tsTimezoneStr));
// pInput->tz todo tz
char* tmp = NULL;
if (pInput->tz == NULL) {
(void)memcpy(varDataVal(output), tsTimezoneStr, TD_TIMEZONE_LEN);
} else{
time_t tx1 = taosGetTimestampSec();
SCL_ERR_RET(taosFormatTimezoneStr(tx1, "UTC-test", pInput->tz, varDataVal(output)));
}
varDataSetLen(output, strlen(varDataVal(output)));
for (int32_t i = 0; i < pInput->numOfRows; ++i) {
SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, output, false));
}
@ -2690,7 +2695,7 @@ int32_t weekdayFunctionImpl(SScalarParam *pInput, int32_t inputNum, SScalarParam
char *input = colDataGetData(pInput[0].columnData, i);
if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal);
int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal, pInput->tz);
if (ret != TSDB_CODE_SUCCESS) {
colDataSetNULL(pOutput->columnData, i);
continue;
@ -2701,7 +2706,7 @@ int32_t weekdayFunctionImpl(SScalarParam *pInput, int32_t inputNum, SScalarParam
GET_TYPED_DATA(timeVal, int64_t, type, input);
}
struct STm tm;
TAOS_CHECK_RETURN(taosTs2Tm(timeVal, timePrec, &tm));
TAOS_CHECK_RETURN(taosTs2Tm(timeVal, timePrec, &tm, pInput->tz));
int64_t ret = startFromZero ? (tm.tm.tm_wday + 6) % 7 : tm.tm.tm_wday + 1;
colDataSetInt64(pOutput->columnData, i, &ret);
}
@ -2800,7 +2805,7 @@ int32_t weekFunctionImpl(SScalarParam *pInput, int32_t inputNum, SScalarParam *p
char *input = colDataGetData(pInput[0].columnData, i);
if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
int32_t ret = convertStringToTimestamp(type, input, prec, &timeVal);
int32_t ret = convertStringToTimestamp(type, input, prec, &timeVal, pInput->tz);
if (ret != TSDB_CODE_SUCCESS) {
colDataSetNULL(pOutput->columnData, i);
continue;
@ -2811,7 +2816,7 @@ int32_t weekFunctionImpl(SScalarParam *pInput, int32_t inputNum, SScalarParam *p
GET_TYPED_DATA(timeVal, int64_t, type, input);
}
struct STm tm;
SCL_ERR_RET(taosTs2Tm(timeVal, prec, &tm));
SCL_ERR_RET(taosTs2Tm(timeVal, prec, &tm, pInput->tz));
int64_t ret = calculateWeekNum(tm.tm, weekMode(mode));
colDataSetInt64(pOutput->columnData, i, &ret);
}

View File

@ -242,7 +242,7 @@ int32_t getVectorBigintValueFn(int32_t srcType, _getBigintValue_fn_t *p) {
static FORCE_INLINE int32_t varToTimestamp(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) {
int64_t value = 0;
int32_t code = TSDB_CODE_SUCCESS;
if (taosParseTime(buf, &value, strlen(buf), pOut->columnData->info.precision) != TSDB_CODE_SUCCESS) {
if (taosParseTime(buf, &value, strlen(buf), pOut->columnData->info.precision, pOut->tz) != TSDB_CODE_SUCCESS) {
value = 0;
code = TSDB_CODE_SCALAR_CONVERT_ERROR;
}
@ -2042,6 +2042,9 @@ int32_t vectorCompareImpl(SScalarParam *pLeft, SScalarParam *pRight, SScalarPara
SScalarParam *param1 = NULL;
SScalarParam *param2 = NULL;
int32_t code = TSDB_CODE_SUCCESS;
pRight->tz = pLeft->tz;
pLeftOut.tz = pLeft->tz;
pRightOut.tz = pRight->tz;
if (noConvertBeforeCompare(GET_PARAM_TYPE(pLeft), GET_PARAM_TYPE(pRight), optr)) {
param1 = pLeft;
param2 = pRight;
@ -2125,6 +2128,7 @@ int32_t vectorIsNull(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pO
}
int32_t vectorNotNull(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) {
pRight->tz = pLeft->tz;
for (int32_t i = 0; i < pLeft->numOfRows; ++i) {
int8_t v = IS_HELPER_NULL(pLeft->columnData, i) ? 0 : 1;
if (v) {
@ -2138,6 +2142,7 @@ int32_t vectorNotNull(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *p
}
int32_t vectorIsTrue(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) {
pRight->tz = pLeft->tz;
SCL_ERR_RET(vectorConvertSingleColImpl(pLeft, pOut, NULL, -1, -1));
for (int32_t i = 0; i < pOut->numOfRows; ++i) {
if (colDataIsNull_s(pOut->columnData, i)) {

View File

@ -413,7 +413,7 @@ int64_t user_mktime64(const uint32_t year, const uint32_t mon, const uint32_t da
return _res + time_zone;
}
time_t taosMktime(struct tm *timep) {
time_t taosMktime(struct tm *timep, timezone_t tz) {
#ifdef WINDOWS
#if 0
struct tm tm1 = {0};
@ -466,7 +466,7 @@ time_t taosMktime(struct tm *timep) {
timep->tm_sec, tz);
#endif
#else
time_t r = mktime(timep);
time_t r = tz != NULL ? mktime_z(tz, timep) : mktime(timep);
if (r == (time_t)-1) {
terrno = TAOS_SYSTEM_ERROR(errno);
}
@ -474,7 +474,74 @@ time_t taosMktime(struct tm *timep) {
#endif
}
struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf, int32_t bufSize) {
struct tm *taosGmTimeR(const time_t *timep, struct tm *result){
if (timep == NULL || result == NULL) {
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;
}
}
#else
return gmtime_r(timep, result);
#endif
}
time_t taosTimeGm(struct tm *tmp){
if (tmp == NULL) {
return -1;
}
return timegm(tmp);
}
struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf, int32_t bufSize, timezone_t tz) {
struct tm *res = NULL;
if (timep == NULL || result == NULL) {
return NULL;
@ -531,7 +598,7 @@ struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf, int3
}
}
#else
res = localtime_r(timep, result);
res = tz != NULL ? localtime_rz(tz, timep, result): localtime_r(timep, result);
if (res == NULL && buf != NULL) {
(void)snprintf(buf, bufSize, "NaN");
}
@ -539,233 +606,6 @@ struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf, int3
return result;
}
time_t taosMktimeRz(timezone_t state, struct tm *timep) {
#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
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
#else
time_t r = mktime_z(state, timep);
if (r == (time_t)-1) {
terrno = TAOS_SYSTEM_ERROR(errno);
}
return r;
#endif
}
struct tm *taosLocalTimeRz(timezone_t state, const time_t *timep, struct tm *result) {
struct tm *res = NULL;
if (timep == NULL || result == NULL) {
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;
}
}
#else
return localtime_rz(state, timep, result);
#endif
}
static int isLeapYear(time_t year) {
if (year % 4)
return 0;
else if (year % 100)
return 1;
else if (year % 400)
return 0;
else
return 1;
}
struct tm *taosLocalTimeNolock(struct tm *result, const time_t *timep, int dst) {
if (result == NULL) {
return NULL;
}
#ifdef WINDOWS
if (*timep < 0) {
return NULL;
// TODO: bugs in following code
SYSTEMTIME ss, s;
FILETIME ff, f;
LARGE_INTEGER offset;
struct tm tm1;
time_t tt = 0;
if (localtime_s(&tm1, &tt) != 0) {
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) {
return NULL;
}
}
#elif defined(LINUX)
time_t secsMin = 60, secsHour = 3600, secsDay = 3600 * 24;
long tz = timezone;
time_t t = *timep;
t -= tz; /* Adjust for timezone. */
t += 3600 * dst; /* Adjust for daylight time. */
time_t days = t / secsDay; /* Days passed since epoch. */
time_t seconds = t % secsDay; /* Remaining seconds. */
result->tm_isdst = dst;
result->tm_hour = seconds / secsHour;
result->tm_min = (seconds % secsHour) / secsMin;
result->tm_sec = (seconds % secsHour) % secsMin;
/* 1/1/1970 was a Thursday, that is, day 4 from the POV of the tm structure
* where sunday = 0, so to calculate the day of the week we have to add 4
* and take the modulo by 7. */
result->tm_wday = (days + 4) % 7;
/* Calculate the current year. */
result->tm_year = 1970;
while (1) {
/* Leap years have one day more. */
time_t daysOfYear = 365 + isLeapYear(result->tm_year);
if (daysOfYear > days) break;
days -= daysOfYear;
result->tm_year++;
}
result->tm_yday = days; /* Number of day of the current year. */
/* We need to calculate in which month and day of the month we are. To do
* so we need to skip days according to how many days there are in each
* month, and adjust for the leap year that has one more day in February. */
int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
mdays[1] += isLeapYear(result->tm_year);
result->tm_mon = 0;
while (days >= mdays[result->tm_mon]) {
days -= mdays[result->tm_mon];
result->tm_mon++;
}
result->tm_mday = days + 1; /* Add 1 since our 'days' is zero-based. */
result->tm_year -= 1900; /* Surprisingly tm_year is year-1900. */
#else
localtime_r(timep, result);
#endif
return result;
}
int32_t taosGetTimestampSec() { return (int32_t)time(NULL); }
int32_t taosClockGetTime(int clock_id, struct timespec *pTS) {

View File

@ -764,7 +764,7 @@ int32_t taosSetGlobalTimezone(const char *tz) {
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));
@ -830,16 +830,9 @@ int32_t taosSetGlobalTimezone(const char *tz) {
int32_t taosFormatTimezoneStr(time_t t, const char* tz, timezone_t sp, char *outTimezoneStr){
struct tm tm1;
if (sp == NULL) {
if (taosLocalTime(&t, &tm1, NULL, 0) == NULL) {
uError("failed to get local time");
return TSDB_CODE_TIME_ERROR;
}
} else {
if (taosLocalTimeRz(sp, &t, &tm1) == NULL) {
uError("failed to get rz time");
return TSDB_CODE_TIME_ERROR;
}
if (taosLocalTime(&t, &tm1, NULL, 0, sp) == NULL) {
uError("%s failed to get local time: code:%d", __FUNCTION__, errno);
return TSDB_CODE_TIME_ERROR;
}
/*
@ -862,12 +855,13 @@ int32_t taosFormatTimezoneStr(time_t t, const char* tz, timezone_t sp, char *out
return TSDB_CODE_TIME_ERROR;
}
(void)snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (%s, %s)", tz, str1, str2);
uDebug("[tz] system timezone:%s", outTimezoneStr);
return 0;
}
void getTimezoneStr(char *tz) {
do {
int n = readlink("/r/localtime", tz, TD_TIMEZONE_LEN - 1);
int n = readlink("/etc/localtime", tz, TD_TIMEZONE_LEN - 1);
if (n < 0) {
uWarn("[tz] failed to readlink /etc/localtime, reason:%s", strerror(errno));
break;
@ -903,6 +897,7 @@ END:
if (tz[0] == '\0') {
memcpy(tz, "n/a", sizeof("n/a"));
}
uDebug("[tz] system timezone:%s", tz);
}
int32_t taosGetSystemTimezone(char *outTimezoneStr) {
@ -3211,3 +3206,627 @@ leapcorr(struct state const *sp, time_t t)
}
return 0;
}
/*
* **************************************************************************
* The code from here to the end of the file is the code for the
* strftime() function.
* *****************
*/
#ifndef DEPRECATE_TWO_DIGIT_YEARS
# define DEPRECATE_TWO_DIGIT_YEARS false
#endif
struct lc_time_T {
const char * mon[MONSPERYEAR];
const char * month[MONSPERYEAR];
const char * wday[DAYSPERWEEK];
const char * weekday[DAYSPERWEEK];
const char * X_fmt;
const char * x_fmt;
const char * c_fmt;
const char * am;
const char * pm;
const char * date_fmt;
};
static const struct lc_time_T C_time_locale = {
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
}, {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
}, {
"Sun", "Mon", "Tue", "Wed",
"Thu", "Fri", "Sat"
}, {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
},
/* X_fmt */
"%H:%M:%S",
/*
** x_fmt
** C99 and later require this format.
** Using just numbers (as here) makes Quakers happier;
** it's also compatible with SVR4.
*/
"%m/%d/%y",
/*
** c_fmt
** C99 and later require this format.
** Previously this code used "%D %X", but we now conform to C99.
** Note that
** "%a %b %d %H:%M:%S %Y"
** is used by Solaris 2.3.
*/
"%a %b %e %T %Y",
/* am */
"AM",
/* pm */
"PM",
/* date_fmt */
"%a %b %e %H:%M:%S %Z %Y"
};
enum warn { IN_NONE, IN_SOME, IN_THIS, IN_ALL };
static char * _add(const char *, char *, const char *);
static char * _conv(int, const char *, char *, const char *);
static char * _fmt(const char *, const struct tm *, char *, const char *,
enum warn *);
static char * _yconv(int, int, bool, bool, char *, char const *);
#ifndef YEAR_2000_NAME
# define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
#endif /* !defined YEAR_2000_NAME */
#if HAVE_STRFTIME_L
size_t
strftime_l(char *restrict s, size_t maxsize, char const *restrict format,
struct tm const *restrict t,
ATTRIBUTE_MAYBE_UNUSED locale_t locale)
{
/* Just call strftime, as only the C locale is supported. */
return strftime(s, maxsize, format, t);
}
#endif
size_t
strftime(char *restrict s, size_t maxsize, char const *restrict format,
struct tm const *restrict t)
{
char * p;
int saved_errno = errno;
enum warn warn = IN_NONE;
tzset();
p = _fmt(format, t, s, s + maxsize, &warn);
if (DEPRECATE_TWO_DIGIT_YEARS
&& warn != IN_NONE && getenv(YEAR_2000_NAME)) {
fprintf(stderr, "\n");
fprintf(stderr, "strftime format \"%s\" ", format);
fprintf(stderr, "yields only two digits of years in ");
if (warn == IN_SOME)
fprintf(stderr, "some locales");
else if (warn == IN_THIS)
fprintf(stderr, "the current locale");
else fprintf(stderr, "all locales");
fprintf(stderr, "\n");
}
if (p == s + maxsize) {
errno = ERANGE;
return 0;
}
*p = '\0';
errno = saved_errno;
return p - s;
}
static char *
_fmt(const char *format, const struct tm *t, char *pt,
const char *ptlim, enum warn *warnp)
{
struct lc_time_T const *Locale = &C_time_locale;
for ( ; *format; ++format) {
if (*format == '%') {
label:
switch (*++format) {
default:
/* Output unknown conversion specifiers as-is,
to aid debugging. This includes '%' at
format end. This conforms to C23 section
7.29.3.5 paragraph 6, which says behavior
is undefined here. */
--format;
break;
case 'A':
pt = _add((t->tm_wday < 0 ||
t->tm_wday >= DAYSPERWEEK) ?
"?" : Locale->weekday[t->tm_wday],
pt, ptlim);
continue;
case 'a':
pt = _add((t->tm_wday < 0 ||
t->tm_wday >= DAYSPERWEEK) ?
"?" : Locale->wday[t->tm_wday],
pt, ptlim);
continue;
case 'B':
pt = _add((t->tm_mon < 0 ||
t->tm_mon >= MONSPERYEAR) ?
"?" : Locale->month[t->tm_mon],
pt, ptlim);
continue;
case 'b':
case 'h':
pt = _add((t->tm_mon < 0 ||
t->tm_mon >= MONSPERYEAR) ?
"?" : Locale->mon[t->tm_mon],
pt, ptlim);
continue;
case 'C':
/*
** %C used to do a...
** _fmt("%a %b %e %X %Y", t);
** ...whereas now POSIX 1003.2 calls for
** something completely different.
** (ado, 1993-05-24)
*/
pt = _yconv(t->tm_year, TM_YEAR_BASE,
true, false, pt, ptlim);
continue;
case 'c':
{
enum warn warn2 = IN_SOME;
pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
*warnp = warn2;
}
continue;
case 'D':
pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
continue;
case 'd':
pt = _conv(t->tm_mday, "%02d", pt, ptlim);
continue;
case 'E':
case 'O':
/*
** Locale modifiers of C99 and later.
** The sequences
** %Ec %EC %Ex %EX %Ey %EY
** %Od %oe %OH %OI %Om %OM
** %OS %Ou %OU %OV %Ow %OW %Oy
** are supposed to provide alternative
** representations.
*/
goto label;
case 'e':
pt = _conv(t->tm_mday, "%2d", pt, ptlim);
continue;
case 'F':
pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
continue;
case 'H':
pt = _conv(t->tm_hour, "%02d", pt, ptlim);
continue;
case 'I':
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
"%02d", pt, ptlim);
continue;
case 'j':
pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
continue;
case 'k':
/*
** This used to be...
** _conv(t->tm_hour % 12 ?
** t->tm_hour % 12 : 12, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbins'
** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 1993-05-24)
*/
pt = _conv(t->tm_hour, "%2d", pt, ptlim);
continue;
#ifdef KITCHEN_SINK
case 'K':
/*
** After all this time, still unclaimed!
*/
pt = _add("kitchen sink", pt, ptlim);
continue;
#endif /* defined KITCHEN_SINK */
case 'l':
/*
** This used to be...
** _conv(t->tm_hour, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbin's
** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 1993-05-24)
*/
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
"%2d", pt, ptlim);
continue;
case 'M':
pt = _conv(t->tm_min, "%02d", pt, ptlim);
continue;
case 'm':
pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
continue;
case 'n':
pt = _add("\n", pt, ptlim);
continue;
case 'p':
pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
Locale->pm :
Locale->am,
pt, ptlim);
continue;
case 'R':
pt = _fmt("%H:%M", t, pt, ptlim, warnp);
continue;
case 'r':
pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
continue;
case 'S':
pt = _conv(t->tm_sec, "%02d", pt, ptlim);
continue;
case 's':
{
struct tm tm;
char buf[INT_STRLEN_MAXIMUM(
time_t) + 1];
time_t mkt;
tm.tm_sec = t->tm_sec;
tm.tm_min = t->tm_min;
tm.tm_hour = t->tm_hour;
tm.tm_mday = t->tm_mday;
tm.tm_mon = t->tm_mon;
tm.tm_year = t->tm_year;
#ifdef TM_GMTOFF
mkt = timeoff(&tm, t->TM_GMTOFF);
#else
tm.tm_isdst = t->tm_isdst;
mkt = mktime(&tm);
#endif
/* If mktime fails, %s expands to the
value of (time_t) -1 as a failure
marker; this is better in practice
than strftime failing. */
if (TYPE_SIGNED(time_t)) {
intmax_t n = mkt;
sprintf(buf, "%"PRIdMAX, n);
} else {
uintmax_t n = mkt;
sprintf(buf, "%"PRIuMAX, n);
}
pt = _add(buf, pt, ptlim);
}
continue;
case 'T':
pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
continue;
case 't':
pt = _add("\t", pt, ptlim);
continue;
case 'U':
pt = _conv((t->tm_yday + DAYSPERWEEK -
t->tm_wday) / DAYSPERWEEK,
"%02d", pt, ptlim);
continue;
case 'u':
/*
** From Arnold Robbins' strftime version 3.0:
** "ISO 8601: Weekday as a decimal number
** [1 (Monday) - 7]"
** (ado, 1993-05-24)
*/
pt = _conv((t->tm_wday == 0) ?
DAYSPERWEEK : t->tm_wday,
"%d", pt, ptlim);
continue;
case 'V': /* ISO 8601 week number */
case 'G': /* ISO 8601 year (four digits) */
case 'g': /* ISO 8601 year (two digits) */
/*
** From Arnold Robbins' strftime version 3.0: "the week number of the
** year (the first Monday as the first day of week 1) as a decimal number
** (01-53)."
** (ado, 1993-05-24)
**
** From <https://www.cl.cam.ac.uk/~mgk25/iso-time.html> by Markus Kuhn:
** "Week 01 of a year is per definition the first week which has the
** Thursday in this year, which is equivalent to the week which contains
** the fourth day of January. In other words, the first week of a new year
** is the week which has the majority of its days in the new year. Week 01
** might also contain days from the previous year and the week before week
** 01 of a year is the last week (52 or 53) of the previous year even if
** it contains days from the new year. A week starts with Monday (day 1)
** and ends with Sunday (day 7). For example, the first week of the year
** 1997 lasts from 1996-12-30 to 1997-01-05..."
** (ado, 1996-01-02)
*/
{
int year;
int base;
int yday;
int wday;
int w;
year = t->tm_year;
base = TM_YEAR_BASE;
yday = t->tm_yday;
wday = t->tm_wday;
for ( ; ; ) {
int len;
int bot;
int top;
len = isleap_sum(year, base) ?
DAYSPERLYEAR :
DAYSPERNYEAR;
/*
** What yday (-3 ... 3) does
** the ISO year begin on?
*/
bot = ((yday + 11 - wday) %
DAYSPERWEEK) - 3;
/*
** What yday does the NEXT
** ISO year begin on?
*/
top = bot -
(len % DAYSPERWEEK);
if (top < -3)
top += DAYSPERWEEK;
top += len;
if (yday >= top) {
++base;
w = 1;
break;
}
if (yday >= bot) {
w = 1 + ((yday - bot) /
DAYSPERWEEK);
break;
}
--base;
yday += isleap_sum(year, base) ?
DAYSPERLYEAR :
DAYSPERNYEAR;
}
#ifdef XPG4_1994_04_09
if ((w == 52 &&
t->tm_mon == TM_JANUARY) ||
(w == 1 &&
t->tm_mon == TM_DECEMBER))
w = 53;
#endif /* defined XPG4_1994_04_09 */
if (*format == 'V')
pt = _conv(w, "%02d",
pt, ptlim);
else if (*format == 'g') {
*warnp = IN_ALL;
pt = _yconv(year, base,
false, true,
pt, ptlim);
} else pt = _yconv(year, base,
true, true,
pt, ptlim);
}
continue;
case 'v':
/*
** From Arnold Robbins' strftime version 3.0:
** "date as dd-bbb-YYYY"
** (ado, 1993-05-24)
*/
pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
continue;
case 'W':
pt = _conv((t->tm_yday + DAYSPERWEEK -
(t->tm_wday ?
(t->tm_wday - 1) :
(DAYSPERWEEK - 1))) / DAYSPERWEEK,
"%02d", pt, ptlim);
continue;
case 'w':
pt = _conv(t->tm_wday, "%d", pt, ptlim);
continue;
case 'X':
pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
continue;
case 'x':
{
enum warn warn2 = IN_SOME;
pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
*warnp = warn2;
}
continue;
case 'y':
*warnp = IN_ALL;
pt = _yconv(t->tm_year, TM_YEAR_BASE,
false, true,
pt, ptlim);
continue;
case 'Y':
pt = _yconv(t->tm_year, TM_YEAR_BASE,
true, true,
pt, ptlim);
continue;
case 'Z':
#ifdef TM_ZONE
pt = _add(t->TM_ZONE, pt, ptlim);
#elif HAVE_TZNAME
if (t->tm_isdst >= 0)
pt = _add(tzname[t->tm_isdst != 0],
pt, ptlim);
#endif
/*
** C99 and later say that %Z must be
** replaced by the empty string if the
** time zone abbreviation is not
** determinable.
*/
continue;
case 'z':
#if defined TM_GMTOFF || USG_COMPAT || ALTZONE
{
long diff;
char const * sign;
bool negative;
# ifdef TM_GMTOFF
diff = t->TM_GMTOFF;
# else
/*
** C99 and later say that the UT offset must
** be computed by looking only at
** tm_isdst. This requirement is
** incorrect, since it means the code
** must rely on magic (in this case
** altzone and timezone), and the
** magic might not have the correct
** offset. Doing things correctly is
** tricky and requires disobeying the standard;
** see GNU C strftime for details.
** For now, punt and conform to the
** standard, even though it's incorrect.
**
** C99 and later say that %z must be replaced by
** the empty string if the time zone is not
** determinable, so output nothing if the
** appropriate variables are not available.
*/
if (t->tm_isdst < 0)
continue;
if (t->tm_isdst == 0)
# if USG_COMPAT
diff = -timezone;
# else
continue;
# endif
else
# if ALTZONE
diff = -altzone;
# else
continue;
# endif
# endif
negative = diff < 0;
if (diff == 0) {
# ifdef TM_ZONE
negative = t->TM_ZONE[0] == '-';
# else
negative = t->tm_isdst < 0;
# if HAVE_TZNAME
if (tzname[t->tm_isdst != 0][0] == '-')
negative = true;
# endif
# endif
}
if (negative) {
sign = "-";
diff = -diff;
} else sign = "+";
pt = _add(sign, pt, ptlim);
diff /= SECSPERMIN;
diff = (diff / MINSPERHOUR) * 100 +
(diff % MINSPERHOUR);
pt = _conv(diff, "%04d", pt, ptlim);
}
#endif
continue;
case '+':
pt = _fmt(Locale->date_fmt, t, pt, ptlim,
warnp);
continue;
case '%':
break;
}
}
if (pt == ptlim)
break;
*pt++ = *format;
}
return pt;
}
static char *
_conv(int n, const char *format, char *pt, const char *ptlim)
{
char buf[INT_STRLEN_MAXIMUM(int) + 1];
sprintf(buf, format, n);
return _add(buf, pt, ptlim);
}
static char *
_add(const char *str, char *pt, const char *ptlim)
{
while (pt < ptlim && (*pt = *str++) != '\0')
++pt;
return pt;
}
/*
** POSIX and the C Standard are unclear or inconsistent about
** what %C and %y do if the year is negative or exceeds 9999.
** Use the convention that %C concatenated with %y yields the
** same output as %Y, and that %Y contains at least 4 bytes,
** with more only if necessary.
*/
static char *
_yconv(int a, int b, bool convert_top, bool convert_yy,
char *pt, const char *ptlim)
{
register int lead;
register int trail;
int DIVISOR = 100;
trail = a % DIVISOR + b % DIVISOR;
lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
trail %= DIVISOR;
if (trail < 0 && lead > 0) {
trail += DIVISOR;
--lead;
} else if (lead < 0 && trail > 0) {
trail -= DIVISOR;
++lead;
}
if (convert_top) {
if (lead == 0 && trail < 0)
pt = _add("-0", pt, ptlim);
else pt = _conv(lead, "%02d", pt, ptlim);
}
if (convert_yy)
pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
return pt;
}

View File

@ -29,30 +29,11 @@
#include "os.h"
#include "tlog.h"
TEST(osTimeTests, taosLocalTimeNolock) {
time_t currentTime;
// Test when result is not NULL
struct tm expectedTime;
struct tm* result = taosLocalTimeNolock(&expectedTime, &currentTime, 1);
if (result) {
EXPECT_EQ(expectedTime.tm_year, result->tm_year);
EXPECT_EQ(expectedTime.tm_mon, result->tm_mon);
EXPECT_EQ(expectedTime.tm_mday, result->tm_mday);
EXPECT_EQ(expectedTime.tm_hour, result->tm_hour);
EXPECT_EQ(expectedTime.tm_min, result->tm_min);
EXPECT_EQ(expectedTime.tm_sec, result->tm_sec);
EXPECT_EQ(expectedTime.tm_wday, result->tm_wday);
EXPECT_EQ(expectedTime.tm_yday, result->tm_yday);
EXPECT_EQ(expectedTime.tm_isdst, result->tm_isdst);
}
}
TEST(osTimeTests, taosLocalTime) {
// Test 1: Test when both timep and result are not NULL
time_t timep = 1617531000; // 2021-04-04 18:10:00
struct tm result;
struct tm* local_time = taosLocalTime(&timep, &result, NULL, 0);
struct tm* local_time = taosLocalTime(&timep, &result, NULL, 0, NULL);
ASSERT_NE(local_time, nullptr);
ASSERT_EQ(local_time->tm_year, 121);
ASSERT_EQ(local_time->tm_mon, 3);
@ -62,7 +43,7 @@ TEST(osTimeTests, taosLocalTime) {
ASSERT_EQ(local_time->tm_sec, 00);
// Test 2: Test when timep is NULL
local_time = taosLocalTime(NULL, &result, NULL, 0);
local_time = taosLocalTime(NULL, &result, NULL, 0, NULL);
ASSERT_EQ(local_time, nullptr);
// Test 4: Test when timep is negative on Windows

View File

@ -254,14 +254,14 @@ static int32_t cfgSetTimezone(SConfigItem *pItem, const char *value, ECfgSrcType
uError("invalid timezone:%s", value);
TAOS_RETURN(TSDB_CODE_INVALID_TIMEZONE);
}
TAOS_CHECK_RETURN(osSetTimezone(value));
TAOS_CHECK_RETURN(doSetConf(pItem, value, stype));
if (strlen(value) == 0) {
uError("cfg:%s, type:%s src:%s, value:%s, skip to set timezone", pItem->name, cfgDtypeStr(pItem->dtype),
cfgStypeStr(stype), value);
TAOS_RETURN(TSDB_CODE_SUCCESS);
}
TAOS_CHECK_RETURN(osSetTimezone(value));
TAOS_CHECK_RETURN(doSetConf(pItem, tsTimezoneStr, stype));
TAOS_RETURN(TSDB_CODE_SUCCESS);
}
@ -698,11 +698,19 @@ int32_t cfgDumpItemValue(SConfigItem *pItem, char *buf, int32_t bufSize, int32_t
case CFG_DTYPE_DOUBLE:
len = tsnprintf(buf, bufSize, "%f", pItem->fval);
break;
case CFG_DTYPE_TIMEZONE:{
// char str1[TD_TIMEZONE_LEN] = {0};
// time_t tx1 = taosGetTimestampSec();
// if (taosFormatTimezoneStr(tx1, buf, NULL, str1) != 0) {
// tstrncpy(str1, "tz error", sizeof(str1));
// }
// len = tsnprintf(buf, bufSize, "%s", str1);
// break;
}
case CFG_DTYPE_STRING:
case CFG_DTYPE_DIR:
case CFG_DTYPE_LOCALE:
case CFG_DTYPE_CHARSET:
case CFG_DTYPE_TIMEZONE:
case CFG_DTYPE_NONE:
len = tsnprintf(buf, bufSize, "%s", pItem->str);
break;

View File

@ -20,6 +20,7 @@
#include "tglobal.h"
#include "tjson.h"
#include "tutil.h"
#include "ttime.h"
#define LOG_MAX_LINE_SIZE (10024)
#define LOG_MAX_LINE_BUFFER_SIZE (LOG_MAX_LINE_SIZE + 3)
@ -157,24 +158,11 @@ static int32_t taosStartLog() {
static void getDay(char *buf, int32_t bufSize) {
time_t t = taosTime(NULL);
struct tm tmInfo;
if (taosLocalTime(&t, &tmInfo, buf, bufSize) != NULL) {
if (taosLocalTime(&t, &tmInfo, buf, bufSize, NULL) != NULL) {
TAOS_UNUSED(strftime(buf, bufSize, "%Y-%m-%d", &tmInfo));
}
}
static int64_t getTimestampToday() {
time_t t = taosTime(NULL);
struct tm tm;
if (taosLocalTime(&t, &tm, NULL, 0) == NULL) {
return 0;
}
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
return (int64_t)taosMktime(&tm);
}
static void getFullPathName(char *fullName, const char *logName) {
if (strlen(tsLogDir) != 0) {
char lastC = tsLogDir[strlen(tsLogDir) - 1];
@ -206,7 +194,7 @@ int32_t taosInitSlowLog() {
getDay(day, sizeof(day));
(void)snprintf(name, PATH_MAX + TD_TIME_STR_LEN, "%s.%s", tsLogObj.slowLogName, day);
tsLogObj.timestampToday = getTimestampToday();
tsLogObj.timestampToday = taosGetTimestampToday(TSDB_TIME_PRECISION_SECONDS, NULL);
tsLogObj.slowHandle = taosLogBuffNew(LOG_SLOW_BUF_SIZE);
if (tsLogObj.slowHandle == NULL) return terrno;
@ -448,7 +436,7 @@ static void taosOpenNewSlowLogFile() {
TdFilePtr pOldFile = tsLogObj.slowHandle->pFile;
tsLogObj.slowHandle->pFile = pFile;
(void)taosCloseFile(&pOldFile);
tsLogObj.timestampToday = getTimestampToday();
tsLogObj.timestampToday = taosGetTimestampToday(TSDB_TIME_PRECISION_SECONDS, NULL);
(void)taosThreadMutexUnlock(&tsLogObj.logMutex);
}
@ -634,8 +622,11 @@ static inline int32_t taosBuildLogHead(char *buffer, const char *flags) {
TAOS_UNUSED(taosGetTimeOfDay(&timeSecs));
time_t curTime = timeSecs.tv_sec;
ptm = taosLocalTime(&curTime, &Tm, NULL, 0);
ptm = taosLocalTime(&curTime, &Tm, NULL, 0, NULL);
if (ptm == NULL){
uError("%s failed to get local time, code:%d", __FUNCTION__ , errno);
return 0;
}
return sprintf(buffer, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " %s %s", ptm->tm_mon + 1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec, taosGetSelfPthreadId(),
LOG_EDITION_FLG, flags);

View File

@ -159,9 +159,44 @@ class TDTestCase:
tdSql.execute(f'drop database {self.dbname}')
# def timezone_check(self, cursor, timezone):
# cursor.execute("show local variables")
# res = cursor.fetchall()
# for i in range(cursor.rowcount):
# if res[i][0] == "timezone" :
# if res[i][1].find(timezone) == -1:
# tdLog.exit("show timezone:%s != %s"%(res[i][1],timezone))
#
# def timezone_check_set_options(self):
# buildPath = tdCom.getBuildPath()
# cmdStr = '%s/build/bin/timezone_test'%(buildPath)
# print("cmdStr:", cmdStr)
# tdLog.info(cmdStr)
# ret = os.system(cmdStr)
# if ret != 0:
# tdLog.exit("timezone_test error")
#
# def timezone_check_conf(self, timezone):
# updateCfgDict = ({"clientCfg" : {'timezone': 'UTC'} },)
# tdDnodes.sim.deploy(updateCfgDict)
# conn = taos.connect(config=tdDnodes.getSimCfgPath())
# cursor = conn.cursor()
# self.timezone_check(cursor, 'UTC')
# cursor.close()
def timezone_check(self, sql, timezone):
tdSql.query(sql)
rows = tdSql.getRows()
for i in range(rows):
if tdSql.getData(i, 0) == "timezone" :
if tdSql.getData(i, 1).find(timezone) == -1:
tdLog.exit("show timezone:%s != %s"%(tdSql.getData(i, 1),timezone))
def run(self): # sourcery skip: extract-duplicate-method
timezone = self.get_system_timezone()
# timezone = self.get_system_timezone()
timezone = "Asia/Shanghai"
self.timezone_check("show local variables", timezone)
self.timezone_check("show dnode 1 variables", timezone)
self.timezone_check_ntb(timezone)
self.timezone_check_stb(timezone)
self.timezone_format_test()

View File

@ -0,0 +1,34 @@
from util.log import *
from util.sql import *
from util.cases import *
from util.sqlset import *
from util.cluster import *
class TDTestCase:
updateCfgDict = {"clientCfg" : {'timezone': 'UTC'} , 'timezone': 'UTC-8'}
def init(self, conn, logSql, replicaVar=1):
self.replicaVar = int(replicaVar)
tdLog.debug(f"start to excute {__file__}")
tdSql.init(conn.cursor())
def timezone_check(self, timezone, sql):
tdSql.execute(sql)
rows = tdSql.getRows()
for i in range(rows):
if tdSql.getData(i, 0) == "timezone" :
if tdSql.getData(i, 1).find(timezone) == -1:
tdLog.exit("show timezone:%s != %s"%(tdSql.getData(i, 1),timezone))
def run(self):
self.timezone_check('UTC', "show local variables")
self.timezone_check('UTC-8', "show dnode 1 variables")
def stop(self):
tdSql.close()
tdLog.success(f"{__file__} successfully executed")
tdCases.addLinux(__file__, TDTestCase())
tdCases.addWindows(__file__, TDTestCase())

View File

@ -337,7 +337,7 @@ char *shellFormatTimestamp(char *buf, int32_t bufSize, int64_t val, int32_t prec
}
struct tm ptm = {0};
if (taosLocalTime(&tt, &ptm, buf, bufSize) == NULL) {
if (taosLocalTime(&tt, &ptm, buf, bufSize, NULL) == NULL) {
return buf;
}
size_t pos = strftime(buf, 35, "%Y-%m-%d %H:%M:%S", &ptm);

View File

@ -15,6 +15,7 @@ add_executable(tmq_multi_thread_test tmq_multi_thread_test.c)
add_executable(tmq_offset_test tmq_offset_test.c)
add_executable(varbinary_test varbinary_test.c)
add_executable(replay_test replay_test.c)
add_executable(timezone_test timezone_test.c)
if(${TD_LINUX})
add_executable(tsz_test tsz_test.c)
@ -142,6 +143,14 @@ target_link_libraries(
PUBLIC os
)
target_link_libraries(
timezone_test
PUBLIC taos
PUBLIC util
PUBLIC common
PUBLIC os
)
if(${TD_LINUX})
target_link_libraries(
tsz_test

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "taos.h"
#include "types.h"
#include "tlog.h"
char* timezone_name = "America/New_York";
void check_timezone(const char* tzName){
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT(pConn != NULL);
TAOS_RES *pRes = taos_query(pConn, "show local variables");
ASSERT(taos_errno(pRes) == 0);
TAOS_ROW row = NULL;
while ((row = taos_fetch_row(pRes)) != NULL) {
if (strcmp(row[0], "timezone") == 0){
ASSERT(strstr(row[1], tzName) != NULL);
}
}
taos_free_result(pRes);
taos_close(pConn);
}
void timezone_set_options_test(){
taos_options(TSDB_OPTION_TIMEZONE, timezone_name);
check_timezone(timezone_name);
}
void timezone_insert_test(){
TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
TAOS_RES *pRes = taos_query(taos, "drop database if exists tz_db");
taos_free_result(pRes);
pRes = taos_query(taos, "create database if not exists tz_db");
taos_free_result(pRes);
pRes = taos_query(taos, "use tz_db");
int code = taos_errno(pRes);
taos_free_result(pRes);
ASSERT(code == 0);
pRes = taos_query(taos, "create stable stb (ts timestamp, c1 int) tags (t1 timestamp, t2 binary(32))");
taos_free_result(pRes);
pRes = taos_query(taos, "create table ntb (ts timestamp, c1 int)");
taos_free_result(pRes);
pRes = taos_query(taos, "insert into tb1 using stb tags (1, 'test') values (1, 2)");
taos_free_result(pRes);
pRes = taos_query(taos, "insert into tb1 using stb tags ('2013-04-12T10:52:01', 'test') values ('2013-04-12T10:52:01', 2)");
taos_free_result(pRes);
pRes = taos_query(taos, "insert into ntb values ('2013-04-12T10:52:01', 2)");
taos_free_result(pRes);
pRes = taos_query(taos, "insert into ntb values (1, 2)");
taos_free_result(pRes);
/*
select today();
select cast(1 as timestamp) + '2013-04-12T10:52:01';
tsConver.sim
"COMPACT DATABASE test START WITH '2023-03-07 14:01:23' END WITH '2023-03-08 14:01:23'"
TK_TIMEZONE
ts > c1('2013-04-12T10:52:01')
in ('2013-04-12T10:52:01')
offsetFromTz hash join
*/
}
int main(int argc, char *argv[]) {
int ret = 0;
timezone_set_options_test();
return ret;
}

View File

@ -597,7 +597,7 @@ void printParaIntoFile() {
time_t tTime = taosGetTimestampSec();
struct tm tm;
taosLocalTime(&tTime, &tm, NULL, 0);
taosLocalTime(&tTime, &tm, NULL, 0, NULL);
taosFprintfFile(pFile, "###################################################################\n");
taosFprintfFile(pFile, "# configDir: %s\n", configDir);

View File

@ -166,7 +166,7 @@ static void printHelp() {
char* getCurrentTimeString(char* timeString) {
time_t tTime = taosGetTimestampSec();
struct tm tm;
taosLocalTime(&tTime, &tm, NULL, 0);
taosLocalTime(&tTime, &tm, NULL, 0, NULL);
sprintf(timeString, "%d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
tm.tm_min, tm.tm_sec);
@ -472,7 +472,7 @@ static char* shellFormatTimestamp(char* buf, int32_t bufSize, int64_t val, int32
}
struct tm ptm;
if (taosLocalTime(&tt, &ptm, buf, bufSize) == NULL) {
if (taosLocalTime(&tt, &ptm, buf, bufSize, NULL) == NULL) {
return buf;
}
size_t pos = strftime(buf, 35, "%Y-%m-%d %H:%M:%S", &ptm);

View File

@ -797,7 +797,7 @@ bool simExecuteNativeSqlCommand(SScript *script, char *rest, bool isSlow) {
tt = (*(int64_t *)row[i]) / 1000000000;
}
if (taosLocalTime(&tt, &tp, timeStr, sizeof(timeStr)) == NULL) {
if (taosLocalTime(&tt, &tp, timeStr, sizeof(timeStr), NULL) == NULL) {
break;
}
strftime(timeStr, 64, "%y-%m-%d %H:%M:%S", &tp);