summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2021-08-10 16:09:03 +0200
committerMax Kellermann <max@musicpd.org>2021-08-10 16:16:15 +0200
commitd7e7adb4963e6acc8c0d287e18ea062bdd7f3fb3 (patch)
tree4a87b9749349b25ff41ba257b1bad0ea1ee4c609
parent45354a421c2a790413385174ef642a839a664cd6 (diff)
time/FileTime: add ChronoToFileTime()
-rw-r--r--src/time/FileTime.hxx49
-rw-r--r--test/time/TestFileTime.cxx4
2 files changed, 53 insertions, 0 deletions
diff --git a/src/time/FileTime.hxx b/src/time/FileTime.hxx
index 6319d7749..a5c79a422 100644
--- a/src/time/FileTime.hxx
+++ b/src/time/FileTime.hxx
@@ -53,6 +53,21 @@ ToInt64(FILETIME ft) noexcept
return ToUint64(ft);
}
+constexpr FILETIME
+ToFileTime(uint_least64_t t) noexcept
+{
+ FILETIME ft{};
+ ft.dwLowDateTime = DWORD(t);
+ ft.dwHighDateTime = DWORD(t >> 32);
+ return ft;
+}
+
+constexpr FILETIME
+ToFileTime(int_least64_t t) noexcept
+{
+ return ToFileTime(uint_least64_t(t));
+}
+
/* "A file time is a 64-bit value that represents the number of
100-nanosecond intervals"
https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times */
@@ -104,6 +119,40 @@ FileTimeToChrono(FILETIME ft) noexcept
return unix_epoch + sys_duration;
}
+constexpr FILETIME
+ToFileTime(FileTimeDuration d) noexcept
+{
+ return ToFileTime(d.count());
+}
+
+constexpr FILETIME
+UnixEpochDurationToFileTime(FileTimeDuration d) noexcept
+{
+ /**
+ * The number of days between the Windows FILETIME epoch
+ * (1601-01-01T00:00) and the Unix epoch (1970-01-01T00:00).
+ */
+ constexpr int_least64_t windows_unix_days = 134774;
+ constexpr int_least64_t windows_unix_hours = windows_unix_days * 24;
+
+ constexpr FileTimeDuration windows_unix_delta{std::chrono::hours{windows_unix_hours}};
+
+ return ToFileTime(d + windows_unix_delta);
+}
+
+inline FILETIME
+ChronoToFileTime(std::chrono::system_clock::time_point tp) noexcept
+{
+ /* this is guaranteed to be 0 in C++20 */
+ const auto unix_epoch = std::chrono::system_clock::from_time_t(0);
+
+ const auto since_unix_epoch = tp - unix_epoch;
+ const auto ft_since_unix_epoch =
+ std::chrono::duration_cast<FileTimeDuration>(since_unix_epoch);
+
+ return UnixEpochDurationToFileTime(ft_since_unix_epoch);
+}
+
constexpr std::chrono::seconds
DeltaFileTimeS(FILETIME a, FILETIME b) noexcept
{
diff --git a/test/time/TestFileTime.cxx b/test/time/TestFileTime.cxx
index 9a1a6474c..da7eaad2e 100644
--- a/test/time/TestFileTime.cxx
+++ b/test/time/TestFileTime.cxx
@@ -49,4 +49,8 @@ TEST(Time, FileTimeToChrono)
ASSERT_EQ(stat(".", &st), 0);
ASSERT_EQ(std::chrono::system_clock::to_time_t(tp), st.st_mtime);
+
+ const auto ft2 = ChronoToFileTime(std::chrono::system_clock::from_time_t(st.st_mtime));
+ const auto tp2 = FileTimeToChrono(ft2);
+ ASSERT_EQ(std::chrono::system_clock::to_time_t(tp2), st.st_mtime);
}