1//===----------------------------------------------------------------------===//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
8// UNSUPPORTED: c++03, c++11, c++14, c++17
9// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
10// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
11
12// TODO FMT This test should not require std::to_chars(floating-point)
13// XFAIL: availability-fp_to_chars-missing
14
15// XFAIL: libcpp-has-no-experimental-tzdb
16// XFAIL: availability-tzdb-missing
17
18// REQUIRES: locale.fr_FR.UTF-8
19// REQUIRES: locale.ja_JP.UTF-8
20
21// <chrono>
22
23// template<class Duration, class charT>
24// struct formatter<chrono::utc_time<Duration>, charT>;
25
26#include <chrono>
27#include <format>
28
29#include <cassert>
30#include <concepts>
31#include <locale>
32#include <iostream>
33#include <type_traits>
34
35#include "formatter_tests.h"
36#include "make_string.h"
37#include "platform_support.h" // locale name macros
38#include "test_macros.h"
39
40template <class CharT>
41static void test_no_chrono_specs() {
42 using namespace std::literals::chrono_literals;
43
44 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
45
46 // Non localized output
47
48 // [time.syn]
49 // using nanoseconds = duration<signed integer type of at least 64 bits, nano>;
50 // using microseconds = duration<signed integer type of at least 55 bits, micro>;
51 // using milliseconds = duration<signed integer type of at least 45 bits, milli>;
52 // using seconds = duration<signed integer type of at least 35 bits>;
53 // using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>;
54 // using hours = duration<signed integer type of at least 23 bits, ratio<3600>>;
55 check(SV("1425-08-04 22:06:56"), SV("{}"), std::chrono::utc_seconds(-17'179'869'184s)); // Minimum value for 35 bits.
56 check(SV("1901-12-13 20:45:52"), SV("{}"), std::chrono::utc_seconds(-2'147'483'648s));
57
58 check(SV("1969-12-31 00:00:00"), SV("{}"), std::chrono::utc_seconds(-24h));
59 check(SV("1969-12-31 06:00:00"), SV("{}"), std::chrono::utc_seconds(-18h));
60 check(SV("1969-12-31 12:00:00"), SV("{}"), std::chrono::utc_seconds(-12h));
61 check(SV("1969-12-31 18:00:00"), SV("{}"), std::chrono::utc_seconds(-6h));
62 check(SV("1969-12-31 23:59:59"), SV("{}"), std::chrono::utc_seconds(-1s));
63
64 check(SV("1970-01-01 00:00:00"), SV("{}"), std::chrono::utc_seconds(0s));
65 check(SV("2000-01-01 00:00:00"), SV("{}"), std::chrono::utc_seconds(946'684'800s + 22s));
66 check(SV("2000-01-01 01:02:03"), SV("{}"), std::chrono::utc_seconds(946'688'523s + 22s));
67
68 check(SV("2038-01-19 03:14:07"), SV("{}"), std::chrono::utc_seconds(2'147'483'647s + 27s));
69 check(SV("2514-05-30 01:53:03"),
70 SV("{}"),
71 std::chrono::utc_seconds(17'179'869'183s + 27s)); // Maximum value for 35 bits.
72
73 check(SV("2000-01-01 01:02:03.123"),
74 SV("{}"),
75 std::chrono::utc_time<std::chrono::milliseconds>(946'688'523'123ms + 22s));
76
77 std::locale::global(loc: std::locale::classic());
78}
79
80template <class CharT>
81static void test_valid_values_year() {
82 using namespace std::literals::chrono_literals;
83
84 constexpr std::basic_string_view<CharT> fmt =
85 SV("{:%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
86 constexpr std::basic_string_view<CharT> lfmt =
87 SV("{:L%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
88
89 const std::locale loc(LOCALE_ja_JP_UTF_8);
90 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
91
92 // Non localized output using C-locale
93 check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),
94 fmt,
95 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
96
97 check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
98 fmt,
99 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
100
101 // Use the global locale (fr_FR)
102 check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),
103 lfmt,
104 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
105
106 check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
107 lfmt,
108 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
109
110 // Use supplied locale (ja_JP). This locale has a different alternate.
111#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
112 check(loc,
113 SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),
114 lfmt,
115 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
116
117 check(loc,
118 SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
119 lfmt,
120 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
121#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)
122 check(loc,
123 SV("%C='19'\t%EC='昭和'\t%y='70'\t%Oy='七十'\t%Ey='45'\t%Y='1970'\t%EY='昭和45年'\n"),
124 lfmt,
125 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
126
127 check(loc,
128 SV("%C='20'\t%EC='平成'\t%y='09'\t%Oy='九'\t%Ey='21'\t%Y='2009'\t%EY='平成21年'\n"),
129 lfmt,
130 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
131#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)
132
133 std::locale::global(loc: std::locale::classic());
134}
135
136template <class CharT>
137static void test_valid_values_month() {
138 using namespace std::literals::chrono_literals;
139
140 constexpr std::basic_string_view<CharT> fmt = SV("{:%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
141 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
142
143 const std::locale loc(LOCALE_ja_JP_UTF_8);
144 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
145
146 // Non localized output using C-locale
147 check(SV("%b='Jan'\t%h='Jan'\t%B='January'\t%m='01'\t%Om='01'\n"),
148 fmt,
149 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
150
151 check(SV("%b='May'\t%h='May'\t%B='May'\t%m='05'\t%Om='05'\n"),
152 fmt,
153 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
154
155 // Use the global locale (fr_FR)
156#if defined(__APPLE__)
157 check(SV("%b='jan'\t%h='jan'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
158 lfmt,
159 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
160#else
161 check(SV("%b='janv.'\t%h='janv.'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
162 lfmt,
163 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
164#endif
165
166 check(SV("%b='mai'\t%h='mai'\t%B='mai'\t%m='05'\t%Om='05'\n"),
167 lfmt,
168 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
169
170 // Use supplied locale (ja_JP). This locale has a different alternate.
171#ifdef _WIN32
172 check(loc,
173 SV("%b='1'\t%h='1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
174 lfmt,
175 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
176
177 check(loc,
178 SV("%b='5'\t%h='5'\t%B='5月'\t%m='05'\t%Om='05'\n"),
179 lfmt,
180 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
181#elif defined(_AIX) // _WIN32
182 check(loc,
183 SV("%b='1月'\t%h='1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),
184 lfmt,
185 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
186
187 check(loc,
188 SV("%b='5月'\t%h='5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),
189 lfmt,
190 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
191#elif defined(__APPLE__) // _WIN32
192 check(loc,
193 SV("%b=' 1'\t%h=' 1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
194 lfmt,
195 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
196
197 check(loc,
198 SV("%b=' 5'\t%h=' 5'\t%B='5月'\t%m='05'\t%Om='05'\n"),
199 lfmt,
200 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
201#elif defined(__FreeBSD__) // _WIN32
202 check(loc,
203 SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),
204 lfmt,
205 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
206
207 check(loc,
208 SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),
209 lfmt,
210 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
211#else // _WIN32
212 check(loc,
213 SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='一'\n"),
214 lfmt,
215 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
216
217 check(loc,
218 SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='五'\n"),
219 lfmt,
220 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
221#endif // _WIN32
222
223 std::locale::global(loc: std::locale::classic());
224}
225
226template <class CharT>
227static void test_valid_values_day() {
228 using namespace std::literals::chrono_literals;
229
230 constexpr std::basic_string_view<CharT> fmt = SV("{:%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
231 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
232
233 const std::locale loc(LOCALE_ja_JP_UTF_8);
234 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
235
236 // Non localized output using C-locale
237 check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),
238 fmt,
239 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
240
241 check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
242 fmt,
243 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
244
245 // Use the global locale (fr_FR)
246 check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),
247 lfmt,
248 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
249
250 check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
251 lfmt,
252 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
253
254 // Use supplied locale (ja_JP). This locale has a different alternate.
255#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
256 check(loc,
257 SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),
258 lfmt,
259 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
260
261 check(loc,
262 SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
263 lfmt,
264 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
265#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
266 check(loc,
267 SV("%d='01'\t%Od='一'\t%e=' 1'\t%Oe='一'\n"),
268 lfmt,
269 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
270
271 check(loc,
272 SV("%d='13'\t%Od='十三'\t%e='13'\t%Oe='十三'\n"),
273 lfmt,
274 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
275
276#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
277
278 std::locale::global(loc: std::locale::classic());
279}
280
281template <class CharT>
282static void test_valid_values_weekday() {
283 using namespace std::literals::chrono_literals;
284
285 constexpr std::basic_string_view<CharT> fmt =
286 SV("{:%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
287 constexpr std::basic_string_view<CharT> lfmt =
288 SV("{:L%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
289
290 const std::locale loc(LOCALE_ja_JP_UTF_8);
291 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
292
293 // Non localized output using C-locale
294 check(SV("%a='Thu'\t%A='Thursday'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
295 fmt,
296 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
297
298 check(SV("%a='Sun'\t%A='Sunday'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
299 fmt,
300 std::chrono::utc_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
301
302 // Use the global locale (fr_FR)
303#if defined(__APPLE__)
304 check(SV("%a='Jeu'\t%A='Jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
305 lfmt,
306 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
307
308 check(SV("%a='Dim'\t%A='Dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
309 lfmt,
310 std::chrono::utc_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
311#else
312 check(SV("%a='jeu.'\t%A='jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
313 lfmt,
314 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
315
316 check(SV("%a='dim.'\t%A='dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
317 lfmt,
318 std::chrono::utc_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
319#endif
320
321 // Use supplied locale (ja_JP).
322 // This locale has a different alternate, but not on all platforms
323#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
324 check(loc,
325 SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
326 lfmt,
327 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
328
329 check(loc,
330 SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
331 lfmt,
332 std::chrono::utc_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
333#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
334 check(loc,
335 SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\n"),
336 lfmt,
337 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
338
339 check(loc,
340 SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\n"),
341 lfmt,
342 std::chrono::utc_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
343#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
344
345 std::locale::global(loc: std::locale::classic());
346}
347
348template <class CharT>
349static void test_valid_values_day_of_year() {
350 using namespace std::literals::chrono_literals;
351
352 constexpr std::basic_string_view<CharT> fmt = SV("{:%%j='%j'%n}");
353 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%j='%j'%n}");
354
355 const std::locale loc(LOCALE_ja_JP_UTF_8);
356 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
357
358 // Non localized output using C-locale
359 check(SV("%j='001'\n"), fmt, std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
360 check(SV("%j='138'\n"), fmt, std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
361
362 // Use the global locale (fr_FR)
363 check(SV("%j='001'\n"), lfmt, std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
364 check(SV("%j='138'\n"), lfmt, std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
365
366 // Use supplied locale (ja_JP). This locale has a different alternate.
367 check(loc, SV("%j='001'\n"), lfmt, std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
368
369 check(
370 loc, SV("%j='138'\n"), lfmt, std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
371
372 std::locale::global(loc: std::locale::classic());
373}
374
375template <class CharT>
376static void test_valid_values_week() {
377 using namespace std::literals::chrono_literals;
378
379 constexpr std::basic_string_view<CharT> fmt = SV("{:%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
380 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
381
382 const std::locale loc(LOCALE_ja_JP_UTF_8);
383 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
384
385 // Non localized output using C-locale
386 check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),
387 fmt,
388 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
389
390 check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
391 fmt,
392 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
393
394 // Use the global locale (fr_FR)
395 check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),
396 lfmt,
397 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
398
399 check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
400 lfmt,
401 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
402
403 // Use supplied locale (ja_JP). This locale has a different alternate.
404#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
405 check(loc,
406 SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),
407 lfmt,
408 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
409
410 check(loc,
411 SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
412 lfmt,
413 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
414#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
415 check(loc,
416 SV("%U='00'\t%OU='〇'\t%W='00'\t%OW='〇'\n"),
417 lfmt,
418 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
419
420 check(loc,
421 SV("%U='20'\t%OU='二十'\t%W='20'\t%OW='二十'\n"),
422 lfmt,
423 std::chrono::utc_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
424#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
425 std::locale::global(loc: std::locale::classic());
426}
427
428template <class CharT>
429static void test_valid_values_iso_8601_week() {
430 using namespace std::literals::chrono_literals;
431
432 constexpr std::basic_string_view<CharT> fmt = SV("{:%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
433 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
434
435 const std::locale loc(LOCALE_ja_JP_UTF_8);
436 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
437
438 // Non localized output using C-locale
439 check(SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),
440 fmt,
441 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
442
443 check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
444 fmt,
445 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
446
447 // Use the global locale (fr_FR)
448 check(SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),
449 lfmt,
450 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
451
452 check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
453 lfmt,
454 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
455
456 // Use supplied locale (ja_JP). This locale has a different alternate.
457#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
458 check(loc,
459 SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),
460 lfmt,
461 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
462
463 check(loc,
464 SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
465 lfmt,
466 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
467#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
468 check(loc,
469 SV("%g='70'\t%G='1970'\t%V='01'\t%OV='一'\n"),
470 lfmt,
471 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
472
473 check(loc,
474 SV("%g='09'\t%G='2009'\t%V='07'\t%OV='七'\n"),
475 lfmt,
476 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
477#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
478
479 std::locale::global(loc: std::locale::classic());
480}
481
482template <class CharT>
483static void test_valid_values_date() {
484 using namespace std::literals::chrono_literals;
485
486 constexpr std::basic_string_view<CharT> fmt = SV("{:%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
487 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
488
489 const std::locale loc(LOCALE_ja_JP_UTF_8);
490 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
491
492 // Non localized output using C-locale
493 check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/70'\t%Ex='01/01/70'\n"),
494 fmt,
495 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
496
497 check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='02/13/09'\t%Ex='02/13/09'\n"),
498 fmt,
499 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
500
501 // Use the global locale (fr_FR)
502#if defined(__APPLE__) || defined(__FreeBSD__)
503 check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01.01.1970'\t%Ex='01.01.1970'\n"),
504 lfmt,
505 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
506
507 check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13.02.2009'\t%Ex='13.02.2009'\n"),
508 lfmt,
509 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
510#else
511 check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/1970'\t%Ex='01/01/1970'\n"),
512 lfmt,
513 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
514
515 check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13/02/2009'\t%Ex='13/02/2009'\n"),
516 lfmt,
517 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
518#endif
519
520 // Use supplied locale (ja_JP). This locale has a different alternate.
521#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
522 check(loc,
523 SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970/01/01'\t%Ex='1970/01/01'\n"),
524 lfmt,
525 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
526
527 check(loc,
528 SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009/02/13'\t%Ex='2009/02/13'\n"),
529 lfmt,
530 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
531#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
532 check(loc,
533 SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970年01月01日'\t%Ex='昭和45年01月01日'\n"),
534 lfmt,
535 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
536
537 check(loc,
538 SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009年02月13日'\t%Ex='平成21年02月13日'\n"),
539 lfmt,
540 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
541#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
542
543 std::locale::global(loc: std::locale::classic());
544}
545
546template <class CharT>
547static void test_valid_values_time() {
548 using namespace std::literals::chrono_literals;
549
550 constexpr std::basic_string_view<CharT> fmt = SV(
551 "{:"
552 "%%H='%H'%t"
553 "%%OH='%OH'%t"
554 "%%I='%I'%t"
555 "%%OI='%OI'%t"
556 "%%M='%M'%t"
557 "%%OM='%OM'%t"
558 "%%S='%S'%t"
559 "%%OS='%OS'%t"
560 "%%p='%p'%t"
561 "%%R='%R'%t"
562 "%%T='%T'%t"
563 "%%r='%r'%t"
564 "%%X='%X'%t"
565 "%%EX='%EX'%t"
566 "%n}");
567 constexpr std::basic_string_view<CharT> lfmt = SV(
568 "{:L"
569 "%%H='%H'%t"
570 "%%OH='%OH'%t"
571 "%%I='%I'%t"
572 "%%OI='%OI'%t"
573 "%%M='%M'%t"
574 "%%OM='%OM'%t"
575 "%%S='%S'%t"
576 "%%OS='%OS'%t"
577 "%%p='%p'%t"
578 "%%R='%R'%t"
579 "%%T='%T'%t"
580 "%%r='%r'%t"
581 "%%X='%X'%t"
582 "%%EX='%EX'%t"
583 "%n}");
584
585 const std::locale loc(LOCALE_ja_JP_UTF_8);
586 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
587
588 // Non localized output using C-locale
589 check(SV("%H='00'\t"
590 "%OH='00'\t"
591 "%I='12'\t"
592 "%OI='12'\t"
593 "%M='00'\t"
594 "%OM='00'\t"
595 "%S='00'\t"
596 "%OS='00'\t"
597 "%p='AM'\t"
598 "%R='00:00'\t"
599 "%T='00:00:00'\t"
600 "%r='12:00:00 AM'\t"
601 "%X='00:00:00'\t"
602 "%EX='00:00:00'\t"
603 "\n"),
604 fmt,
605 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
606
607 check(SV("%H='23'\t"
608 "%OH='23'\t"
609 "%I='11'\t"
610 "%OI='11'\t"
611 "%M='31'\t"
612 "%OM='31'\t"
613 "%S='30.123'\t"
614 "%OS='30.123'\t"
615 "%p='PM'\t"
616 "%R='23:31'\t"
617 "%T='23:31:30.123'\t"
618 "%r='11:31:30 PM'\t"
619 "%X='23:31:30'\t"
620 "%EX='23:31:30'\t"
621 "\n"),
622 fmt,
623 std::chrono::utc_time<std::chrono::milliseconds>(
624 1'234'567'890'123ms + 24s)); // 23:31:30 UTC on Friday, 13 February 2009
625 // Use the global locale (fr_FR)
626 check(SV("%H='00'\t"
627 "%OH='00'\t"
628 "%I='12'\t"
629 "%OI='12'\t"
630 "%M='00'\t"
631 "%OM='00'\t"
632 "%S='00'\t"
633 "%OS='00'\t"
634#if defined(_AIX)
635 "%p='AM'\t"
636#else
637 "%p=''\t"
638#endif
639 "%R='00:00'\t"
640 "%T='00:00:00'\t"
641#ifdef _WIN32
642 "%r='00:00:00'\t"
643#elif defined(_AIX)
644 "%r='12:00:00 AM'\t"
645#elif defined(__APPLE__) || defined(__FreeBSD__)
646 "%r=''\t"
647#else
648 "%r='12:00:00 '\t"
649#endif
650 "%X='00:00:00'\t"
651 "%EX='00:00:00'\t"
652 "\n"),
653 lfmt,
654 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
655
656 check(SV("%H='23'\t"
657 "%OH='23'\t"
658 "%I='11'\t"
659 "%OI='11'\t"
660 "%M='31'\t"
661 "%OM='31'\t"
662 "%S='30,123'\t"
663 "%OS='30,123'\t"
664#if defined(_AIX)
665 "%p='PM'\t"
666#else
667 "%p=''\t"
668#endif
669 "%R='23:31'\t"
670 "%T='23:31:30,123'\t"
671#ifdef _WIN32
672 "%r='23:31:30'\t"
673#elif defined(_AIX)
674 "%r='11:31:30 PM'\t"
675#elif defined(__APPLE__) || defined(__FreeBSD__)
676 "%r=''\t"
677#else
678 "%r='11:31:30 '\t"
679#endif
680 "%X='23:31:30'\t"
681 "%EX='23:31:30'\t"
682 "\n"),
683 lfmt,
684 std::chrono::utc_time<std::chrono::milliseconds>(
685 1'234'567'890'123ms + 24s)); // 23:31:30 UTC on Friday, 13 February 2009
686
687 // Use supplied locale (ja_JP). This locale has a different alternate.
688#if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
689 check(loc,
690 SV("%H='00'\t"
691 "%OH='00'\t"
692 "%I='12'\t"
693 "%OI='12'\t"
694 "%M='00'\t"
695 "%OM='00'\t"
696 "%S='00'\t"
697 "%OS='00'\t"
698# if defined(__APPLE__)
699 "%p='AM'\t"
700# else
701 "%p='午前'\t"
702# endif
703 "%R='00:00'\t"
704 "%T='00:00:00'\t"
705# if defined(__APPLE__) || defined(__FreeBSD__)
706# if defined(__APPLE__)
707 "%r='12:00:00 AM'\t"
708# else
709 "%r='12:00:00 午前'\t"
710# endif
711 "%X='00時00分00秒'\t"
712 "%EX='00時00分00秒'\t"
713# elif defined(_WIN32)
714 "%r='0:00:00'\t"
715 "%X='0:00:00'\t"
716 "%EX='0:00:00'\t"
717# else
718 "%r='午前12:00:00'\t"
719 "%X='00:00:00'\t"
720 "%EX='00:00:00'\t"
721# endif
722 "\n"),
723 lfmt,
724 std::chrono::hh_mm_ss(0s));
725
726 check(loc,
727 SV("%H='23'\t"
728 "%OH='23'\t"
729 "%I='11'\t"
730 "%OI='11'\t"
731 "%M='31'\t"
732 "%OM='31'\t"
733 "%S='30.123'\t"
734 "%OS='30.123'\t"
735# if defined(__APPLE__)
736 "%p='PM'\t"
737# else
738 "%p='午後'\t"
739# endif
740 "%R='23:31'\t"
741 "%T='23:31:30.123'\t"
742# if defined(__APPLE__) || defined(__FreeBSD__)
743# if defined(__APPLE__)
744 "%r='11:31:30 PM'\t"
745# else
746 "%r='11:31:30 午後'\t"
747# endif
748 "%X='23時31分30秒'\t"
749 "%EX='23時31分30秒'\t"
750# elif defined(_WIN32)
751 "%r='23:31:30'\t"
752 "%X='23:31:30'\t"
753 "%EX='23:31:30'\t"
754# else
755 "%r='午後11:31:30'\t"
756 "%X='23:31:30'\t"
757 "%EX='23:31:30'\t"
758# endif
759 "\n"),
760 lfmt,
761 std::chrono::hh_mm_ss(23h + 31min + 30s + 123ms));
762#else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
763 check(loc,
764 SV("%H='00'\t"
765 "%OH='〇'\t"
766 "%I='12'\t"
767 "%OI='十二'\t"
768 "%M='00'\t"
769 "%OM='〇'\t"
770 "%S='00'\t"
771 "%OS='〇'\t"
772 "%p='午前'\t"
773 "%R='00:00'\t"
774 "%T='00:00:00'\t"
775 "%r='午前12時00分00秒'\t"
776 "%X='00時00分00秒'\t"
777 "%EX='00時00分00秒'\t"
778 "\n"),
779 lfmt,
780 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
781
782 check(loc,
783 SV("%H='23'\t"
784 "%OH='二十三'\t"
785 "%I='11'\t"
786 "%OI='十一'\t"
787 "%M='31'\t"
788 "%OM='三十一'\t"
789 "%S='30.123'\t"
790 "%OS='三十.123'\t"
791 "%p='午後'\t"
792 "%R='23:31'\t"
793 "%T='23:31:30.123'\t"
794 "%r='午後11時31分30秒'\t"
795 "%X='23時31分30秒'\t"
796 "%EX='23時31分30秒'\t"
797 "\n"),
798 lfmt,
799 std::chrono::utc_time<std::chrono::milliseconds>(
800 1'234'567'890'123ms + 24s)); // 23:31:30 UTC on Friday, 13 February 2009
801#endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
802
803 std::locale::global(loc: std::locale::classic());
804}
805
806template <class CharT>
807static void test_valid_values_date_time() {
808 using namespace std::literals::chrono_literals;
809
810 constexpr std::basic_string_view<CharT> fmt = SV("{:%%c='%c'%t%%Ec='%Ec'%n}");
811 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%c='%c'%t%%Ec='%Ec'%n}");
812
813 const std::locale loc(LOCALE_ja_JP_UTF_8);
814 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
815
816 // Non localized output using C-locale
817 check(SV("%c='Thu Jan 1 00:00:00 1970'\t%Ec='Thu Jan 1 00:00:00 1970'\n"),
818 fmt,
819 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
820
821 check(SV("%c='Fri Feb 13 23:31:30 2009'\t%Ec='Fri Feb 13 23:31:30 2009'\n"),
822 fmt,
823 std::chrono::utc_seconds(1'234'567'890s + 24s)); // 23:31:30 UTC on Friday, 13 February 2009
824
825 // Use the global locale (fr_FR)
826 check(
827// https://sourceware.org/bugzilla/show_bug.cgi?id=24054
828#if defined(__powerpc__) && defined(__linux__)
829 SV("%c='jeu. 01 janv. 1970 00:00:00 UTC'\t%Ec='jeu. 01 janv. 1970 00:00:00 UTC'\n"),
830#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
831 SV("%c='jeu. 01 janv. 1970 00:00:00 GMT'\t%Ec='jeu. 01 janv. 1970 00:00:00 GMT'\n"),
832#elif defined(_AIX)
833 SV("%c=' 1 janvier 1970 à 00:00:00 UTC'\t%Ec=' 1 janvier 1970 à 00:00:00 UTC'\n"),
834#elif defined(__APPLE__)
835 SV("%c='Jeu 1 jan 00:00:00 1970'\t%Ec='Jeu 1 jan 00:00:00 1970'\n"),
836#elif defined(_WIN32)
837 SV("%c='01/01/1970 00:00:00'\t%Ec='01/01/1970 00:00:00'\n"),
838#elif defined(__FreeBSD__)
839 SV("%c='jeu. 1 janv. 00:00:00 1970'\t%Ec='jeu. 1 janv. 00:00:00 1970'\n"),
840#else
841 SV("%c='jeu. 01 janv. 1970 00:00:00'\t%Ec='jeu. 01 janv. 1970 00:00:00'\n"),
842#endif
843 lfmt,
844 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
845
846 check(
847// https://sourceware.org/bugzilla/show_bug.cgi?id=24054
848#if defined(__powerpc__) && defined(__linux__)
849 SV("%c='ven. 13 févr. 2009 23:31:30 UTC'\t%Ec='ven. 13 févr. 2009 23:31:30 UTC'\n"),
850#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
851 SV("%c='ven. 13 févr. 2009 23:31:30 GMT'\t%Ec='ven. 13 févr. 2009 23:31:30 GMT'\n"),
852#elif defined(_AIX)
853 SV("%c='13 février 2009 à 23:31:30 UTC'\t%Ec='13 février 2009 à 23:31:30 UTC'\n"),
854#elif defined(__APPLE__)
855 SV("%c='Ven 13 fév 23:31:30 2009'\t%Ec='Ven 13 fév 23:31:30 2009'\n"),
856#elif defined(_WIN32)
857 SV("%c='13/02/2009 23:31:30'\t%Ec='13/02/2009 23:31:30'\n"),
858#elif defined(__FreeBSD__)
859 SV("%c='ven. 13 févr. 23:31:30 2009'\t%Ec='ven. 13 févr. 23:31:30 2009'\n"),
860#else
861 SV("%c='ven. 13 févr. 2009 23:31:30'\t%Ec='ven. 13 févr. 2009 23:31:30'\n"),
862#endif
863 lfmt,
864 std::chrono::utc_seconds(1'234'567'890s + 24s)); // 23:31:30 UTC on Friday, 13 February 2009
865
866 // Use supplied locale (ja_JP). This locale has a different alternate.a
867#if defined(__APPLE__) || defined(__FreeBSD__)
868 check(loc,
869 SV("%c='木 1/ 1 00:00:00 1970'\t%Ec='木 1/ 1 00:00:00 1970'\n"),
870 lfmt,
871 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
872 check(loc,
873 SV("%c='金 2/13 23:31:30 2009'\t%Ec='金 2/13 23:31:30 2009'\n"),
874 lfmt,
875 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
876#elif defined(_AIX) // defined(__APPLE__)|| defined(__FreeBSD__)
877 check(loc,
878 SV("%c='1970年01月 1日 00:00:00 UTC'\t%Ec='1970年01月 1日 00:00:00 UTC'\n"),
879 lfmt,
880 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
881 check(loc,
882 SV("%c='2009年02月13日 23:31:30 UTC'\t%Ec='2009年02月13日 23:31:30 UTC'\n"),
883 lfmt,
884 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
885#elif defined(_WIN32) // defined(__APPLE__)|| defined(__FreeBSD__)
886 check(loc,
887 SV("%c='1970/01/01 0:00:00'\t%Ec='1970/01/01 0:00:00'\n"),
888 lfmt,
889 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
890 check(loc,
891 SV("%c='2009/02/13 23:31:30'\t%Ec='2009/02/13 23:31:30'\n"),
892 lfmt,
893 std::chrono::utc_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
894#else // defined(__APPLE__)|| defined(__FreeBSD__)
895 check(loc,
896 SV("%c='1970年01月01日 00時00分00秒'\t%Ec='昭和45年01月01日 00時00分00秒'\n"),
897 lfmt,
898 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
899
900 check(loc,
901 SV("%c='2009年02月13日 23時31分30秒'\t%Ec='平成21年02月13日 23時31分30秒'\n"),
902 lfmt,
903 std::chrono::utc_seconds(1'234'567'890s + 24s)); // 23:31:30 UTC on Friday, 13 February 2009
904#endif // defined(__APPLE__)|| defined(__FreeBSD__)
905
906 std::locale::global(loc: std::locale::classic());
907}
908
909template <class CharT>
910static void test_valid_values_time_zone() {
911 using namespace std::literals::chrono_literals;
912
913 constexpr std::basic_string_view<CharT> fmt = SV("{:%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
914 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
915
916 const std::locale loc(LOCALE_ja_JP_UTF_8);
917 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
918
919 // Non localized output using C-locale
920 check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='UTC'\n"),
921 fmt,
922 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
923
924 // Use the global locale (fr_FR)
925 check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='UTC'\n"),
926 lfmt,
927 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
928
929 // Use supplied locale (ja_JP).
930 check(loc,
931 SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='UTC'\n"),
932 lfmt,
933 std::chrono::utc_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
934
935 std::locale::global(loc: std::locale::classic());
936}
937
938template <class CharT>
939static void test_utc_transitions() {
940 using namespace std::literals::chrono_literals;
941
942 constexpr std::basic_string_view<CharT> fmt = SV("{:%F %T}");
943 check(SV("1972-06-30 23:59:59"), fmt, std::chrono::utc_seconds(78'796'799s));
944 check(SV("1972-06-30 23:59:60"), fmt, std::chrono::utc_seconds(78'796'800s));
945 check(SV("1972-07-01 00:00:00"), fmt, std::chrono::utc_seconds(78'796'801s));
946
947 check(SV("1972-12-31 23:59:59"), fmt, std::chrono::utc_seconds(94'694'400s));
948 check(SV("1972-12-31 23:59:60"), fmt, std::chrono::utc_seconds(94'694'401s));
949 check(SV("1973-01-01 00:00:00"), fmt, std::chrono::utc_seconds(94'694'402s));
950}
951
952template <class CharT>
953static void test_valid_values() {
954 test_valid_values_year<CharT>();
955 test_valid_values_month<CharT>();
956 test_valid_values_day<CharT>();
957 test_valid_values_weekday<CharT>();
958 test_valid_values_day_of_year<CharT>();
959 test_valid_values_week<CharT>();
960 test_valid_values_iso_8601_week<CharT>();
961 test_valid_values_date<CharT>();
962 test_valid_values_time<CharT>();
963 test_valid_values_date_time<CharT>();
964 test_valid_values_time_zone<CharT>();
965
966 test_utc_transitions<CharT>();
967}
968
969// In order to have the UTC seconds the number of leap seconds need to be
970// included in the UTC time. The number of leap seconds for times far in the
971// future are not yet known and may change in the future.
972template <class CharT>
973static void test() {
974 using namespace std::literals::chrono_literals;
975
976 test_no_chrono_specs<CharT>();
977 test_valid_values<CharT>();
978 check_invalid_types<CharT>(
979 {SV("a"), SV("A"), SV("b"), SV("B"), SV("c"), SV("C"), SV("d"), SV("D"), SV("e"), SV("F"), SV("g"),
980 SV("G"), SV("h"), SV("H"), SV("I"), SV("j"), SV("m"), SV("M"), SV("p"), SV("r"), SV("R"), SV("S"),
981 SV("T"), SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("X"), SV("y"), SV("Y"), SV("z"),
982 SV("Z"), SV("Ec"), SV("EC"), SV("Ex"), SV("EX"), SV("Ey"), SV("EY"), SV("Ez"), SV("Od"), SV("Oe"), SV("OH"),
983 SV("OI"), SV("Om"), SV("OM"), SV("OS"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), SV("Oz")},
984 std::chrono::utc_seconds(0s));
985
986 check_exception("The format specifier expects a '%' or a '}'", SV("{:A"), std::chrono::utc_seconds(0s));
987 check_exception("The chrono specifiers contain a '{'", SV("{:%%{"), std::chrono::utc_seconds(0s));
988 check_exception("End of input while parsing a conversion specifier", SV("{:%"), std::chrono::utc_seconds(0s));
989 check_exception("End of input while parsing the modifier E", SV("{:%E"), std::chrono::utc_seconds(0s));
990 check_exception("End of input while parsing the modifier O", SV("{:%O"), std::chrono::utc_seconds(0s));
991
992 // Precision not allowed
993 check_exception("The format specifier expects a '%' or a '}'", SV("{:.3}"), std::chrono::utc_seconds(0s));
994}
995
996int main(int, char**) {
997 test<char>();
998
999#ifndef TEST_HAS_NO_WIDE_CHARACTERS
1000 test<wchar_t>();
1001#endif
1002
1003 return 0;
1004}
1005

source code of libcxx/test/std/time/time.syn/formatter.utc_time.pass.cpp