[Libreoffice-commits] online.git: common/Util.cpp common/Util.hpp test/WhiteBoxTests.cpp
Ashod Nakashian (via logerrit)
logerrit at kemper.freedesktop.org
Tue Oct 29 01:39:53 UTC 2019
common/Util.cpp | 44 +++++++++++++++++++++++++++++++++----------
common/Util.hpp | 3 ++
test/WhiteBoxTests.cpp | 50 ++++++++++++++++++++++++++++++++++---------------
3 files changed, 72 insertions(+), 25 deletions(-)
New commits:
commit d038ceb118bc777756f8390dd959cb94c860ef25
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Fri Oct 25 20:48:05 2019 -0400
Commit: Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Tue Oct 29 02:39:34 2019 +0100
test: Improve iso8601ToTimestamp and tests
Using double caused all sorts of rounding issues,
especially with random unit-test failures.
Luckily, we don't need doubles and can do everything
with integers.
Also added a new function to print time_point as
iso8601 string, for logging and convenience.
Change-Id: I1c2040c02d1143282dbde0dadef32613b77c330d
Reviewed-on: https://gerrit.libreoffice.org/81578
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/common/Util.cpp b/common/Util.cpp
index 3ceb2378a..49d465035 100644
--- a/common/Util.cpp
+++ b/common/Util.cpp
@@ -25,7 +25,6 @@
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
-#include <time.h>
#include <atomic>
#include <cassert>
@@ -33,6 +32,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
@@ -836,31 +836,55 @@ namespace Util
return oss.str();
}
- std::chrono::system_clock::time_point iso8601ToTimestamp(const std::string& iso8601Time, const std::string& logName)
+ std::string time_point_to_iso8601(std::chrono::system_clock::time_point tp)
+ {
+ const std::time_t tt = std::chrono::system_clock::to_time_t(tp);
+ std::tm tm;
+ gmtime_r(&tt, &tm);
+
+ std::ostringstream oss;
+ oss << tm.tm_year + 1900 << '-' << std::setfill('0') << std::setw(2) << tm.tm_mon + 1 << '-'
+ << std::setfill('0') << std::setw(2) << tm.tm_mday << 'T';
+ oss << std::setfill('0') << std::setw(2) << tm.tm_hour << ':';
+ oss << std::setfill('0') << std::setw(2) << tm.tm_min << ':';
+ const std::chrono::duration<double> sec
+ = tp - std::chrono::system_clock::from_time_t(tt) + std::chrono::seconds(tm.tm_sec);
+ if (sec.count() < 10)
+ oss << '0';
+ oss << std::fixed << sec.count() << 'Z';
+
+ return oss.str();
+ }
+
+ std::chrono::system_clock::time_point iso8601ToTimestamp(const std::string& iso8601Time,
+ const std::string& logName)
{
std::chrono::system_clock::time_point timestamp;
std::tm tm;
- const char *cstr = iso8601Time.c_str();
- const char *trailing;
+ const char* cstr = iso8601Time.c_str();
+ const char* trailing;
if (!(trailing = strptime(cstr, "%Y-%m-%dT%H:%M:%S", &tm)))
{
LOG_WRN(logName << " [" << iso8601Time << "] is in invalid format."
- << "Returning " << timestamp.time_since_epoch().count());
+ << "Returning " << timestamp.time_since_epoch().count());
return timestamp;
}
+
timestamp += std::chrono::seconds(timegm(&tm));
if (trailing[0] == '\0')
return timestamp;
- double us;
+
if (trailing[0] != '.')
{
LOG_WRN(logName << " [" << iso8601Time << "] is in invalid format."
- << ". Returning " << timestamp.time_since_epoch().count());
+ << ". Returning " << timestamp.time_since_epoch().count());
return timestamp;
}
- char *end = nullptr;
- us = strtod(trailing, &end);
- std::size_t seconds_us = us * std::chrono::system_clock::period::den / std::chrono::system_clock::period::num;
+
+ char* end = nullptr;
+ const size_t us = strtoul(trailing + 1, &end, 10); // Skip the '.' and read as integer.
+ const std::size_t seconds_us = us * std::chrono::system_clock::period::den
+ / std::chrono::system_clock::period::num / 1000000;
timestamp += std::chrono::system_clock::duration(seconds_us);
diff --git a/common/Util.hpp b/common/Util.hpp
index d345950ba..82389c1ab 100644
--- a/common/Util.hpp
+++ b/common/Util.hpp
@@ -935,6 +935,9 @@ int main(int argc, char**argv)
//// Return time in ISO8061 fraction format
std::string getIso8601FracformatTime(std::chrono::system_clock::time_point time);
+ /// Convert a time_point to iso8601 formatted string.
+ std::string time_point_to_iso8601(std::chrono::system_clock::time_point tp);
+
//// Convert time from ISO8061 fraction format
std::chrono::system_clock::time_point iso8601ToTimestamp(const std::string& iso8601Time, const std::string& logName);
diff --git a/test/WhiteBoxTests.cpp b/test/WhiteBoxTests.cpp
index 597adb500..219c3ccf2 100644
--- a/test/WhiteBoxTests.cpp
+++ b/test/WhiteBoxTests.cpp
@@ -738,37 +738,57 @@ void WhiteBoxTests::testTime()
{
std::ostringstream oss;
- std::chrono::system_clock::time_point t(std::chrono::nanoseconds(1567444337874777375));
- CPPUNIT_ASSERT_EQUAL(std::string("2019-09-02T17:12:17.874777Z"), Util::getIso8601FracformatTime(t));
+ std::chrono::system_clock::time_point t(std::chrono::nanoseconds(1567444337874777375));
+ CPPUNIT_ASSERT_EQUAL(std::string("2019-09-02T17:12:17.874777Z"),
+ Util::getIso8601FracformatTime(t));
t = std::chrono::system_clock::time_point(std::chrono::nanoseconds(0));
- CPPUNIT_ASSERT_EQUAL(std::string("1970-01-01T00:00:00.000000Z"), Util::getIso8601FracformatTime(t));
+ CPPUNIT_ASSERT_EQUAL(std::string("1970-01-01T00:00:00.000000Z"),
+ Util::getIso8601FracformatTime(t));
- t = Util::iso8601ToTimestamp("2019-09-02T17:12:17.874777Z", "LastModifiedTime");
- oss << t.time_since_epoch().count();
- CPPUNIT_ASSERT_EQUAL(std::string("1567444337874777000"), oss.str());
-
- oss.str(std::string());
t = Util::iso8601ToTimestamp("1970-01-01T00:00:00.000000Z", "LastModifiedTime");
oss << t.time_since_epoch().count();
CPPUNIT_ASSERT_EQUAL(std::string("0"), oss.str());
+ CPPUNIT_ASSERT_EQUAL(std::string("1970-01-01T00:00:00.000000Z"),
+ Util::time_point_to_iso8601(t));
oss.str(std::string());
- t = std::chrono::system_clock::now();
- uint64_t t_in_micros = (t.time_since_epoch().count() / 1000) * 1000;
- oss << t_in_micros;
- std::string first = oss.str();
- std::string s = Util::getIso8601FracformatTime(t);
- t = Util::iso8601ToTimestamp(s, "LastModifiedTime");
+ t = Util::iso8601ToTimestamp("2019-09-02T17:12:17.874777Z", "LastModifiedTime");
+ oss << t.time_since_epoch().count();
+ CPPUNIT_ASSERT_EQUAL(std::string("1567444337874777000"), oss.str());
+ CPPUNIT_ASSERT_EQUAL(std::string("2019-09-02T17:12:17.874777Z"),
+ Util::time_point_to_iso8601(t));
+
oss.str(std::string());
+ t = Util::iso8601ToTimestamp("2019-10-24T14:31:28.063730Z", "LastModifiedTime");
oss << t.time_since_epoch().count();
- CPPUNIT_ASSERT_EQUAL(first, oss.str());
+ CPPUNIT_ASSERT_EQUAL(std::string("1571927488063730000"), oss.str());
+ CPPUNIT_ASSERT_EQUAL(std::string("2019-10-24T14:31:28.063730Z"),
+ Util::time_point_to_iso8601(t));
+
+ t = Util::iso8601ToTimestamp("2020-02-20T20:02:20.100000Z", "LastModifiedTime");
+ CPPUNIT_ASSERT_EQUAL(std::string("2020-02-20T20:02:20.100000Z"),
+ Util::time_point_to_iso8601(t));
t = std::chrono::system_clock::time_point();
CPPUNIT_ASSERT_EQUAL(std::string("Thu, 01 Jan 1970 00:00:00"), Util::getHttpTime(t));
t = std::chrono::system_clock::time_point(std::chrono::nanoseconds(1569592993495336798));
CPPUNIT_ASSERT_EQUAL(std::string("Fri, 27 Sep 2019 14:03:13"), Util::getHttpTime(t));
+
+ for (int i = 0; i < 100; ++i)
+ {
+ t = std::chrono::system_clock::now();
+ const uint64_t t_in_micros = (t.time_since_epoch().count() / 1000) * 1000;
+
+ const std::string s = Util::getIso8601FracformatTime(t);
+ t = Util::iso8601ToTimestamp(s, "LastModifiedTime");
+ CPPUNIT_ASSERT_EQUAL(std::to_string(t_in_micros),
+ std::to_string(t.time_since_epoch().count()));
+
+ // Allow a small delay to get a different timestamp on next iteration.
+ sleep(0);
+ }
}
CPPUNIT_TEST_SUITE_REGISTRATION(WhiteBoxTests);
More information about the Libreoffice-commits
mailing list