From ab5d2a5a88b9ddea73c6d341c77dac74b0d8b7eb Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Fri, 20 Nov 2015 14:45:18 +0300 Subject: [PATCH 1/2] Add time_t to w3c time format converter and from time_t to w3c time converter as well. --- base/base_tests/base_tests.pro | 1 + base/base_tests/w3ctime_test.cpp | 17 ++++++++++++ base/w3ctime.hpp | 44 ++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 base/base_tests/w3ctime_test.cpp create mode 100644 base/w3ctime.hpp diff --git a/base/base_tests/base_tests.pro b/base/base_tests/base_tests.pro index a827fb1513..fa45f82abd 100644 --- a/base/base_tests/base_tests.pro +++ b/base/base_tests/base_tests.pro @@ -39,5 +39,6 @@ SOURCES += \ threads_test.cpp \ timer_test.cpp \ worker_thread_test.cpp \ + w3ctime_test.cpp \ HEADERS += diff --git a/base/base_tests/w3ctime_test.cpp b/base/base_tests/w3ctime_test.cpp new file mode 100644 index 0000000000..1689734aa9 --- /dev/null +++ b/base/base_tests/w3ctime_test.cpp @@ -0,0 +1,17 @@ +#include "base/w3ctime.hpp" +#include "testing/testing.hpp" + +using namespace w3ctime; + +UNIT_TEST(ParseTime) +{ + TEST_EQUAL(ParseTime(""), kNotATime, ()); + TEST_EQUAL(ParseTime("2015-10-11 23:21"), kNotATime, ()); + TEST_EQUAL(ParseTime("2015-10-11T23:21Z"), 1444605660, ()); +} + +UNIT_TEST(TimeToString) +{ + TEST_EQUAL(TimeToString(0), "1970-01-01T00:00Z", ()); + TEST_EQUAL(TimeToString(1444605660), "2015-10-11T23:21Z", ()); +} diff --git a/base/w3ctime.hpp b/base/w3ctime.hpp new file mode 100644 index 0000000000..5bc8ae7621 --- /dev/null +++ b/base/w3ctime.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "std/array.hpp" +#include "std/ctime.hpp" +#include "std/string.hpp" + +// It would be better to use c++ standard means of +// time parsing and unparsing like +// time_get/time_put () or get_time/put_time (). +// But at the moment of writing they was not widely supporded +// and/or worked inkorekd. +// +// All covertions are made in UTC + +namespace w3ctime +{ +char constexpr kW3CTimeFormat[] = "%Y-%m-%dT%H:%MZ"; + +// Two more digits for year and one for \n +size_t constexpr kBufSize = sizeof(kW3CTimeFormat) + 2 + 1; + +time_t constexpr kNotATime = -1; + +inline time_t ParseTime(std::string const & w3ctime) noexcept +{ + std::tm tm{}; + if (strptime(w3ctime.data(), kW3CTimeFormat, &tm) == nullptr) + return kNotATime; + + return timegm(&tm); +} + +inline std::string TimeToString(time_t const timestamp) noexcept +{ + std::tm tm{}; + array buff{}; + + gmtime_r(×tamp, &tm); + strftime(buff.data(), kBufSize, kW3CTimeFormat, &tm); + + return buff.data(); +} + +} // namespace w3ctime From f1c736614db00379ed4ace95fee793ce10746403 Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Fri, 20 Nov 2015 15:24:39 +0300 Subject: [PATCH 2/2] Code review. --- base/base.pro | 2 ++ base/base_tests/w3ctime_test.cpp | 10 ++++--- base/w3ctime.cpp | 43 +++++++++++++++++++++++++++++ base/w3ctime.hpp | 46 +++++++++----------------------- 4 files changed, 63 insertions(+), 38 deletions(-) create mode 100644 base/w3ctime.cpp diff --git a/base/base.pro b/base/base.pro index 5709bcc700..2f32121666 100644 --- a/base/base.pro +++ b/base/base.pro @@ -31,6 +31,7 @@ SOURCES += \ thread_pool.cpp \ threaded_container.cpp \ timer.cpp \ + w3ctime.cpp \ HEADERS += \ SRC_FIRST.hpp \ @@ -81,4 +82,5 @@ HEADERS += \ threaded_list.hpp \ threaded_priority_queue.hpp \ timer.hpp \ + w3ctime.hpp \ worker_thread.hpp \ diff --git a/base/base_tests/w3ctime_test.cpp b/base/base_tests/w3ctime_test.cpp index 1689734aa9..1d42f1ce32 100644 --- a/base/base_tests/w3ctime_test.cpp +++ b/base/base_tests/w3ctime_test.cpp @@ -1,12 +1,14 @@ -#include "base/w3ctime.hpp" #include "testing/testing.hpp" -using namespace w3ctime; +#include "base/w3ctime.hpp" + +using namespace base; UNIT_TEST(ParseTime) { - TEST_EQUAL(ParseTime(""), kNotATime, ()); - TEST_EQUAL(ParseTime("2015-10-11 23:21"), kNotATime, ()); + TEST(NotATime(ParseTime("")), ()); + TEST(NotATime(ParseTime("2015-10-11 23:21")), ()); + TEST(!NotATime(ParseTime("2015-10-11T23:21Z")), ()); TEST_EQUAL(ParseTime("2015-10-11T23:21Z"), 1444605660, ()); } diff --git a/base/w3ctime.cpp b/base/w3ctime.cpp new file mode 100644 index 0000000000..3d3c3c2e7f --- /dev/null +++ b/base/w3ctime.cpp @@ -0,0 +1,43 @@ +#include "w3ctime.hpp" + +#include "std/array.hpp" + +// It would be better to use c++ standard means of +// time parsing and unparsing like +// time_get/time_put () or get_time/put_time (). +// But at the moment of writing they was not widely supporded +// and/or worked incorrect. +// +// All covertions are made in UTC + +namespace +{ +char constexpr kW3CTimeFormat[] = "%Y-%m-%dT%H:%MZ"; + +// Two more digits for year. +size_t constexpr kBufSize = sizeof(kW3CTimeFormat) + 2; +} // namespace + +namespace base +{ +time_t ParseTime(std::string const & w3ctime) noexcept +{ + std::tm tm{}; + if (strptime(w3ctime.data(), kW3CTimeFormat, &tm) == nullptr) + return -1; + + return timegm(&tm); +} + +std::string TimeToString(time_t const timestamp) +{ + std::tm tm{}; + array buff{}; + + gmtime_r(×tamp, &tm); + if (strftime(buff.data(), kBufSize, kW3CTimeFormat, &tm) == 0) + buff[0] = 0; + + return buff.data(); +} +} // namespace base diff --git a/base/w3ctime.hpp b/base/w3ctime.hpp index 5bc8ae7621..60745afda9 100644 --- a/base/w3ctime.hpp +++ b/base/w3ctime.hpp @@ -1,44 +1,22 @@ #pragma once -#include "std/array.hpp" #include "std/ctime.hpp" #include "std/string.hpp" -// It would be better to use c++ standard means of -// time parsing and unparsing like -// time_get/time_put () or get_time/put_time (). -// But at the moment of writing they was not widely supporded -// and/or worked inkorekd. -// -// All covertions are made in UTC - -namespace w3ctime +namespace base { -char constexpr kW3CTimeFormat[] = "%Y-%m-%dT%H:%MZ"; -// Two more digits for year and one for \n -size_t constexpr kBufSize = sizeof(kW3CTimeFormat) + 2 + 1; +inline bool NotATime(time_t const t) noexcept { return t == -1; } -time_t constexpr kNotATime = -1; +// See http://www.w3.org/TR/NOTE-datetime to learn more +// about the format. -inline time_t ParseTime(std::string const & w3ctime) noexcept -{ - std::tm tm{}; - if (strptime(w3ctime.data(), kW3CTimeFormat, &tm) == nullptr) - return kNotATime; +// Parses a string of a format YYYY-MM-DDThh:mmTZD +// (eg 1997-07-16T19:20:30.45+01:00). +// Returns timestamp corresponding to w3ctime or -1 on failure. +time_t ParseTime(std::string const & w3ctime) noexcept; - return timegm(&tm); -} - -inline std::string TimeToString(time_t const timestamp) noexcept -{ - std::tm tm{}; - array buff{}; - - gmtime_r(×tamp, &tm); - strftime(buff.data(), kBufSize, kW3CTimeFormat, &tm); - - return buff.data(); -} - -} // namespace w3ctime +// Converts timestamp to a string of a fromat YYYY-MM-DDThh:mmTZD +// or empty string if cannot convert. +std::string TimeToString(time_t const timestamp); +} // namespace base