diff options
-rw-r--r-- | libbutl/timestamp.cxx | 28 | ||||
-rw-r--r-- | libbutl/timestamp.mxx | 10 | ||||
-rw-r--r-- | tests/timestamp/driver.cxx | 12 |
3 files changed, 50 insertions, 0 deletions
diff --git a/libbutl/timestamp.cxx b/libbutl/timestamp.cxx index 296e070..0242758 100644 --- a/libbutl/timestamp.cxx +++ b/libbutl/timestamp.cxx @@ -662,4 +662,32 @@ namespace butl return system_clock::from_time_t (time) + chrono::duration_cast<duration> (t.second); } + + duration + daytime (timestamp t) + { + // Convert the time from Epoch to the local time. + // + time_t time (system_clock::to_time_t (t)); + + std::tm tm; + if (details::localtime (&time, &tm) == nullptr) + throw_generic_error (errno); + + // Roll the time back to the latest midnight. + // + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + + // Convert the local midnight to time from Epoch. + // + time = mktime (&tm); + if (time == -1) + throw_generic_error (errno); + + // Note: preserves the accuracy of the original time. + // + return t - system_clock::from_time_t (time); + } } diff --git a/libbutl/timestamp.mxx b/libbutl/timestamp.mxx index f4a06f9..9525ec0 100644 --- a/libbutl/timestamp.mxx +++ b/libbutl/timestamp.mxx @@ -194,4 +194,14 @@ LIBBUTL_MODEXPORT namespace butl const char* format, bool local, const char** end = nullptr); + + // Rebase a time point from UNIX epoch to midnight in the local time zone + // (so the returned duration is always less than 24 hours). + // + // Specifically, convert the time point from Epoch to the local time and + // return the time elapsed since midnight. Throw std::system_error on + // underlying time conversion function failures. + // + LIBBUTL_SYMEXPORT duration + daytime (timestamp); } diff --git a/tests/timestamp/driver.cxx b/tests/timestamp/driver.cxx index 1746c2e..11e1821 100644 --- a/tests/timestamp/driver.cxx +++ b/tests/timestamp/driver.cxx @@ -225,4 +225,16 @@ main () assert (parse ( "Apr 8 19:31:10 2016", "%b %d %H:%M:%S %Y", "Apr 08 19:31:10 2016")); + + { + timestamp t (from_string ("Apr 8 19:31:10 2016", + "%b %d %H:%M:%S %Y", + true /* local */)); + + timestamp mt (from_string ("Apr 8 00:00:00 2016", + "%b %d %H:%M:%S %Y", + true /* local */)); + + assert (daytime (t) == t - mt); + } } |