aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbutl/timestamp.cxx28
-rw-r--r--libbutl/timestamp.mxx10
-rw-r--r--tests/timestamp/driver.cxx12
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);
+ }
}