27
27
#include " concat_macros.h"
28
28
29
29
template <class Duration >
30
- static void test_leap_seconds (std::chrono::utc_time<Duration> time, std::chrono::sys_time< Duration> expected) {
30
+ static void test_leap_seconds (std::chrono::utc_time<Duration> time, std::chrono::sys_time<Duration> expected) {
31
31
auto result = std::chrono::utc_clock::to_sys (time);
32
32
TEST_REQUIRE (
33
33
result == expected,
@@ -42,7 +42,7 @@ static std::chrono::sys_seconds get_sys_time(long long seconds_since_1900) {
42
42
return std::chrono::sys_seconds{std::chrono::seconds{seconds_since_1900} - __offset};
43
43
}
44
44
45
- // Tests the set of existing database entries at the time of writing. Since
45
+ // Tests the set of existing database entries at the time of writing. Since
46
46
// the last leap second insertion is several years ago, it's expected all
47
47
// systems have the same information. (Adding new entries in the future does
48
48
// not affect this test.)
@@ -122,6 +122,78 @@ static void test_transitions() {
122
122
test_transition (get_sys_time (3692217600 ), 26s, true ); // 1 Jan 2017
123
123
}
124
124
125
+ // Tests the transition for clocks where the duration's rep is a floating-point type.
126
+ static void test_transitions_floating_point () {
127
+ using namespace std ::literals::chrono_literals;
128
+
129
+ // Based on test_transitions but uses a floating-point duration.
130
+ using F = float ;
131
+
132
+ auto test_transition = [](std::chrono::sys_seconds sys, std::chrono::seconds elapsed, bool positive) {
133
+ // Note at the time of writing all leap seconds are positive so the else
134
+ // branch is never executed. The private test for this function tests
135
+ // negative leap seconds and uses the else branch.
136
+
137
+ std::chrono::utc_seconds utc = std::chrono::utc_seconds{sys.time_since_epoch ()} + elapsed;
138
+
139
+ using D = std::chrono::duration<F>;
140
+ using S = std::chrono ::time_point<std::chrono::system_clock, D>;
141
+ using U = std::chrono ::time_point<std::chrono::utc_clock, D>;
142
+
143
+ S s{sys.time_since_epoch ()};
144
+ bool is_leap_second = s.time_since_epoch ().count () == sys.time_since_epoch ().count ();
145
+ assert (is_leap_second);
146
+
147
+ U u{utc.time_since_epoch ()};
148
+ if (positive) {
149
+ test_leap_seconds (u - 1ns, s - 1ns);
150
+ test_leap_seconds (u, s - 1s);
151
+ test_leap_seconds (u + 0ns, s - 1ns);
152
+ test_leap_seconds (u + 1s - 1ns, s - 1ns);
153
+ test_leap_seconds (u + 1s, s);
154
+ test_leap_seconds (u + 1s + 0ns, s + 0ns);
155
+ test_leap_seconds (u + 1s + 1ns, s + 1ns);
156
+
157
+ test_leap_seconds (U{D{std::nextafter (u.time_since_epoch ().count (), F{0 })}},
158
+ S{D{std::nextafter (s.time_since_epoch ().count (), F{0 })}});
159
+ test_leap_seconds (u, S{D{s.time_since_epoch ().count () - F{1 }}});
160
+ test_leap_seconds (U{D{u.time_since_epoch ().count () + F{1 }}}, s);
161
+ test_leap_seconds (U{D{std::nextafter (u.time_since_epoch ().count () + F{1 }, std::numeric_limits<F>::max ())}},
162
+ S{D{std::nextafter (s.time_since_epoch ().count (), std::numeric_limits<F>::max ())}});
163
+ }
164
+ };
165
+
166
+ // Transitions from the start of UTC.
167
+ test_transition (get_sys_time (2287785600 ), 0s, true ); // 1 Jul 1972
168
+ test_transition (get_sys_time (2303683200 ), 1s, true ); // 1 Jan 1973
169
+ test_transition (get_sys_time (2335219200 ), 2s, true ); // 1 Jan 1974
170
+ test_transition (get_sys_time (2366755200 ), 3s, true ); // 1 Jan 1975
171
+ test_transition (get_sys_time (2398291200 ), 4s, true ); // 1 Jan 1976
172
+ test_transition (get_sys_time (2429913600 ), 5s, true ); // 1 Jan 1977
173
+ test_transition (get_sys_time (2461449600 ), 6s, true ); // 1 Jan 1978
174
+ test_transition (get_sys_time (2492985600 ), 7s, true ); // 1 Jan 1979
175
+ test_transition (get_sys_time (2524521600 ), 8s, true ); // 1 Jan 1980
176
+ test_transition (get_sys_time (2571782400 ), 9s, true ); // 1 Jul 1981
177
+ test_transition (get_sys_time (2603318400 ), 10s, true ); // 1 Jul 1982
178
+ test_transition (get_sys_time (2634854400 ), 11s, true ); // 1 Jul 1983
179
+ test_transition (get_sys_time (2698012800 ), 12s, true ); // 1 Jul 1985
180
+ test_transition (get_sys_time (2776982400 ), 13s, true ); // 1 Jan 1988
181
+ test_transition (get_sys_time (2840140800 ), 14s, true ); // 1 Jan 1990
182
+ test_transition (get_sys_time (2871676800 ), 15s, true ); // 1 Jan 1991
183
+ test_transition (get_sys_time (2918937600 ), 16s, true ); // 1 Jul 1992
184
+ test_transition (get_sys_time (2950473600 ), 17s, true ); // 1 Jul 1993
185
+ test_transition (get_sys_time (2982009600 ), 18s, true ); // 1 Jul 1994
186
+ test_transition (get_sys_time (3029443200 ), 19s, true ); // 1 Jan 1996
187
+ test_transition (get_sys_time (3076704000 ), 20s, true ); // 1 Jul 1997
188
+ test_transition (get_sys_time (3124137600 ), 21s, true ); // 1 Jan 1999
189
+ test_transition (get_sys_time (3345062400 ), 22s, true ); // 1 Jan 2006
190
+ test_transition (get_sys_time (3439756800 ), 23s, true ); // 1 Jan 2009
191
+ test_transition (get_sys_time (3550089600 ), 24s, true ); // 1 Jul 2012
192
+ test_transition (get_sys_time (3644697600 ), 25s, true ); // 1 Jul 2015
193
+ test_transition (get_sys_time (3692217600 ), 26s, true ); // 1 Jan 2017
194
+
195
+ }
196
+
125
197
// Tests whether the return type is the expected type.
126
198
static void test_return_type () {
127
199
using namespace std ::chrono;
@@ -143,5 +215,6 @@ static void test_return_type() {
143
215
144
216
int main (int , const char **) {
145
217
test_transitions ();
218
+ test_transitions_floating_point ();
146
219
test_return_type ();
147
220
}
0 commit comments