util: add time::{to,from}IsoExtendedString()

Also, backport weeks/months/years duration types from C++20

Change-Id: I6d5c831b7aa2ffa3a894a8adaba0e3879d84ef61
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");