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