From 452954dc1f375aeedbccade53188b4a8b6ad82f1 Mon Sep 17 00:00:00 2001 From: Martchus Date: Wed, 19 Apr 2017 21:48:23 +0200 Subject: [PATCH] Add DateTime::exactGmtNow() * Provides more precise wall-clock time * Only available under UNIX so far --- chrono/datetime.cpp | 21 +++++++++++++++++++-- chrono/datetime.h | 14 ++++++++++++++ tests/chronotests.cpp | 6 ++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/chrono/datetime.cpp b/chrono/datetime.cpp index a5cdce3..ef5c50c 100644 --- a/chrono/datetime.cpp +++ b/chrono/datetime.cpp @@ -7,6 +7,10 @@ #include #include +#if defined(PLATFORM_UNIX) +# include +#endif + using namespace std; using namespace ChronoUtilities; using namespace ConversionUtilities; @@ -49,7 +53,7 @@ inline bool inRangeExclMax(num1 val, num2 min, num3 max) */ /*! - * \brief Constructs a new DateTime object with the local time from the specified \a timeStamp. + * \brief Constructs a new DateTime object with the local time from the specified UNIX \a timeStamp. */ DateTime DateTime::fromTimeStamp(time_t timeStamp) { @@ -63,7 +67,7 @@ DateTime DateTime::fromTimeStamp(time_t timeStamp) } /*! - * \brief Constructs a new DateTime object with the GMT time from the specified \a timeStamp. + * \brief Constructs a new DateTime object with the GMT time from the specified UNIX \a timeStamp. */ DateTime DateTime::fromTimeStampGmt(time_t timeStamp) { @@ -286,6 +290,19 @@ const char *DateTime::printDayOfWeek(DayOfWeek dayOfWeek, bool abbreviation) return ""; } +#if defined(PLATFORM_UNIX) +/*! + * \brief Returns a DateTime object that is set to the current date and time on this computer, expressed as the GMT time. + * \remarks + */ +DateTime DateTime::exactGmtNow() +{ + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return DateTime(DateTime::unixEpochStart().totalTicks() + static_cast(t.tv_sec) * TimeSpan::ticksPerSecond + static_cast(t.tv_nsec) / 100); +} +#endif + /*! * \brief Converts the given date expressed in \a year, \a month and \a day to ticks. */ diff --git a/chrono/datetime.h b/chrono/datetime.h index a7fc363..1d98bc8 100644 --- a/chrono/datetime.h +++ b/chrono/datetime.h @@ -89,8 +89,12 @@ public: static const char *printDayOfWeek(DayOfWeek dayOfWeek, bool abbreviation = false); static constexpr DateTime eternity(); + static constexpr DateTime unixEpochStart(); static DateTime now(); static DateTime gmtNow(); +#if defined(PLATFORM_UNIX) + static DateTime exactGmtNow(); +#endif constexpr static bool isLeapYear(int year); static int daysInMonth(int year, int month); @@ -352,8 +356,17 @@ constexpr inline DateTime DateTime::eternity() return DateTime(std::numeric_limits::max()); } +/*! + * \brief Returns the DateTime object for the "1970-01-01T00:00:00Z". + */ +constexpr inline DateTime DateTime::unixEpochStart() +{ + return DateTime(621355968000000000); +} + /*! * \brief Returns a DateTime object that is set to the current date and time on this computer, expressed as the local time. + * \remarks The time might be rounded to full seconds. Use exactGmtNow() for better precision. */ inline DateTime DateTime::now() { @@ -362,6 +375,7 @@ inline DateTime DateTime::now() /*! * \brief Returns a DateTime object that is set to the current date and time on this computer, expressed as the GMT time. + * \remarks The time might be rounded to full seconds. Use exactGmtNow() for better precision. */ inline DateTime DateTime::gmtNow() { diff --git a/tests/chronotests.cpp b/tests/chronotests.cpp index 68d46b1..c7c3726 100644 --- a/tests/chronotests.cpp +++ b/tests/chronotests.cpp @@ -71,6 +71,12 @@ void ChronoTests::testDateTime() CPPUNIT_ASSERT_THROW(TimeSpan::fromString("2012-02-29 15:34:34:20.033"), ConversionException); const auto test3 = DateTime::fromIsoString("2016-08-29T21:32:31.125+02:00"); CPPUNIT_ASSERT_EQUAL("2016-08-29T21:32:31.125+02:00"s, test3.first.toIsoString(test3.second)); + + // test now() and exactNow() (or at least whether both behave the same) +#if defined(PLATFORM_UNIX) + const auto delta = DateTime::gmtNow() - DateTime::exactGmtNow(); + CPPUNIT_ASSERT(delta < TimeSpan::fromSeconds(2) && delta > TimeSpan::fromSeconds(-2)); +#endif } /*!