Add DateTime::exactGmtNow()

* Provides more precise wall-clock time
* Only available under UNIX so far
This commit is contained in:
Martchus 2017-04-19 21:48:23 +02:00
parent ead0fadac3
commit 452954dc1f
3 changed files with 39 additions and 2 deletions

View File

@ -7,6 +7,10 @@
#include <iomanip>
#include <stdexcept>
#if defined(PLATFORM_UNIX)
# include <time.h>
#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<uint64>(t.tv_sec) * TimeSpan::ticksPerSecond + static_cast<uint64>(t.tv_nsec) / 100);
}
#endif
/*!
* \brief Converts the given date expressed in \a year, \a month and \a day to ticks.
*/

View File

@ -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<decltype(m_ticks)>::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()
{

View File

@ -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
}
/*!