feat:[TD-32642] add timezone logic
This commit is contained in:
parent
7aef49638e
commit
69da972796
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(", &ptm, buf, bufLen)) {
|
||||
if (NULL == taosLocalTime(", &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;
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ¶mList[0], ctx, rowNum));
|
||||
paramList[0].tz = node->tz;
|
||||
if (paramNum > 1) {
|
||||
TSWAP(ctx->type.selfType, ctx->type.peerType);
|
||||
SCL_ERR_JRET(sclInitParam(node->pRight, ¶mList[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(¶ms, node->pParameterList, ctx, ¶mNum, &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;
|
||||
|
|
|
@ -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 *)", &tmInfo, buf, sizeof(buf)) == NULL) {
|
||||
len = (int32_t)strlen(buf);
|
||||
if (taosGmTimeR((const time_t *)", &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);
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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, ¤tTime, 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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())
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue