util: add time::{to,from}IsoExtendedString()
Also, backport weeks/months/years duration types from C++20
Change-Id: I6d5c831b7aa2ffa3a894a8adaba0e3879d84ef61
diff --git a/docs/doxygen.conf.in b/docs/doxygen.conf.in
index d70ac1c..82513e4 100644
--- a/docs/doxygen.conf.in
+++ b/docs/doxygen.conf.in
@@ -437,7 +437,7 @@
# included in the documentation.
# The default value is: NO.
-EXTRACT_STATIC = YES
+EXTRACT_STATIC = NO
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO,
@@ -1041,13 +1041,6 @@
ALPHABETICAL_INDEX = YES
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX = 5
-
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
diff --git a/ndn-cxx/util/time.cpp b/ndn-cxx/util/time.cpp
index 3f4f9db..e233ca5 100644
--- a/ndn-cxx/util/time.cpp
+++ b/ndn-cxx/util/time.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -102,27 +102,27 @@
/////////////////////////////////////////////////////////////////////////////////////////////
-const system_clock::TimePoint&
+const system_clock::time_point&
getUnixEpoch()
{
- static constexpr system_clock::TimePoint epoch(seconds::zero());
+ static constexpr system_clock::time_point epoch(seconds::zero());
return epoch;
}
milliseconds
-toUnixTimestamp(const system_clock::TimePoint& point)
+toUnixTimestamp(const system_clock::time_point& point)
{
return duration_cast<milliseconds>(point - getUnixEpoch());
}
-system_clock::TimePoint
+system_clock::time_point
fromUnixTimestamp(milliseconds duration)
{
return getUnixEpoch() + duration;
}
static boost::posix_time::ptime
-convertToPosixTime(const system_clock::TimePoint& timePoint)
+convertToPosixTime(const system_clock::time_point& timePoint)
{
namespace bpt = boost::posix_time;
static bpt::ptime epoch(boost::gregorian::date(1970, 1, 1));
@@ -140,12 +140,18 @@
}
std::string
-toIsoString(const system_clock::TimePoint& timePoint)
+toIsoString(const system_clock::time_point& timePoint)
{
return boost::posix_time::to_iso_string(convertToPosixTime(timePoint));
}
-static system_clock::TimePoint
+std::string
+toIsoExtendedString(const system_clock::time_point& timePoint)
+{
+ return boost::posix_time::to_iso_extended_string(convertToPosixTime(timePoint));
+}
+
+static system_clock::time_point
convertToTimePoint(const boost::posix_time::ptime& ptime)
{
namespace bpt = boost::posix_time;
@@ -154,18 +160,24 @@
// .total_seconds() has an issue with large dates until Boost 1.66, see #4478.
// time_t overflows for large dates on 32-bit platforms (Y2038 problem).
auto sinceEpoch = ptime - epoch;
- auto point = system_clock::TimePoint(seconds(sinceEpoch.ticks() / bpt::time_duration::ticks_per_second()));
+ auto point = system_clock::time_point(seconds(sinceEpoch.ticks() / bpt::time_duration::ticks_per_second()));
return point + microseconds(sinceEpoch.total_microseconds() % 1000000);
}
-system_clock::TimePoint
+system_clock::time_point
fromIsoString(const std::string& isoString)
{
return convertToTimePoint(boost::posix_time::from_iso_string(isoString));
}
+system_clock::time_point
+fromIsoExtendedString(const std::string& isoString)
+{
+ return convertToTimePoint(boost::posix_time::from_iso_extended_string(isoString));
+}
+
std::string
-toString(const system_clock::TimePoint& timePoint,
+toString(const system_clock::time_point& timePoint,
const std::string& format/* = "%Y-%m-%d %H:%M:%S"*/,
const std::locale& locale/* = std::locale("C")*/)
{
@@ -179,7 +191,7 @@
return os.str();
}
-system_clock::TimePoint
+system_clock::time_point
fromString(const std::string& timePointStr,
const std::string& format/* = "%Y-%m-%d %H:%M:%S"*/,
const std::locale& locale/* = std::locale("C")*/)
diff --git a/ndn-cxx/util/time.hpp b/ndn-cxx/util/time.hpp
index 1e7221f..0d55431 100644
--- a/ndn-cxx/util/time.hpp
+++ b/ndn-cxx/util/time.hpp
@@ -30,16 +30,24 @@
namespace ndn {
namespace time {
-using boost::chrono::duration;
+template<typename Rep, typename Period>
+using duration = boost::chrono::duration<Rep, Period>;
+
using boost::chrono::duration_cast;
-using days = duration<int_fast32_t, boost::ratio<86400>>;
-using boost::chrono::hours;
-using boost::chrono::minutes;
-using boost::chrono::seconds;
-using boost::chrono::milliseconds;
-using boost::chrono::microseconds;
-using boost::chrono::nanoseconds;
+// C++20
+using days = duration<int_fast32_t, boost::ratio<86400>>;
+using weeks = duration<int_fast32_t, boost::ratio<604800>>;
+using months = duration<int_fast32_t, boost::ratio<2629746>>;
+using years = duration<int_fast32_t, boost::ratio<31556952>>;
+
+// C++11
+using hours = boost::chrono::hours;
+using minutes = boost::chrono::minutes;
+using seconds = boost::chrono::seconds;
+using milliseconds = boost::chrono::milliseconds;
+using microseconds = boost::chrono::microseconds;
+using nanoseconds = boost::chrono::nanoseconds;
/** \return the absolute value of the duration d
* \note The function does not participate in the overload resolution
@@ -172,15 +180,15 @@
* To get the current time:
*
* <code>
- * system_clock::TimePoint now = system_clock::now();
+ * const auto now = system_clock::now();
* </code>
*
- * To convert a TimePoint to/from UNIX timestamp:
+ * To convert a time_point to/from UNIX timestamp:
*
* <code>
- * system_clock::TimePoint time = ...;
+ * system_clock::time_point time = ...;
* uint64_t timestampInMilliseconds = toUnixTimestamp(time).count();
- * system_clock::TimePoint time2 = fromUnixTimestamp(milliseconds(timestampInMilliseconds));
+ * system_clock::time_point time2 = fromUnixTimestamp(milliseconds(timestampInMilliseconds));
* </code>
*/
class system_clock
@@ -192,8 +200,8 @@
using time_point = boost::chrono::time_point<system_clock>;
static constexpr bool is_steady = boost::chrono::system_clock::is_steady;
- typedef time_point TimePoint;
- typedef duration Duration;
+ using TimePoint = time_point;
+ using Duration = duration;
static time_point
now() noexcept;
@@ -222,8 +230,8 @@
using time_point = boost::chrono::time_point<steady_clock>;
static constexpr bool is_steady = true;
- typedef time_point TimePoint;
- typedef duration Duration;
+ using TimePoint = time_point;
+ using Duration = duration;
static time_point
now() noexcept;
@@ -244,28 +252,28 @@
};
/**
- * \brief Get system_clock::TimePoint representing UNIX time epoch (00:00:00 on Jan 1, 1970)
+ * \brief Return a system_clock::time_point representing the UNIX time epoch,
+ * i.e., 00:00:00 UTC on 1 January 1970.
*/
-const system_clock::TimePoint&
+const system_clock::time_point&
getUnixEpoch();
/**
- * \brief Convert system_clock::TimePoint to UNIX timestamp
+ * \brief Convert system_clock::time_point to UNIX timestamp
*/
milliseconds
-toUnixTimestamp(const system_clock::TimePoint& point);
+toUnixTimestamp(const system_clock::time_point& point);
/**
- * \brief Convert UNIX timestamp to system_clock::TimePoint
+ * \brief Convert UNIX timestamp to system_clock::time_point
*/
-system_clock::TimePoint
+system_clock::time_point
fromUnixTimestamp(milliseconds duration);
/**
- * \brief Convert to the ISO string representation of the time (YYYYMMDDTHHMMSS,fffffffff)
+ * \brief Convert to the ISO 8601 string representation, basic format (`YYYYMMDDTHHMMSS,fffffffff`).
*
- * If \p timePoint contains doesn't contain fractional seconds,
- * the output format is YYYYMMDDTHHMMSS
+ * If \p timePoint does not contain any fractional seconds, the output format is `YYYYMMDDTHHMMSS`.
*
* Examples:
*
@@ -275,25 +283,37 @@
* - without fractional seconds: 20020131T100001
*/
std::string
-toIsoString(const system_clock::TimePoint& timePoint);
+toIsoString(const system_clock::time_point& timePoint);
/**
- * \brief Convert from the ISO string (YYYYMMDDTHHMMSS,fffffffff) representation
- * to the internal time format
+ * \brief Convert from the ISO 8601 basic string format (`YYYYMMDDTHHMMSS,fffffffff`)
+ * to the internal time format.
*
- * Examples of accepted ISO strings:
+ * Examples of accepted strings:
*
* - with fractional nanoseconds: 20020131T100001,123456789
* - with fractional microseconds: 20020131T100001,123456
* - with fractional milliseconds: 20020131T100001,123
* - without fractional seconds: 20020131T100001
- *
*/
-system_clock::TimePoint
+system_clock::time_point
fromIsoString(const std::string& isoString);
/**
- * \brief Convert time point to string with specified format
+ * \brief Convert to the ISO 8601 string representation, extended format (`YYYY-MM-DDTHH:MM:SS,fffffffff`).
+ */
+std::string
+toIsoExtendedString(const system_clock::time_point& timePoint);
+
+/**
+ * \brief Convert from the ISO 8601 extended string format (`YYYY-MM-DDTHH:MM:SS,fffffffff`)
+ * to the internal time format.
+ */
+system_clock::time_point
+fromIsoExtendedString(const std::string& isoString);
+
+/**
+ * \brief Convert time point to string with specified format.
*
* By default, `%Y-%m-%d %H:%M:%S` is used, producing dates like
* `2014-04-10 22:51:00`
@@ -306,12 +326,12 @@
* describes possible formatting flags
**/
std::string
-toString(const system_clock::TimePoint& timePoint,
+toString(const system_clock::time_point& timePoint,
const std::string& format = "%Y-%m-%d %H:%M:%S",
const std::locale& locale = std::locale("C"));
/**
- * \brief Convert from string of specified format into time point
+ * \brief Convert from string of specified format into time point.
*
* By default, `%Y-%m-%d %H:%M:%S` is used, accepting dates like
* `2014-04-10 22:51:00`
@@ -323,7 +343,7 @@
* \sa https://www.boost.org/doc/libs/1_65_1/doc/html/date_time/date_time_io.html#date_time.format_flags
* describes possible formatting flags
*/
-system_clock::TimePoint
+system_clock::time_point
fromString(const std::string& timePointStr,
const std::string& format = "%Y-%m-%d %H:%M:%S",
const std::locale& locale = std::locale("C"));
@@ -334,14 +354,14 @@
namespace boost {
namespace chrono {
-template<class CharT>
+template<typename CharT>
struct clock_string<ndn::time::system_clock, CharT>
{
static std::basic_string<CharT>
since();
};
-template<class CharT>
+template<typename CharT>
struct clock_string<ndn::time::steady_clock, CharT>
{
static std::basic_string<CharT>
diff --git a/tests/unit/util/time.t.cpp b/tests/unit/util/time.t.cpp
index 92699a9..2232e12 100644
--- a/tests/unit/util/time.t.cpp
+++ b/tests/unit/util/time.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -33,14 +33,63 @@
BOOST_AUTO_TEST_SUITE(Util)
BOOST_AUTO_TEST_SUITE(TestTime)
+BOOST_AUTO_TEST_CASE(Duration)
+{
+ BOOST_TEST(years(1) == months(12));
+ BOOST_TEST(months(1) == minutes(43829) + seconds(6));
+ BOOST_TEST(weeks(1) == days(7));
+ BOOST_TEST(days(1) == hours(24));
+ BOOST_TEST(hours(1) == minutes(60));
+ BOOST_TEST(minutes(1) == seconds(60));
+ BOOST_TEST(seconds(1) == milliseconds(1000));
+ BOOST_TEST(milliseconds(1) == microseconds(1000));
+ BOOST_TEST(microseconds(1) == nanoseconds(1000));
+}
+
+BOOST_AUTO_TEST_CASE(Abs)
+{
+ BOOST_TEST(abs(nanoseconds(24422)) == nanoseconds(24422));
+ BOOST_TEST(abs(microseconds(0)) == microseconds(0));
+ BOOST_TEST(abs(milliseconds(-15583)) == milliseconds(15583));
+}
+
+BOOST_AUTO_TEST_CASE(Literals)
+{
+ BOOST_TEST(42_s == seconds(42));
+
+ BOOST_TEST(1_day == 24_h);
+ BOOST_TEST(2_days == 48_h);
+ BOOST_TEST(0.5_day == 12_h);
+ BOOST_TEST(.5_days == 12_h);
+
+ BOOST_TEST(1_h == 60_min);
+ BOOST_TEST(0.5_h == 30_min);
+
+ BOOST_TEST(1_min == 60_s);
+ BOOST_TEST(0.5_min == 30_s);
+
+ BOOST_TEST(1_s == 1000_ms);
+ BOOST_TEST(0.5_s == 500_ms);
+
+ BOOST_TEST(1_ms == 1000_us);
+ BOOST_TEST(0.5_ms == 500_us);
+
+ BOOST_TEST(1_us == 1000_ns);
+ BOOST_TEST(0.5_us == 500_ns);
+
+ BOOST_TEST(1_ns == nanoseconds(1));
+ BOOST_TEST(5.5_ns == 0.0055_us);
+}
+
BOOST_AUTO_TEST_CASE(SystemClock)
{
- system_clock::TimePoint value = system_clock::now();
- system_clock::TimePoint referenceTime = fromUnixTimestamp(1390966967032_ms);
+ system_clock::time_point value = system_clock::now();
+ system_clock::time_point referenceTime = fromUnixTimestamp(1390966967032_ms);
BOOST_TEST(value > referenceTime);
BOOST_CHECK_EQUAL(toIsoString(referenceTime), "20140129T034247.032000");
+ BOOST_CHECK_EQUAL(toIsoExtendedString(referenceTime), "2014-01-29T03:42:47.032000");
BOOST_CHECK_EQUAL(toString(referenceTime), "2014-01-29 03:42:47");
// Unfortunately, not all systems has lv_LV locale installed :(
@@ -53,6 +102,10 @@
BOOST_TEST(fromIsoString("20140129T034247.032000Z") == referenceTime);
BOOST_TEST(fromIsoString("20140129T034247") != referenceTime);
BOOST_TEST(fromIsoString("20140129T034247") == fromUnixTimestamp(1390966967_s));
+ BOOST_TEST(fromIsoExtendedString("2014-01-29T03:42:47.032000") == referenceTime);
+ BOOST_TEST(fromIsoExtendedString("2014-01-29T03:42:47.032000Z") == referenceTime);
+ BOOST_TEST(fromIsoExtendedString("2014-01-29T03:42:47") != referenceTime);
+ BOOST_TEST(fromIsoExtendedString("2014-01-29T03:42:47") == fromUnixTimestamp(1390966967_s));
BOOST_TEST(fromString("2014-01-29 03:42:47") != referenceTime);
BOOST_TEST(fromString("2014-01-29 03:42:47") == fromUnixTimestamp(1390966967_s));
@@ -65,9 +118,9 @@
BOOST_AUTO_TEST_CASE(SteadyClock)
{
- steady_clock::TimePoint oldValue = steady_clock::now();
+ steady_clock::time_point oldValue = steady_clock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
- steady_clock::TimePoint newValue = steady_clock::now();
+ steady_clock::time_point newValue = steady_clock::now();
BOOST_CHECK_GT(newValue, oldValue);
}
@@ -78,19 +131,15 @@
tp += 1596592240_s;
BOOST_TEST(toIsoString(tp) == "20200805T015040");
+ BOOST_TEST(toIsoExtendedString(tp) == "2020-08-05T01:50:40");
BOOST_TEST(toString(tp) == "2020-08-05 01:50:40");
BOOST_TEST(fromIsoString("20200805T015040") == tp);
BOOST_TEST(fromIsoString("20200805T015040.123456") != tp);
+ BOOST_TEST(fromIsoExtendedString("2020-08-05T01:50:40") == tp);
+ BOOST_TEST(fromIsoExtendedString("2020-08-05T01:50:40.123456") != tp);
BOOST_TEST(fromString("2020-08-05 01:50:40") == tp);
}
-BOOST_AUTO_TEST_CASE(Abs)
-{
- BOOST_CHECK_EQUAL(abs(nanoseconds(24422)), nanoseconds(24422));
- BOOST_CHECK_EQUAL(abs(microseconds(0)), microseconds(0));
- BOOST_CHECK_EQUAL(abs(milliseconds(-15583)), milliseconds(15583));
-}
-
BOOST_AUTO_TEST_CASE(LargeDates)
{
auto value = fromUnixTimestamp(1390966967032_ms);
@@ -106,34 +155,6 @@
BOOST_CHECK_EQUAL(fromString("2114-01-29 03:42:47.03200", "%Y-%m-%d %H:%M:%S%F"), value);
}
-BOOST_AUTO_TEST_CASE(Literals)
-{
- BOOST_CHECK_EQUAL(42_s, seconds(42));
-
- BOOST_CHECK_EQUAL(1_day, 24_h);
- BOOST_CHECK_EQUAL(2_days, 48_h);
- BOOST_CHECK_EQUAL(0.5_day, 12_h);
- BOOST_CHECK_EQUAL(.5_days, 12_h);
-
- BOOST_CHECK_EQUAL(1_h, 60_min);
- BOOST_CHECK_EQUAL(0.5_h, 30_min);
-
- BOOST_CHECK_EQUAL(1_min, 60_s);
- BOOST_CHECK_EQUAL(0.5_min, 30_s);
-
- BOOST_CHECK_EQUAL(1_s, 1000_ms);
- BOOST_CHECK_EQUAL(0.5_s, 500_ms);
-
- BOOST_CHECK_EQUAL(1_ms, 1000_us);
- BOOST_CHECK_EQUAL(0.5_ms, 500_us);
-
- BOOST_CHECK_EQUAL(1_us, 1000_ns);
- BOOST_CHECK_EQUAL(0.5_us, 500_ns);
-
- BOOST_CHECK_EQUAL(1_ns, nanoseconds(1));
- BOOST_CHECK_EQUAL(5.5_ns, 0.0055_us);
-}
-
BOOST_AUTO_TEST_CASE(Year2038)
{
auto year2042 = fromIsoString("20420101T000001.042000");