diff --git a/core/common/Strptime.cpp b/core/common/Strptime.cpp index 66fa06a131..aae3fe0c05 100644 --- a/core/common/Strptime.cpp +++ b/core/common/Strptime.cpp @@ -82,7 +82,7 @@ static const unsigned char* find_string(const unsigned char*, int*, const char* // Modify from https://github.com/tnodir/luasys/blob/master/src/win32/strptime.c const char* strptime_ns(const char* buf, const char* fmt, struct tm* tm, long* nanosecond, int* nanosecondLength) { // Replenish %s support. - if (0 == strcmp("%s", fmt)) { + if (0 == strcmp("%s", fmt) || 0 == strcmp("%s%f", fmt)) { char* cp; long long n; n = strtoll(buf, &cp, 10); @@ -107,15 +107,20 @@ const char* strptime_ns(const char* buf, const char* fmt, struct tm* tm, long* n *nanosecond = 0; *nanosecondLength = 0; - conv_nanosecond((const unsigned char*)(buf + secondTimestampLength), nanosecond, nanosecondLength); + const unsigned char* fractionStart = (const unsigned char*)(buf + secondTimestampLength); + conv_nanosecond(fractionStart, nanosecond, nanosecondLength); return ((const char*)cp); } unsigned char c; const unsigned char *bp, *ep; int alt_format, i, split_year = 0, neg = 0, offs; + char* cp = nullptr; + long long n; + time_t t; const char* new_fmt; *nanosecond = 0; + *nanosecondLength = 0; bp = (const unsigned char*)buf; @@ -291,6 +296,22 @@ const char* strptime_ns(const char* buf, const char* fmt, struct tm* tm, long* n LEGAL_ALT(ALT_O); continue; + case 's': /* Seconds since epoch. */ + n = strtoll((const char*)bp, &cp, 10); + if (n == 0 || (long long)(t = n) != n) { + return NULL; + } +#ifdef _MSC_VER + if (localtime_s(tm, &t) != 0) + return NULL; +#else + if (NULL == localtime_r(&t, tm)) + return NULL; +#endif + bp = (const unsigned char*)cp; + LEGAL_ALT(0); + continue; + case 'U': /* The week of year, beginning on sunday. */ case 'W': /* The week of year, beginning on monday. */ /* @@ -561,7 +582,7 @@ static const unsigned char* conv_num(const unsigned char* buf, int* dest, unsign static const unsigned char* conv_nanosecond(const unsigned char* buf, long* dest, int* nanosecondLength) { unsigned int result = 0; unsigned char ch; - int digitNum = 0; + int precisionDigitNum = 0; const unsigned char* start = buf; ch = *buf; @@ -569,12 +590,14 @@ static const unsigned char* conv_nanosecond(const unsigned char* buf, long* dest return NULL; do { - result *= 10; - result += ch - '0'; - ++digitNum; + if (precisionDigitNum < 9) { + result *= 10; + result += ch - '0'; + ++precisionDigitNum; + } ch = *++buf; } while (ch >= '0' && ch <= '9'); - for (int i = 0; i < 9 - digitNum; i++) { + for (int i = 0; i < 9 - precisionDigitNum; i++) { result *= 10; } *dest = result; diff --git a/core/unittest/common/TimeUtilUnittest.h b/core/unittest/common/TimeUtilUnittest.h index 2642760282..7344f421fe 100644 --- a/core/unittest/common/TimeUtilUnittest.h +++ b/core/unittest/common/TimeUtilUnittest.h @@ -193,8 +193,13 @@ void TimeUtilUnittest::TestStrptimeNanosecond() { 123456000}, {"1325430307", "%s", "1325430307", "%s", 0}, {"325430307", "%s", "325430307", "%s", 0}, + {"1325430307123456", "%s%f", "1325430307", "%s", 123456000}, + {"1325430307123456789", "%s%f", "1325430307", "%s", 123456789}, + {"1776235692.2729697", "%s.%f", "1776235692", "%s", 272969700}, + {"1776235692.2729697123", "%s.%f", "1776235692", "%s", 272969712}, + {"1776235692.2729697123Z", "%s.%fZ", "1776235692Z", "%sZ", 272969712}, // the behavior of `strptime_ns` is different with C++ `strptime` in this case - // {"1325430307123456", "%s", "1325430307123456", "%s", 123456000}, + {"1325430307123456", "%s", "1325430307", "%s", 123456000}, {"15:05:07.123456 2012-01-01", "%H:%M:%S.%f %Y-%m-%d", "15:05:07 2012-01-01", "%H:%M:%S %Y-%m-%d", 123456000}, };