Skip to content

Commit f6932fe

Browse files
Enable conversion between winrt::clock and std::chrono::system_clock (#698)
Co-authored-by: Kenny Kerr <[email protected]>
1 parent aed7977 commit f6932fe

File tree

2 files changed

+60
-5
lines changed

2 files changed

+60
-5
lines changed

strings/base_chrono.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ WINRT_EXPORT namespace winrt
4242

4343
static time_t to_time_t(time_point const& time) noexcept
4444
{
45-
return std::chrono::duration_cast<time_t_duration>(time - time_t_epoch).count();
45+
return std::chrono::system_clock::to_time_t(to_sys(time));
4646
}
4747

4848
static time_point from_time_t(time_t time) noexcept
4949
{
50-
return time_t_epoch + time_t_duration{ time };
50+
return from_sys(std::chrono::system_clock::from_time_t(time));
5151
}
5252

5353
static file_time to_file_time(time_point const& time) noexcept
@@ -70,10 +70,25 @@ WINRT_EXPORT namespace winrt
7070
return from_file_time(time);
7171
}
7272

73+
template <typename Duration>
74+
static std::chrono::time_point<std::chrono::system_clock, std::common_type_t<Duration, std::chrono::seconds>>
75+
to_sys(std::chrono::time_point<clock, Duration> const& tp)
76+
{
77+
return epoch + tp.time_since_epoch();
78+
}
79+
80+
template <typename Duration>
81+
static std::chrono::time_point<clock, std::common_type_t<Duration, std::chrono::seconds>>
82+
from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const& tp)
83+
{
84+
using result_t = std::chrono::time_point<clock, std::common_type_t<Duration, std::chrono::seconds>>;
85+
return result_t{ tp - epoch };
86+
}
87+
7388
private:
7489

75-
// Define 00:00:00, Jan 1 1970 UTC in FILETIME units.
76-
static constexpr time_point time_t_epoch{ duration{ 0x019DB1DED53E8000 } };
77-
using time_t_duration = std::chrono::duration<time_t>;
90+
// system_clock epoch is 00:00:00, Jan 1 1970.
91+
// This is 11644473600 seconds after Windows FILETIME epoch of 00:00:00, Jan 1 1601.
92+
static constexpr std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> epoch{ std::chrono::seconds{ -11644473600 } };
7893
};
7994
}

test/old_tests/UnitTests/clock.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,43 @@ TEST_CASE("clock, FILETIME")
9595
const auto diff = abs(clock::now() - clock::from_file_time(now_ft));
9696
REQUIRE(diff < milliseconds{ 100 });
9797
}
98+
99+
TEST_CASE("clock, system_clock")
100+
{
101+
DateTime const now_dt = clock::now();
102+
auto const now_sys = system_clock::now();
103+
104+
// Round trip DateTime to std::chrono::system_clock::time_point and back
105+
REQUIRE(clock::from_sys(clock::to_sys(now_dt)) == now_dt);
106+
107+
// Round trip other direction
108+
REQUIRE(clock::to_sys(clock::from_sys(now_sys)) == now_sys);
109+
110+
// Round trip with custom resolution
111+
{
112+
auto const now_dt_sec = time_point_cast<seconds>(now_dt);
113+
REQUIRE(clock::from_sys(clock::to_sys(now_dt_sec)) == now_dt_sec);
114+
}
115+
{
116+
auto const now_dt_mins = time_point_cast<minutes>(now_dt);
117+
REQUIRE(clock::from_sys(clock::to_sys(now_dt_mins)) == now_dt_mins);
118+
}
119+
{
120+
auto const now_sys_sec = time_point_cast<seconds>(now_sys);
121+
REQUIRE(clock::to_sys(clock::from_sys(now_sys_sec)) == now_sys_sec);
122+
}
123+
{
124+
auto const now_sys_mins = time_point_cast<seconds>(now_sys);
125+
REQUIRE(clock::to_sys(clock::from_sys(now_sys_mins)) == now_sys_mins);
126+
}
127+
128+
// Verify that the epoch calculations are correct.
129+
{
130+
auto const diff = now_dt - clock::from_sys(now_sys);
131+
REQUIRE(abs(diff) < milliseconds{ 100 });
132+
}
133+
{
134+
auto const diff = now_sys - clock::to_sys(now_dt);
135+
REQUIRE(abs(diff) < milliseconds{ 100 });
136+
}
137+
}

0 commit comments

Comments
 (0)