Improve DateTime
* Improve documentation about time zone handling * Add DateTime::toTimeStamp() * Add experimental DateTime::fromChronoTimePoint() and DateTime::fromChronoTimePointGmt()
This commit is contained in:
parent
83180119c2
commit
085ec2feca
|
@ -39,12 +39,13 @@ template <typename num1, typename num2, typename num3> constexpr bool inRangeExc
|
||||||
* \remarks
|
* \remarks
|
||||||
* - Time values are measured in 100-nanosecond units called ticks,
|
* - Time values are measured in 100-nanosecond units called ticks,
|
||||||
* and a particular date is the number of ticks since 12:00 midnight, January 1,
|
* and a particular date is the number of ticks since 12:00 midnight, January 1,
|
||||||
* 0001 A.D. (C.E.) in the GregorianCalendar calendar (excluding ticks that would
|
* 0001 A.D. (C.E.) in the Gregorian Calendar (excluding ticks that would be added by leap seconds).
|
||||||
* be added by leap seconds).
|
* - There is no time zone information associated. You need to keep track of the used time zone separately. That can
|
||||||
* - There is no time zone information associated. Hence different time zones are
|
* be done by keeping an additional TimeSpan around which represents the delta to GMT or by simply using GMT everywhere
|
||||||
* not taken into account when comparing two instances. For instance, the
|
* in the program.
|
||||||
* expression (DateTime::now() - DateTime::gmtNow()) returns one hour in Germany during winter
|
* - When constructing an instance via DateTime::fromTimeStamp(), DateTime::fromChronoTimePoint() or DateTime::fromIsoStringLocal()
|
||||||
* time (instead of zero).
|
* the time zone deltas are "baked into" the DateTime instance. For instance, the expression (DateTime::now() - DateTime::gmtNow())
|
||||||
|
* returns one hour in Germany during winter time (and *not* zero although both instances represent the current time).
|
||||||
* \todo
|
* \todo
|
||||||
* - Add method for parsing custom string formats.
|
* - Add method for parsing custom string formats.
|
||||||
* - Add method for printing to custom string formats.
|
* - Add method for printing to custom string formats.
|
||||||
|
|
|
@ -60,8 +60,10 @@ public:
|
||||||
static std::pair<DateTime, TimeSpan> fromIsoString(const char *str);
|
static std::pair<DateTime, TimeSpan> fromIsoString(const char *str);
|
||||||
static DateTime fromIsoStringGmt(const char *str);
|
static DateTime fromIsoStringGmt(const char *str);
|
||||||
static DateTime fromIsoStringLocal(const char *str);
|
static DateTime fromIsoStringLocal(const char *str);
|
||||||
static DateTime fromTimeStamp(time_t timeStamp);
|
static DateTime fromTimeStamp(std::time_t timeStamp);
|
||||||
constexpr static DateTime fromTimeStampGmt(time_t timeStamp);
|
constexpr static DateTime fromTimeStampGmt(std::time_t timeStamp);
|
||||||
|
template <typename TimePoint> static DateTime fromChronoTimePoint(TimePoint timePoint);
|
||||||
|
template <typename TimePoint> constexpr static DateTime fromChronoTimePointGmt(TimePoint timePoint);
|
||||||
|
|
||||||
constexpr std::uint64_t &ticks();
|
constexpr std::uint64_t &ticks();
|
||||||
constexpr std::uint64_t totalTicks() const;
|
constexpr std::uint64_t totalTicks() const;
|
||||||
|
@ -84,6 +86,7 @@ public:
|
||||||
std::string toString(DateTimeOutputFormat format = DateTimeOutputFormat::DateAndTime, bool noMilliseconds = false) const;
|
std::string toString(DateTimeOutputFormat format = DateTimeOutputFormat::DateAndTime, bool noMilliseconds = false) const;
|
||||||
void toString(std::string &result, DateTimeOutputFormat format = DateTimeOutputFormat::DateAndTime, bool noMilliseconds = false) const;
|
void toString(std::string &result, DateTimeOutputFormat format = DateTimeOutputFormat::DateAndTime, bool noMilliseconds = false) const;
|
||||||
std::string toIsoString(TimeSpan timeZoneDelta = TimeSpan()) const;
|
std::string toIsoString(TimeSpan timeZoneDelta = TimeSpan()) const;
|
||||||
|
constexpr std::time_t toTimeStamp() const;
|
||||||
static const char *printDayOfWeek(DayOfWeek dayOfWeek, bool abbreviation = false);
|
static const char *printDayOfWeek(DayOfWeek dayOfWeek, bool abbreviation = false);
|
||||||
|
|
||||||
static constexpr DateTime eternity();
|
static constexpr DateTime eternity();
|
||||||
|
@ -220,6 +223,26 @@ constexpr inline DateTime DateTime::fromTimeStampGmt(std::time_t timeStamp)
|
||||||
return DateTime(DateTime::unixEpochStart().totalTicks() + static_cast<std::uint64_t>(timeStamp) * TimeSpan::ticksPerSecond);
|
return DateTime(DateTime::unixEpochStart().totalTicks() + static_cast<std::uint64_t>(timeStamp) * TimeSpan::ticksPerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a new DateTime object with the local time from the specified std::chrono::time_point.
|
||||||
|
* \remarks Works only with time points of std::chrono::system_clock so far. C++20 will fix this. Until then this function
|
||||||
|
* should be considered experimental.
|
||||||
|
*/
|
||||||
|
template <typename TimePoint> inline DateTime DateTime::fromChronoTimePoint(TimePoint timePoint)
|
||||||
|
{
|
||||||
|
return DateTime::fromTimeStamp(decltype(timePoint)::clock::to_time_t(timePoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a new DateTime object with the GMT time from the specified std::chrono::time_point.
|
||||||
|
* \remarks Works only with time points of std::chrono::system_clock so far. C++20 will fix this. Until then this function
|
||||||
|
* should be considered experimental.
|
||||||
|
*/
|
||||||
|
template <typename TimePoint> constexpr DateTime DateTime::fromChronoTimePointGmt(TimePoint timePoint)
|
||||||
|
{
|
||||||
|
return DateTime::fromTimeStampGmt(decltype(timePoint)::clock::to_time_t(timePoint));
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns a mutable reference to the total ticks.
|
* \brief Returns a mutable reference to the total ticks.
|
||||||
*/
|
*/
|
||||||
|
@ -396,6 +419,14 @@ inline std::string DateTime::toString(DateTimeOutputFormat format, bool noMillis
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the UNIX timestamp for the current instance.
|
||||||
|
*/
|
||||||
|
constexpr std::time_t DateTime::toTimeStamp() const
|
||||||
|
{
|
||||||
|
return (totalTicks() - DateTime::unixEpochStart().totalTicks()) / TimeSpan::ticksPerSecond;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Constructs a new instance of the DateTime class with the maximal number of ticks.
|
* \brief Constructs a new instance of the DateTime class with the maximal number of ticks.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <cppunit/TestFixture.h>
|
#include <cppunit/TestFixture.h>
|
||||||
#include <cppunit/extensions/HelperMacros.h>
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -114,11 +115,17 @@ void ChronoTests::testDateTime()
|
||||||
CPPUNIT_ASSERT(!test1.isSameDay(test1 + TimeSpan::fromHours(9)));
|
CPPUNIT_ASSERT(!test1.isSameDay(test1 + TimeSpan::fromHours(9)));
|
||||||
CPPUNIT_ASSERT_EQUAL("Wed 2012-02-29 15:34:20.033"s, test1.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
|
CPPUNIT_ASSERT_EQUAL("Wed 2012-02-29 15:34:20.033"s, test1.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
|
||||||
|
|
||||||
// test fromTimeStamp()
|
// test fromTimeStamp()/toTimeStamp()
|
||||||
const auto fromTimeStampGmt = DateTime::fromTimeStampGmt(1453840331), fromTimeStamp = DateTime::fromTimeStamp(1453840331);
|
const auto timeStamp = static_cast<time_t>(1453840331);
|
||||||
|
const auto fromTimeStampGmt = DateTime::fromTimeStampGmt(timeStamp), fromTimeStamp = DateTime::fromTimeStamp(timeStamp);
|
||||||
CPPUNIT_ASSERT_EQUAL("Tue 2016-01-26 20:32:11"s, fromTimeStampGmt.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
|
CPPUNIT_ASSERT_EQUAL("Tue 2016-01-26 20:32:11"s, fromTimeStampGmt.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
|
||||||
CPPUNIT_ASSERT(fabs((fromTimeStamp - fromTimeStampGmt).totalDays()) <= 1.0);
|
CPPUNIT_ASSERT(fabs((fromTimeStamp - fromTimeStampGmt).totalDays()) <= 1.0);
|
||||||
CPPUNIT_ASSERT_EQUAL(DateTime(), DateTime::fromTimeStamp(0));
|
CPPUNIT_ASSERT_EQUAL(DateTime(), DateTime::fromTimeStamp(0));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(timeStamp, fromTimeStampGmt.toTimeStamp());
|
||||||
|
|
||||||
|
// test fromChronoTimePointGmt()
|
||||||
|
const auto fromChronoTimePointGmt = DateTime::fromChronoTimePointGmt(chrono::system_clock::from_time_t(timeStamp));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("Tue 2016-01-26 20:32:11"s, fromChronoTimePointGmt.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
|
||||||
|
|
||||||
// test whether ConversionException() is thrown when invalid values are specified
|
// test whether ConversionException() is thrown when invalid values are specified
|
||||||
CPPUNIT_ASSERT_THROW(DateTime::fromDate(0, 1, 1), ConversionException);
|
CPPUNIT_ASSERT_THROW(DateTime::fromDate(0, 1, 1), ConversionException);
|
||||||
|
|
Loading…
Reference in New Issue