diff --git a/include/znc/Utils.h b/include/znc/Utils.h index 1ff5565b..41d809a4 100644 --- a/include/znc/Utils.h +++ b/include/znc/Utils.h @@ -83,6 +83,7 @@ public: static CString CTime(time_t t, const CString& sTZ); static CString FormatTime(time_t t, const CString& sFormat, const CString& sTZ); static CString FormatServerTime(const timeval& tv); + static timeval ParseServerTime(const CString& sTime); static SCString GetTimezones(); static SCString GetEncodings(); diff --git a/src/Utils.cpp b/src/Utils.cpp index 3dbd18c8..85f24d81 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -458,6 +458,19 @@ CString CUtils::FormatServerTime(const timeval& tv) { return CString(sTime) + "." + s_msec + "Z"; } +timeval CUtils::ParseServerTime(const CString& sTime) { + struct tm stm; + memset(&stm, 0, sizeof(stm)); + const char* cp = strptime(sTime.c_str(), "%Y-%m-%dT%H:%M:%S", &stm); + struct timeval tv; + tv.tv_sec = mktime(&stm); + CString s_usec(cp); + if (s_usec.TrimPrefix(".") && s_usec.TrimSuffix("Z")) { + tv.tv_usec = s_usec.ToULong() * 1000; + } + return tv; +} + namespace { void FillTimezones(const CString& sPath, SCString& result, const CString& sPrefix) { CDir Dir; diff --git a/test/UtilsTest.cpp b/test/UtilsTest.cpp index ea5bf21a..f3926ffb 100644 --- a/test/UtilsTest.cpp +++ b/test/UtilsTest.cpp @@ -75,3 +75,32 @@ TEST(IRC32, SetMessageTags) { EXPECT_EQ(R"(@a=\:\s\\\r\n :rest)", sLine); } +TEST(UtilsTest, ServerTime) { + char* oldTZ = getenv("TZ"); + if (oldTZ) oldTZ = strdup(oldTZ); + setenv("TZ", "UTC", 1); + tzset(); + + timeval tv1 = CUtils::ParseServerTime("2011-10-19T16:40:51.620Z"); + CString str1 = CUtils::FormatServerTime(tv1); + EXPECT_EQ("2011-10-19T16:40:51.620Z", str1); + + timeval now; + if (!gettimeofday(&now, nullptr)) { + now.tv_sec = time(nullptr); + now.tv_usec = 0; + } + + CString str2 = CUtils::FormatServerTime(now); + timeval tv2 = CUtils::ParseServerTime(str2); + EXPECT_EQ(now.tv_sec, tv2.tv_sec); + EXPECT_EQ(now.tv_usec, tv2.tv_usec); + + if (oldTZ) { + setenv("TZ", oldTZ, 1); + free(oldTZ); + } else { + unsetenv("TZ"); + } + tzset(); +}