1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03, c++11, c++14, c++17
10// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
11
12// XFAIL: libcpp-has-no-experimental-tzdb
13// XFAIL: availability-tzdb-missing
14
15// <chrono>
16
17// class utc_clock;
18
19// static sys_time<common_type_t<_Duration, seconds>>
20// to_sys(const utc_time<_Duration>& __time);
21
22#include <chrono>
23#include <cmath>
24#include <cassert>
25
26#include "test_macros.h"
27#include "assert_macros.h"
28#include "concat_macros.h"
29
30template <class Duration>
31static void test_leap_seconds(std::chrono::utc_time<Duration> time, std::chrono::sys_time<Duration> expected) {
32 auto result = std::chrono::utc_clock::to_sys(time);
33 TEST_REQUIRE(
34 result == expected,
35 TEST_WRITE_CONCATENATED("\tTime: ", time, "\nExpected output ", expected, "\nActual output ", result, '\n'));
36}
37
38static std::chrono::sys_seconds get_sys_time(long long seconds_since_1900) {
39 // The file leap-seconds.list stores dates since 1 January 1900, 00:00:00, we want
40 // seconds since 1 January 1970.
41 constexpr auto offset =
42 std::chrono::sys_days{std::chrono::January / 1 / 1970} - std::chrono::sys_days{std::chrono::January / 1 / 1900};
43 return std::chrono::sys_seconds{std::chrono::seconds{seconds_since_1900} - offset};
44}
45
46// Tests the set of existing database entries at the time of writing. Since
47// the last leap second insertion is several years ago, it's expected all
48// systems have the same information. (Adding new entries in the future does
49// not affect this test.)
50static void test_transitions() {
51 using namespace std::literals::chrono_literals;
52
53 test_leap_seconds(std::chrono::utc_seconds::min(), std::chrono::sys_seconds::min());
54
55 // Epoch transition no transitions.
56 test_leap_seconds(std::chrono::utc_seconds{-1s}, std::chrono::sys_seconds{-1s});
57 test_leap_seconds(std::chrono::utc_seconds{0s}, std::chrono::sys_seconds{0s});
58 test_leap_seconds(std::chrono::utc_seconds{1s}, std::chrono::sys_seconds{1s});
59
60 // "sys" is the time of the transition to the next leap second.
61 // "elapsed" is the number of leap seconds before the transition.
62 // "positive" is the leap second added +1s? If not it's -1s.
63 auto test_transition = [](std::chrono::sys_seconds sys, std::chrono::seconds elapsed, bool positive) {
64 // Note at the time of writing all leap seconds are positive so the else
65 // branch is never executed. The private test for this function tests
66 // negative leap seconds and uses the else branch.
67
68 std::chrono::utc_seconds utc = std::chrono::utc_seconds{sys.time_since_epoch()} + elapsed;
69 if (positive) {
70 // Every transition has the following tests
71 // - 1ns before the start of the transition no adjustment needed
72 // - at the start of the transition sys is clamped at the time just prior to the moment
73 // of the leap second insertion. The exact value depends
74 // on the resolution of the result type.
75 // - 1ns before the end of the transition sys is still clamped like before
76 // - at the end of the transition sys is 1s behind the utc time
77 // - 1ns after the end of the transition sys is still 1s behind the utc time
78 test_leap_seconds(utc - 1ns, sys - 1ns);
79 test_leap_seconds(utc, sys - 1s);
80 test_leap_seconds(utc + 0ns, sys - 1ns);
81 test_leap_seconds(utc + 1s - 1ns, sys - 1ns);
82 test_leap_seconds(utc + 1s, sys);
83 test_leap_seconds(utc + 1s + 0ns, sys + 0ns);
84 test_leap_seconds(utc + 1s + 1ns, sys + 1ns);
85 } else {
86 // Every transition has the following tests
87 // - 1ns before the transition no adjustment needed
88 // - at the transition sys is 1s ahead of the utc time
89 // - 1ns after the transition sys is still 1s ahead of the utc time
90 test_leap_seconds(utc - 1ns, sys - 1ns);
91 test_leap_seconds(utc, sys + 1s);
92 test_leap_seconds(utc + 1ns, sys + 1s + 1ns);
93 }
94 };
95
96 // Transitions from the start of UTC.
97 test_transition(get_sys_time(2287785600), 0s, true); // 1 Jul 1972
98 test_transition(get_sys_time(2303683200), 1s, true); // 1 Jan 1973
99 test_transition(get_sys_time(2335219200), 2s, true); // 1 Jan 1974
100 test_transition(get_sys_time(2366755200), 3s, true); // 1 Jan 1975
101 test_transition(get_sys_time(2398291200), 4s, true); // 1 Jan 1976
102 test_transition(get_sys_time(2429913600), 5s, true); // 1 Jan 1977
103 test_transition(get_sys_time(2461449600), 6s, true); // 1 Jan 1978
104 test_transition(get_sys_time(2492985600), 7s, true); // 1 Jan 1979
105 test_transition(get_sys_time(2524521600), 8s, true); // 1 Jan 1980
106 test_transition(get_sys_time(2571782400), 9s, true); // 1 Jul 1981
107 test_transition(get_sys_time(2603318400), 10s, true); // 1 Jul 1982
108 test_transition(get_sys_time(2634854400), 11s, true); // 1 Jul 1983
109 test_transition(get_sys_time(2698012800), 12s, true); // 1 Jul 1985
110 test_transition(get_sys_time(2776982400), 13s, true); // 1 Jan 1988
111 test_transition(get_sys_time(2840140800), 14s, true); // 1 Jan 1990
112 test_transition(get_sys_time(2871676800), 15s, true); // 1 Jan 1991
113 test_transition(get_sys_time(2918937600), 16s, true); // 1 Jul 1992
114 test_transition(get_sys_time(2950473600), 17s, true); // 1 Jul 1993
115 test_transition(get_sys_time(2982009600), 18s, true); // 1 Jul 1994
116 test_transition(get_sys_time(3029443200), 19s, true); // 1 Jan 1996
117 test_transition(get_sys_time(3076704000), 20s, true); // 1 Jul 1997
118 test_transition(get_sys_time(3124137600), 21s, true); // 1 Jan 1999
119 test_transition(get_sys_time(3345062400), 22s, true); // 1 Jan 2006
120 test_transition(get_sys_time(3439756800), 23s, true); // 1 Jan 2009
121 test_transition(get_sys_time(3550089600), 24s, true); // 1 Jul 2012
122 test_transition(get_sys_time(3644697600), 25s, true); // 1 Jul 2015
123 test_transition(get_sys_time(3692217600), 26s, true); // 1 Jan 2017
124}
125
126// Tests the transition for clocks where the duration's rep is a floating-point type.
127static void test_transitions_floating_point() {
128 using namespace std::literals::chrono_literals;
129
130 // Based on test_transitions but uses a floating-point duration.
131 using F = float;
132
133 auto test_transition = [](std::chrono::sys_seconds sys, std::chrono::seconds elapsed, bool positive) {
134 // Note at the time of writing all leap seconds are positive so the else
135 // branch is never executed. The private test for this function tests
136 // negative leap seconds and uses the else branch.
137
138 std::chrono::utc_seconds utc = std::chrono::utc_seconds{sys.time_since_epoch()} + elapsed;
139
140 using D = std::chrono::duration<F>;
141 using S = std::chrono ::time_point<std::chrono::system_clock, D>;
142 using U = std::chrono ::time_point<std::chrono::utc_clock, D>;
143
144 S s{sys.time_since_epoch()};
145 bool is_leap_second = s.time_since_epoch().count() == sys.time_since_epoch().count();
146 assert(is_leap_second);
147
148 U u{utc.time_since_epoch()};
149 if (positive) {
150 test_leap_seconds(u - 1ns, s - 1ns);
151 test_leap_seconds(u, s - 1s);
152 test_leap_seconds(u + 0ns, s - 1ns);
153 test_leap_seconds(u + 1s - 1ns, s - 1ns);
154 test_leap_seconds(u + 1s, s);
155 test_leap_seconds(u + 1s + 0ns, s + 0ns);
156 test_leap_seconds(u + 1s + 1ns, s + 1ns);
157
158 test_leap_seconds(U{D{std::nextafter(u.time_since_epoch().count(), F{0})}},
159 S{D{std::nextafter(s.time_since_epoch().count(), F{0})}});
160 test_leap_seconds(u, S{D{s.time_since_epoch().count() - F{1}}});
161 test_leap_seconds(U{D{u.time_since_epoch().count() + F{1}}}, s);
162 test_leap_seconds(U{D{std::nextafter(u.time_since_epoch().count() + F{1}, std::numeric_limits<F>::max())}},
163 S{D{std::nextafter(s.time_since_epoch().count(), std::numeric_limits<F>::max())}});
164 }
165 };
166
167 // Transitions from the start of UTC.
168 test_transition(get_sys_time(2287785600), 0s, true); // 1 Jul 1972
169 test_transition(get_sys_time(2303683200), 1s, true); // 1 Jan 1973
170 test_transition(get_sys_time(2335219200), 2s, true); // 1 Jan 1974
171 test_transition(get_sys_time(2366755200), 3s, true); // 1 Jan 1975
172 test_transition(get_sys_time(2398291200), 4s, true); // 1 Jan 1976
173 test_transition(get_sys_time(2429913600), 5s, true); // 1 Jan 1977
174 test_transition(get_sys_time(2461449600), 6s, true); // 1 Jan 1978
175 test_transition(get_sys_time(2492985600), 7s, true); // 1 Jan 1979
176 test_transition(get_sys_time(2524521600), 8s, true); // 1 Jan 1980
177 test_transition(get_sys_time(2571782400), 9s, true); // 1 Jul 1981
178 test_transition(get_sys_time(2603318400), 10s, true); // 1 Jul 1982
179 test_transition(get_sys_time(2634854400), 11s, true); // 1 Jul 1983
180 test_transition(get_sys_time(2698012800), 12s, true); // 1 Jul 1985
181 test_transition(get_sys_time(2776982400), 13s, true); // 1 Jan 1988
182 test_transition(get_sys_time(2840140800), 14s, true); // 1 Jan 1990
183 test_transition(get_sys_time(2871676800), 15s, true); // 1 Jan 1991
184 test_transition(get_sys_time(2918937600), 16s, true); // 1 Jul 1992
185 test_transition(get_sys_time(2950473600), 17s, true); // 1 Jul 1993
186 test_transition(get_sys_time(2982009600), 18s, true); // 1 Jul 1994
187 test_transition(get_sys_time(3029443200), 19s, true); // 1 Jan 1996
188 test_transition(get_sys_time(3076704000), 20s, true); // 1 Jul 1997
189 test_transition(get_sys_time(3124137600), 21s, true); // 1 Jan 1999
190 test_transition(get_sys_time(3345062400), 22s, true); // 1 Jan 2006
191 test_transition(get_sys_time(3439756800), 23s, true); // 1 Jan 2009
192 test_transition(get_sys_time(3550089600), 24s, true); // 1 Jul 2012
193 test_transition(get_sys_time(3644697600), 25s, true); // 1 Jul 2015
194 test_transition(get_sys_time(3692217600), 26s, true); // 1 Jan 2017
195}
196
197// Tests whether the return type is the expected type.
198static void test_return_type() {
199 namespace cr = std::chrono;
200 using namespace std::literals::chrono_literals;
201
202 {
203 [[maybe_unused]] std::same_as<cr::sys_time<cr::nanoseconds>> decltype(auto) _ =
204 cr::utc_clock::to_sys(cr::utc_time<cr::nanoseconds>{0ns});
205 }
206 {
207 [[maybe_unused]] std::same_as<cr::sys_time<cr::microseconds>> decltype(auto) _ =
208 cr::utc_clock::to_sys(cr::utc_time<cr::microseconds>{0us});
209 }
210 {
211 [[maybe_unused]] std::same_as<cr::sys_time<cr::milliseconds>> decltype(auto) _ =
212 cr::utc_clock::to_sys(cr::utc_time<cr::milliseconds>{0ms});
213 }
214
215 {
216 [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =
217 cr::utc_clock::to_sys(cr::utc_time<cr::seconds>{cr::seconds{0}});
218 }
219
220 {
221 [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =
222 cr::utc_clock::to_sys(cr::utc_time<cr::minutes>{cr::minutes{0}});
223 }
224 {
225 [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =
226 cr::utc_clock::to_sys(cr::utc_time<cr::hours>{cr::hours{0}});
227 }
228 {
229 [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =
230 cr::utc_clock::to_sys(cr::utc_time<cr::days>{cr::days{0}});
231 }
232 {
233 [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =
234 cr::utc_clock::to_sys(cr::utc_time<cr::weeks>{cr::weeks{0}});
235 }
236 {
237 [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =
238 cr::utc_clock::to_sys(cr::utc_time<cr::months>{cr::months{0}});
239 }
240 {
241 [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =
242 cr::utc_clock::to_sys(cr::utc_time<cr::years>{cr::years{0}});
243 }
244}
245
246int main(int, const char**) {
247 test_transitions();
248 test_transitions_floating_point();
249 test_return_type();
250
251 return 0;
252}
253

source code of libcxx/test/std/time/time.clock/time.clock.utc/time.clock.utc.members/to_sys.pass.cpp