extend Time class with string formatters
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Tue, 30 Jan 2018 09:24:03 +0000 (10:24 +0100)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Wed, 27 Mar 2019 09:31:38 +0000 (10:31 +0100)
Add convenience member functions for the existing formatters.
Note that the make_*() group of functions all use
``localtime_r()`` internally so unit tests must be guarded by an
explicit time zone change to UTC.

src/timefunc.cpp
src/timefunc.hxx
test/test_timefunc.cpp

index 6d4b365..0abdfcb 100644 (file)
@@ -1011,6 +1011,37 @@ namespace clock {
         return *this;
     }
 
+    boost::optional<std::string>
+    Time::format_iso8601 (const bool utc,
+                          const bool date,
+                          const bool time,
+                          const bool tz) const
+    {
+        time_breakdown_fn breakdown = utc ? gmtime_r : localtime_r;
+        struct tm tm;
+
+        if (breakdown (&this->value.tv_sec, &tm) == NULL) {
+            return boost::none;
+        }
+
+        return ::format_iso8601 (tm, date, time, tz);
+    }
+
+    boost::optional<std::string>
+    Time::make_nice_time (void) const
+    {
+        /* XXX the cast below results in loss of precision with 64 bit time_t! */
+        return ::make_nice_time (static_cast<int> (this->value.tv_sec));
+    }
+
+    boost::optional<std::string>
+    Time::format_full_time (void) const
+    { return ::format_full_time (this->value.tv_sec); }
+
+    boost::optional<std::string>
+    Time::format_date (void) const
+    { return ::format_date (this->value.tv_sec); }
+
     boost::optional<Time>
     now (const enum type::id id, const enum type::variant var) NOEXCEPT
     {
index 74c16e4..1b9df92 100644 (file)
@@ -494,6 +494,19 @@ namespace clock {
             friend std::ostream &
             operator<< (std::ostream &os, const Time &t);
 
+        /* formatting ********************************************************/
+        public:
+
+            boost::optional<std::string>
+            format_iso8601 (const bool utc  = true,
+                            const bool date = true,
+                            const bool time = true,
+                            const bool tz   = true) const;
+
+            boost::optional<std::string> make_nice_time (void) const;
+            boost::optional<std::string> format_full_time (void) const;
+            boost::optional<std::string> format_date (void) const;
+
     }; /* [class Time] */
 
     inline Time 
index 658950d..e5b4adf 100644 (file)
@@ -997,6 +997,60 @@ BOOST_AUTO_TEST_SUITE(Clock)
         BOOST_CHECK_EQUAL(ts.size (), 2);
     }
 
+    BOOST_AUTO_TEST_CASE(FormatISO8601_T)
+    {
+        I2n::clock::Time t (42, 42);
+        boost::optional<std::string> s = t.format_iso8601 (true, false, true, false);
+
+        BOOST_CHECK_EQUAL("00:00:42", *s);
+    }
+
+    BOOST_AUTO_TEST_CASE(FormatISO8601_DT)
+    {
+        I2n::clock::Time t (1541934671, 0);
+        boost::optional<std::string> s = t.format_iso8601 (true, true, true, false);
+
+        BOOST_CHECK_EQUAL("2018-11-11T11:11:11", *s);
+    }
+
+    BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ)
+    {
+        I2n::clock::Time t (1541934671, 0);
+        boost::optional<std::string> s = t.format_iso8601 (true, true, true, true);
+
+        BOOST_CHECK_EQUAL("2018-11-11T11:11:11Z+0000", *s);
+    }
+
+    BOOST_AUTO_TEST_CASE(Format_make_nice_time)
+    {
+        I2n::clock::Time t (111111, 0);
+        boost::optional<std::string> s = t.make_nice_time ();
+
+        BOOST_CHECK_EQUAL("1 day, 06:51:51", *s);
+    }
+
+    BOOST_AUTO_TEST_CASE(Format_format_full_time)
+    {
+        I2n::clock::Time t (1541934671, 0);
+        /*
+         * brr, the old formatters use localtime without a way to opt out of
+         * it!
+         */
+        setenv ("TZ", "UTC", 1);
+        tzset();
+        boost::optional<std::string> s = t.format_full_time ();
+
+        BOOST_CHECK_EQUAL("11.11.2018 11:11", *s);
+    }
+
+    BOOST_AUTO_TEST_CASE(Format_format_date)
+    {
+        I2n::clock::Time t (1541934671, 0);
+        boost::optional<std::string> s = t.format_date ();
+
+        BOOST_CHECK_EQUAL("11.11.2018", *s);
+    }
+
 BOOST_AUTO_TEST_SUITE_END() /* [Clock] */
 
 BOOST_AUTO_TEST_SUITE_END()