xref: /llvm-project/libcxx/test/std/time/time.syn/formatter.year_month_weekday.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::year_month_weekday, 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 "string_literal.h"
36 #include "test_macros.h"
37 
38 template <class CharT>
39 static void test_no_chrono_specs() {
40   // Valid year, valid month, valid day, valid index
41   check(SV("1970/Jan/Mon[1]"),
42         SV("{}"),
43         std::chrono::year_month_weekday{
44             std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
45   check(SV("*1970/Jan/Mon[1]"),
46         SV("{:*>16}"),
47         std::chrono::year_month_weekday{
48             std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
49   check(SV("*1970/Jan/Mon[1]*"),
50         SV("{:*^17}"),
51         std::chrono::year_month_weekday{
52             std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
53 
54   // Valid year, valid month, valid day, invalid index
55   check(SV("1970/Jan/Mon[7 is not a valid index]"),
56         SV("{}"),
57         std::chrono::year_month_weekday{
58             std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}});
59 
60   // Valid year, valid month, invalid day, valid index
61   check(SV("1970/Jan/13 is not a valid weekday[1]"),
62         SV("{}"),
63         std::chrono::year_month_weekday{
64             std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
65 
66   // Valid year, valid month, invalid day, invalid index
67   check(SV("1970/Jan/13 is not a valid weekday[7 is not a valid index]"),
68         SV("{}"),
69         std::chrono::year_month_weekday{
70             std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}});
71 
72   // Valid year, invalid month, valid day, invalid index
73   check(SV("1970/0 is not a valid month/Mon[7 is not a valid index]"),
74         SV("{}"),
75         std::chrono::year_month_weekday{
76             std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}});
77 
78   // Valid year, invalid month, invalid day, valid index
79   check(SV("1970/0 is not a valid month/13 is not a valid weekday[1]"),
80         SV("{}"),
81         std::chrono::year_month_weekday{
82             std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
83 
84   // Valid year, invalid month, invalid day, invalid index
85   check(SV("1970/0 is not a valid month/13 is not a valid weekday[7 is not a valid index]"),
86         SV("{}"),
87         std::chrono::year_month_weekday{
88             std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}});
89 
90   // Invalid year, valid month, valid day, valid index
91   check(
92       SV("-32768 is not a valid year/Jan/Mon[1]"),
93       SV("{}"),
94       std::chrono::year_month_weekday{
95           std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
96 
97   // Invalid year, valid month, valid day, invalid index
98   check(
99       SV("-32768 is not a valid year/Jan/Mon[7 is not a valid index]"),
100       SV("{}"),
101       std::chrono::year_month_weekday{
102           std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}});
103 
104   // Invalid year, valid month, invalid day, valid index
105   check(
106       SV("-32768 is not a valid year/Jan/13 is not a valid weekday[1]"),
107       SV("{}"),
108       std::chrono::year_month_weekday{
109           std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
110 
111   // Invalid year, valid month, invalid day, invalid index
112   check(
113       SV("-32768 is not a valid year/Jan/13 is not a valid weekday[7 is not a valid index]"),
114       SV("{}"),
115       std::chrono::year_month_weekday{
116           std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}});
117 
118   // Invalid year, invalid month, valid day, invalid index
119   check(
120       SV("-32768 is not a valid year/0 is not a valid month/Mon[7 is not a valid index]"),
121       SV("{}"),
122       std::chrono::year_month_weekday{
123           std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}});
124 
125   // Invalid year, invalid month, invalid day, valid index
126   check(
127       SV("-32768 is not a valid year/0 is not a valid month/13 is not a valid weekday[1]"),
128       SV("{}"),
129       std::chrono::year_month_weekday{
130           std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
131 
132   // Invalid year, invalid month, invalid day, invalid index
133   check(
134       SV("-32768 is not a valid year/0 is not a valid month/13 is not a valid weekday[7 is not a valid index]"),
135       SV("{}"),
136       std::chrono::year_month_weekday{
137           std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}});
138 }
139 
140 // TODO FMT Should x throw?
141 template <class CharT>
142 static void test_invalid_values() {
143   // Test that %a, %A, %b, %B, %h, %j, %u, %U, %V, %w, %W, %Ou, %OU, %OV, %Ow, and %OW throw an exception.
144   check_exception(
145       "Formatting a weekday name needs a valid weekday",
146       SV("{:%a}"),
147       std::chrono::year_month_weekday{
148           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
149 
150   check_exception(
151       "Formatting a weekday name needs a valid weekday",
152       SV("{:%A}"),
153       std::chrono::year_month_weekday{
154           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
155 
156   check_exception(
157       "Formatting a month name from an invalid month number",
158       SV("{:%b}"),
159       std::chrono::year_month_weekday{
160           std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
161 
162   check_exception(
163       "Formatting a month name from an invalid month number",
164       SV("{:%B}"),
165       std::chrono::year_month_weekday{
166           std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
167 
168   check_exception(
169       "Formatting a month name from an invalid month number",
170       SV("{:%h}"),
171       std::chrono::year_month_weekday{
172           std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
173 
174   check_exception(
175       "Formatting a day of year needs a valid date",
176       SV("{:%j}"),
177       std::chrono::year_month_weekday{
178           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}});
179   check_exception(
180       "Formatting a day of year needs a valid date",
181       SV("{:%j}"),
182       std::chrono::year_month_weekday{
183           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
184   check_exception(
185       "Formatting a day of year needs a valid date",
186       SV("{:%j}"),
187       std::chrono::year_month_weekday{
188           std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
189   check_exception(
190       "Formatting a day of year needs a valid date",
191       SV("{:%j}"),
192       std::chrono::year_month_weekday{
193           std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
194 
195   check_exception(
196       "Formatting a weekday needs a valid weekday",
197       SV("{:%u}"),
198       std::chrono::year_month_weekday{
199           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
200 
201   check_exception(
202       "Formatting a week of year needs a valid date",
203       SV("{:%U}"),
204       std::chrono::year_month_weekday{
205           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}});
206   check_exception(
207       "Formatting a week of year needs a valid date",
208       SV("{:%U}"),
209       std::chrono::year_month_weekday{
210           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
211   check_exception(
212       "Formatting a week of year needs a valid date",
213       SV("{:%U}"),
214       std::chrono::year_month_weekday{
215           std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
216   check_exception(
217       "Formatting a week of year needs a valid date",
218       SV("{:%U}"),
219       std::chrono::year_month_weekday{
220           std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
221 
222   check_exception(
223       "Formatting a week of year needs a valid date",
224       SV("{:%V}"),
225       std::chrono::year_month_weekday{
226           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}});
227   check_exception(
228       "Formatting a week of year needs a valid date",
229       SV("{:%V}"),
230       std::chrono::year_month_weekday{
231           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
232   check_exception(
233       "Formatting a week of year needs a valid date",
234       SV("{:%V}"),
235       std::chrono::year_month_weekday{
236           std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
237   check_exception(
238       "Formatting a week of year needs a valid date",
239       SV("{:%V}"),
240       std::chrono::year_month_weekday{
241           std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
242 
243   check_exception(
244       "Formatting a weekday needs a valid weekday",
245       SV("{:%w}"),
246       std::chrono::year_month_weekday{
247           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
248 
249   check_exception(
250       "Formatting a week of year needs a valid date",
251       SV("{:%W}"),
252       std::chrono::year_month_weekday{
253           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}});
254   check_exception(
255       "Formatting a week of year needs a valid date",
256       SV("{:%W}"),
257       std::chrono::year_month_weekday{
258           std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}});
259   check_exception(
260       "Formatting a week of year needs a valid date",
261       SV("{:%W}"),
262       std::chrono::year_month_weekday{
263           std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
264   check_exception(
265       "Formatting a week of year needs a valid date",
266       SV("{:%W}"),
267       std::chrono::year_month_weekday{
268           std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
269 }
270 
271 template <class CharT>
272 static void test_valid_md_values() {
273   constexpr std::basic_string_view<CharT> fmt =
274       SV("{:%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%t%%Oe='%Oe'%n}");
275   constexpr std::basic_string_view<CharT> lfmt =
276       SV("{:L%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%t%%Oe='%Oe'%n}");
277 
278   const std::locale loc(LOCALE_ja_JP_UTF_8);
279   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
280 
281   // Non localized output using C-locale
282 
283   check(SV("%b='Jan'\t%B='January'\t%h='Jan'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"),
284         fmt,
285         std::chrono::year_month_weekday{
286             std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
287   check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"),
288         fmt,
289         std::chrono::year_month_weekday{
290             std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}});
291 
292   // Use the global locale (fr_FR)
293 #if defined(__APPLE__)
294   check(SV("%b='jan'\t%B='janvier'\t%h='jan'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"),
295         lfmt,
296         std::chrono::year_month_weekday{
297             std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
298 
299   check(SV("%b='déc'\t%B='décembre'\t%h='déc'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"),
300         lfmt,
301         std::chrono::year_month_weekday{
302             std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}});
303 
304 #else  // defined(__APPLE__)
305   check(SV("%b='janv.'\t%B='janvier'\t%h='janv.'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"),
306         lfmt,
307         std::chrono::year_month_weekday{
308             std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
309   check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"),
310         lfmt,
311         std::chrono::year_month_weekday{
312             std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}});
313 
314 #endif // defined(__APPLE__)
315 
316   // Use supplied locale (ja_JP)
317 #if defined(_WIN32)
318   check(loc,
319         SV("%b='1'\t%B='1月'\t%h='1'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"),
320         lfmt,
321         std::chrono::year_month_weekday{
322             std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
323 
324   check(loc,
325         SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"),
326         lfmt,
327         std::chrono::year_month_weekday{
328             std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}});
329 
330 #elif defined(_AIX) // defined(_WIN32)
331   check(loc,
332         SV("%b='1月'\t%B='1月'\t%h='1月'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"),
333         lfmt,
334         std::chrono::year_month_weekday{
335             std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
336 
337   check(loc,
338         SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"),
339         lfmt,
340         std::chrono::year_month_weekday{
341             std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}});
342 
343 #elif defined(__APPLE__) // defined(_WIN32)
344   check(loc,
345         SV("%b=' 1'\t%B='1月'\t%h=' 1'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"),
346         lfmt,
347         std::chrono::year_month_weekday{
348             std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
349 
350   check(loc,
351         SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"),
352         lfmt,
353         std::chrono::year_month_weekday{
354             std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}});
355 
356 #elif defined(__FreeBSD__) // defined(_WIN32)
357   check(loc,
358         SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"),
359         lfmt,
360         std::chrono::year_month_weekday{
361             std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
362 
363   check(loc,
364         SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"),
365         lfmt,
366         std::chrono::year_month_weekday{
367             std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}});
368 #else                    // defined(_WIN32)
369   check(loc,
370         SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='一'\t%d='01'\t%e=' 1'\t%Od='一'\t%Oe='一'\n"),
371         lfmt,
372         std::chrono::year_month_weekday{
373             std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
374 
375   check(loc,
376         SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='十二'\t%d='20'\t%e='20'\t%Od='二十'\t%Oe='二十'\n"),
377         lfmt,
378         std::chrono::year_month_weekday{
379             std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}});
380 
381 #endif                   //  defined(_WIN32)
382 
383   std::locale::global(std::locale::classic());
384 }
385 
386 template <class CharT>
387 static void test_valid_ymd_values() {
388   constexpr std::basic_string_view<CharT> fmt = SV(
389       "{:"
390       "%%C='%C'%t"
391       "%%D='%D'%t"
392       "%%F='%F'%t"
393       "%%j='%j'%t"
394       "%%g='%g'%t"
395       "%%G='%G'%t"
396       "%%u='%u'%t"
397       "%%U='%U'%t"
398       "%%V='%V'%t"
399       "%%w='%w'%t"
400       "%%W='%W'%t"
401       "%%x='%x'%t"
402       "%%y='%y'%t"
403       "%%Y='%Y'%t"
404       "%%Ex='%Ex'%t"
405       "%%EC='%EC'%t"
406       "%%Ey='%Ey'%t"
407       "%%EY='%EY'%t"
408       "%%Ou='%Ou'%t"
409       "%%OU='%OU'%t"
410       "%%OV='%OV'%t"
411       "%%Ow='%Ow'%t"
412       "%%OW='%OW'%t"
413       "%%Oy='%Oy'%t"
414       "%n}");
415 
416   constexpr std::basic_string_view<CharT> lfmt = SV(
417       "{:L"
418       "%%C='%C'%t"
419       "%%D='%D'%t"
420       "%%F='%F'%t"
421       "%%j='%j'%t"
422       "%%g='%g'%t"
423       "%%G='%G'%t"
424       "%%u='%u'%t"
425       "%%U='%U'%t"
426       "%%V='%V'%t"
427       "%%w='%w'%t"
428       "%%W='%W'%t"
429       "%%x='%x'%t"
430       "%%y='%y'%t"
431       "%%Y='%Y'%t"
432       "%%Ex='%Ex'%t"
433       "%%EC='%EC'%t"
434       "%%Ey='%Ey'%t"
435       "%%EY='%EY'%t"
436       "%%Ou='%Ou'%t"
437       "%%OU='%OU'%t"
438       "%%OV='%OV'%t"
439       "%%Ow='%Ow'%t"
440       "%%OW='%OW'%t"
441       "%%Oy='%Oy'%t"
442       "%n}");
443 
444   const std::locale loc(LOCALE_ja_JP_UTF_8);
445   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
446 
447   // Non localized output using C-locale
448   check(
449       SV("%C='19'\t"
450          "%D='01/01/70'\t"
451          "%F='1970-01-01'\t"
452          "%j='001'\t"
453          "%g='70'\t"
454          "%G='1970'\t"
455          "%u='4'\t"
456          "%U='00'\t"
457          "%V='01'\t"
458          "%w='4'\t"
459          "%W='00'\t"
460          "%x='01/01/70'\t"
461          "%y='70'\t"
462          "%Y='1970'\t"
463          "%Ex='01/01/70'\t"
464          "%EC='19'\t"
465          "%Ey='70'\t"
466          "%EY='1970'\t"
467          "%Ou='4'\t"
468          "%OU='00'\t"
469          "%OV='01'\t"
470          "%Ow='4'\t"
471          "%OW='00'\t"
472          "%Oy='70'\t"
473          "\n"),
474       fmt,
475       std::chrono::year_month_weekday{
476           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
477 
478   check(
479       SV("%C='20'\t"
480          "%D='05/29/04'\t"
481          "%F='2004-05-29'\t"
482          "%j='150'\t"
483          "%g='04'\t"
484          "%G='2004'\t"
485          "%u='6'\t"
486          "%U='21'\t"
487          "%V='22'\t"
488          "%w='6'\t"
489          "%W='21'\t"
490          "%x='05/29/04'\t"
491          "%y='04'\t"
492          "%Y='2004'\t"
493          "%Ex='05/29/04'\t"
494          "%EC='20'\t"
495          "%Ey='04'\t"
496          "%EY='2004'\t"
497          "%Ou='6'\t"
498          "%OU='21'\t"
499          "%OV='22'\t"
500          "%Ow='6'\t"
501          "%OW='21'\t"
502          "%Oy='04'\t"
503          "\n"),
504       fmt,
505       std::chrono::year_month_weekday{
506           std::chrono::year{2004}, std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{6}, 5}});
507 
508   // Use the global locale (fr_FR)
509   check(
510       SV("%C='19'\t"
511          "%D='01/01/70'\t"
512          "%F='1970-01-01'\t"
513          "%j='001'\t"
514          "%g='70'\t"
515          "%G='1970'\t"
516          "%u='4'\t"
517          "%U='00'\t"
518          "%V='01'\t"
519          "%w='4'\t"
520          "%W='00'\t"
521 #if defined(__APPLE__) || defined(__FreeBSD__)
522          "%x='01.01.1970'\t"
523 #else
524          "%x='01/01/1970'\t"
525 #endif
526          "%y='70'\t"
527          "%Y='1970'\t"
528 #if defined(__APPLE__) || defined(__FreeBSD__)
529          "%Ex='01.01.1970'\t"
530 #else
531          "%Ex='01/01/1970'\t"
532 #endif
533          "%EC='19'\t"
534          "%Ey='70'\t"
535          "%EY='1970'\t"
536          "%Ou='4'\t"
537          "%OU='00'\t"
538          "%OV='01'\t"
539          "%Ow='4'\t"
540          "%OW='00'\t"
541          "%Oy='70'\t"
542          "\n"),
543       lfmt,
544       std::chrono::year_month_weekday{
545           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
546 
547   check(
548       SV("%C='20'\t"
549          "%D='05/29/04'\t"
550          "%F='2004-05-29'\t"
551          "%j='150'\t"
552          "%g='04'\t"
553          "%G='2004'\t"
554          "%u='6'\t"
555          "%U='21'\t"
556          "%V='22'\t"
557          "%w='6'\t"
558          "%W='21'\t"
559 #if defined(__APPLE__) || defined(__FreeBSD__)
560          "%x='29.05.2004'\t"
561 #else
562          "%x='29/05/2004'\t"
563 #endif
564          "%y='04'\t"
565          "%Y='2004'\t"
566 #if defined(__APPLE__) || defined(__FreeBSD__)
567          "%Ex='29.05.2004'\t"
568 #else
569          "%Ex='29/05/2004'\t"
570 #endif
571          "%EC='20'\t"
572          "%Ey='04'\t"
573          "%EY='2004'\t"
574          "%Ou='6'\t"
575          "%OU='21'\t"
576          "%OV='22'\t"
577          "%Ow='6'\t"
578          "%OW='21'\t"
579          "%Oy='04'\t"
580          "\n"),
581       lfmt,
582       std::chrono::year_month_weekday{
583           std::chrono::year{2004}, std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{6}, 5}});
584 
585   // Use supplied locale (ja_JP)
586   check(
587       loc,
588       SV("%C='19'\t"
589          "%D='01/01/70'\t"
590          "%F='1970-01-01'\t"
591          "%j='001'\t"
592          "%g='70'\t"
593          "%G='1970'\t"
594          "%u='4'\t"
595          "%U='00'\t"
596          "%V='01'\t"
597          "%w='4'\t"
598          "%W='00'\t"
599 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
600          "%x='1970/01/01'\t"
601 #else  // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
602          "%x='1970年01月01日'\t"
603 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
604          "%y='70'\t"
605          "%Y='1970'\t"
606 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
607          "%Ex='1970/01/01'\t"
608          "%EC='19'\t"
609          "%Ey='70'\t"
610          "%EY='1970'\t"
611          "%Ou='4'\t"
612          "%OU='00'\t"
613          "%OV='01'\t"
614          "%Ow='4'\t"
615          "%OW='00'\t"
616          "%Oy='70'\t"
617 #else  // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
618          "%Ex='昭和45年01月01日'\t"
619          "%EC='昭和'\t"
620          "%Ey='45'\t"
621          "%EY='昭和45年'\t"
622          "%Ou='四'\t"
623          "%OU='〇'\t"
624          "%OV='一'\t"
625          "%Ow='四'\t"
626          "%OW='〇'\t"
627          "%Oy='七十'\t"
628 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
629          "\n"),
630       lfmt,
631       std::chrono::year_month_weekday{
632           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}});
633 
634   check(
635       loc,
636       SV("%C='20'\t"
637          "%D='05/29/04'\t"
638          "%F='2004-05-29'\t"
639          "%j='150'\t"
640          "%g='04'\t"
641          "%G='2004'\t"
642          "%u='6'\t"
643          "%U='21'\t"
644          "%V='22'\t"
645          "%w='6'\t"
646          "%W='21'\t"
647 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
648          "%x='2004/05/29'\t"
649 #else  // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
650          "%x='2004年05月29日'\t"
651 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
652          "%y='04'\t"
653          "%Y='2004'\t"
654 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
655          "%Ex='2004/05/29'\t"
656          "%EC='20'\t"
657          "%Ey='04'\t"
658          "%EY='2004'\t"
659          "%Ou='6'\t"
660          "%OU='21'\t"
661          "%OV='22'\t"
662          "%Ow='6'\t"
663          "%OW='21'\t"
664          "%Oy='04'\t"
665 #else  // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
666          "%Ex='平成16年05月29日'\t"
667          "%EC='平成'\t"
668          "%Ey='16'\t"
669          "%EY='平成16年'\t"
670          "%Ou='六'\t"
671          "%OU='二十一'\t"
672          "%OV='二十二'\t"
673          "%Ow='六'\t"
674          "%OW='二十一'\t"
675          "%Oy='四'\t"
676 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
677          "\n"),
678       lfmt,
679       std::chrono::year_month_weekday{
680           std::chrono::year{2004}, std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{6}, 5}});
681 
682   std::locale::global(std::locale::classic());
683 }
684 
685 template <class CharT>
686 static void test_valid_values() {
687   // Fields only using month and day.
688   test_valid_md_values<CharT>();
689   // Fields only using year, month, and day.
690   test_valid_ymd_values<CharT>();
691 }
692 
693 template <class CharT>
694 static void test() {
695   test_no_chrono_specs<CharT>();
696   test_invalid_values<CharT>();
697   test_valid_values<CharT>();
698   check_invalid_types<CharT>(
699       {SV("a"),  SV("A"),  SV("b"),  SV("B"),  SV("C"),  SV("d"),  SV("D"),  SV("e"),  SV("EC"),
700        SV("Ex"), SV("Ey"), SV("EY"), SV("F"),  SV("g"),  SV("G"),  SV("h"),  SV("j"),  SV("m"),
701        SV("Od"), SV("Oe"), SV("Om"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"),
702        SV("u"),  SV("U"),  SV("V"),  SV("w"),  SV("W"),  SV("x"),  SV("y"),  SV("Y")},
703       std::chrono::year_month_weekday{
704           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
705 
706   check_exception(
707       "The format specifier expects a '%' or a '}'",
708       SV("{:A"),
709       std::chrono::year_month_weekday{
710           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
711   check_exception(
712       "The chrono specifiers contain a '{'",
713       SV("{:%%{"),
714       std::chrono::year_month_weekday{
715           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
716   check_exception(
717       "End of input while parsing a conversion specifier",
718       SV("{:%"),
719       std::chrono::year_month_weekday{
720           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
721   check_exception(
722       "End of input while parsing the modifier E",
723       SV("{:%E"),
724       std::chrono::year_month_weekday{
725           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
726   check_exception(
727       "End of input while parsing the modifier O",
728       SV("{:%O"),
729       std::chrono::year_month_weekday{
730           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
731 
732   // Precision not allowed
733   check_exception(
734       "The format specifier expects a '%' or a '}'",
735       SV("{:.3}"),
736       std::chrono::year_month_weekday{
737           std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}});
738 }
739 
740 int main(int, char**) {
741   test<char>();
742 
743 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
744   test<wchar_t>();
745 #endif
746 
747   return 0;
748 }
749