xref: /llvm-project/libcxx/test/std/time/time.syn/formatter.utc_time.pass.cpp (revision 0cd794d4860e376698bb4da24bcdf8cbf331835c)
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 
40 template <class CharT>
41 static 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(std::locale::classic());
78 }
79 
80 template <class CharT>
81 static 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(std::locale::classic());
134 }
135 
136 template <class CharT>
137 static 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(std::locale::classic());
224 }
225 
226 template <class CharT>
227 static 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(std::locale::classic());
279 }
280 
281 template <class CharT>
282 static 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(std::locale::classic());
346 }
347 
348 template <class CharT>
349 static 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(std::locale::classic());
373 }
374 
375 template <class CharT>
376 static 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(std::locale::classic());
426 }
427 
428 template <class CharT>
429 static 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(std::locale::classic());
480 }
481 
482 template <class CharT>
483 static 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(std::locale::classic());
544 }
545 
546 template <class CharT>
547 static 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(std::locale::classic());
804 }
805 
806 template <class CharT>
807 static 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(std::locale::classic());
907 }
908 
909 template <class CharT>
910 static 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(std::locale::classic());
936 }
937 
938 template <class CharT>
939 static 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 
952 template <class CharT>
953 static 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.
972 template <class CharT>
973 static 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 
996 int 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