xref: /llvm-project/libcxx/test/std/time/time.syn/formatter.weekday_index.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 // TODO FMT Investigate Windows issues.
17 // XFAIL: msvc
18 
19 // REQUIRES: locale.fr_FR.UTF-8
20 // REQUIRES: locale.ja_JP.UTF-8
21 
22 // <chrono>
23 
24 // template<class charT> struct formatter<chrono::weekday_index, 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   // Valid weekday valid index
45   check(SV("Sun[1]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(0), 1});
46 
47   // Invalid weekday valid index
48   check(SV("8 is not a valid weekday[1]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
49   check(SV("255 is not a valid weekday[1]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
50 
51   // Valid weekday invalid index
52   check(SV("Sun[0 is not a valid index]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
53   check(SV("Sun[6 is not a valid index]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(0), 6});
54   check(SV("Sun[255 is not a valid index]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(0), 255});
55 
56   // Invalid weekday invalid index
57   check(SV("8 is not a valid weekday[0 is not a valid index]"),
58         SV("{}"),
59         std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
60   check(SV("127 is not a valid weekday[6 is not a valid index]"),
61         SV("{}"),
62         std::chrono::weekday_indexed{std::chrono::weekday(127), 6});
63   check(SV("255 is not a valid weekday[255 is not a valid index]"),
64         SV("{}"),
65         std::chrono::weekday_indexed{std::chrono::weekday(255), 255});
66 }
67 
68 template <class CharT>
69 static void test_valid_values() {
70   constexpr std::basic_string_view<CharT> fmt =
71       SV("{:%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%n}");
72   constexpr std::basic_string_view<CharT> lfmt =
73       SV("{:L%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%n}");
74 
75   const std::locale loc(LOCALE_ja_JP_UTF_8);
76   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
77 
78   // Non localized output using C-locale
79   check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"),
80         fmt,
81         std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
82   check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Mon'\t%A='Monday'\n"),
83         fmt,
84         std::chrono::weekday_indexed{std::chrono::weekday(1), 1});
85   check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Tue'\t%A='Tuesday'\n"),
86         fmt,
87         std::chrono::weekday_indexed{std::chrono::weekday(2), 2});
88   check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Wed'\t%A='Wednesday'\n"),
89         fmt,
90         std::chrono::weekday_indexed{std::chrono::weekday(3), 3});
91   check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Thu'\t%A='Thursday'\n"),
92         fmt,
93         std::chrono::weekday_indexed{std::chrono::weekday(4), 4});
94   check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Fri'\t%A='Friday'\n"),
95         fmt,
96         std::chrono::weekday_indexed{std::chrono::weekday(5), 5});
97   check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sat'\t%A='Saturday'\n"),
98         fmt,
99         std::chrono::weekday_indexed{std::chrono::weekday(6), 6});
100   check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"),
101         fmt,
102         std::chrono::weekday_indexed{std::chrono::weekday(7), 7});
103 
104   // Use the global locale (fr_FR)
105 #if defined(__APPLE__)
106   check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"),
107         lfmt,
108         std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
109   check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Lun'\t%A='Lundi'\n"),
110         lfmt,
111         std::chrono::weekday_indexed{std::chrono::weekday(1), 1});
112   check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Mar'\t%A='Mardi'\n"),
113         lfmt,
114         std::chrono::weekday_indexed{std::chrono::weekday(2), 2});
115   check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Mer'\t%A='Mercredi'\n"),
116         lfmt,
117         std::chrono::weekday_indexed{std::chrono::weekday(3), 3});
118   check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Jeu'\t%A='Jeudi'\n"),
119         lfmt,
120         std::chrono::weekday_indexed{std::chrono::weekday(4), 4});
121   check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Ven'\t%A='Vendredi'\n"),
122         lfmt,
123         std::chrono::weekday_indexed{std::chrono::weekday(5), 5});
124   check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sam'\t%A='Samedi'\n"),
125         lfmt,
126         std::chrono::weekday_indexed{std::chrono::weekday(6), 6});
127   check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"),
128         lfmt,
129         std::chrono::weekday_indexed{std::chrono::weekday(7), 7});
130 #else  // defined(__APPLE__)
131   check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"),
132         lfmt,
133         std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
134   check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='lun.'\t%A='lundi'\n"),
135         lfmt,
136         std::chrono::weekday_indexed{std::chrono::weekday(1), 1});
137   check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='mar.'\t%A='mardi'\n"),
138         lfmt,
139         std::chrono::weekday_indexed{std::chrono::weekday(2), 2});
140   check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='mer.'\t%A='mercredi'\n"),
141         lfmt,
142         std::chrono::weekday_indexed{std::chrono::weekday(3), 3});
143   check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='jeu.'\t%A='jeudi'\n"),
144         lfmt,
145         std::chrono::weekday_indexed{std::chrono::weekday(4), 4});
146   check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='ven.'\t%A='vendredi'\n"),
147         lfmt,
148         std::chrono::weekday_indexed{std::chrono::weekday(5), 5});
149   check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='sam.'\t%A='samedi'\n"),
150         lfmt,
151         std::chrono::weekday_indexed{std::chrono::weekday(6), 6});
152   check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"),
153         lfmt,
154         std::chrono::weekday_indexed{std::chrono::weekday(7), 7});
155 #endif // defined(__APPLE__)
156 
157   // Use supplied locale (ja_JP).
158   // This locale has a different alternate, but not on all platforms
159 #if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
160   check(loc,
161         SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"),
162         lfmt,
163         std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
164   check(loc,
165         SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='月'\t%A='月曜日'\n"),
166         lfmt,
167         std::chrono::weekday_indexed{std::chrono::weekday(1), 1});
168   check(loc,
169         SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='火'\t%A='火曜日'\n"),
170         lfmt,
171         std::chrono::weekday_indexed{std::chrono::weekday(2), 2});
172   check(loc,
173         SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='水'\t%A='水曜日'\n"),
174         lfmt,
175         std::chrono::weekday_indexed{std::chrono::weekday(3), 3});
176   check(loc,
177         SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='木'\t%A='木曜日'\n"),
178         lfmt,
179         std::chrono::weekday_indexed{std::chrono::weekday(4), 4});
180   check(loc,
181         SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='金'\t%A='金曜日'\n"),
182         lfmt,
183         std::chrono::weekday_indexed{std::chrono::weekday(5), 5});
184   check(loc,
185         SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='土'\t%A='土曜日'\n"),
186         lfmt,
187         std::chrono::weekday_indexed{std::chrono::weekday(6), 6});
188   check(loc,
189         SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"),
190         lfmt,
191         std::chrono::weekday_indexed{std::chrono::weekday(7), 7});
192 #else  // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
193   check(loc,
194         SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"),
195         lfmt,
196         std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
197   check(loc,
198         SV("%u='1'\t%Ou='一'\t%w='1'\t%Ow='一'\t%a='月'\t%A='月曜日'\n"),
199         lfmt,
200         std::chrono::weekday_indexed{std::chrono::weekday(1), 1});
201   check(loc,
202         SV("%u='2'\t%Ou='二'\t%w='2'\t%Ow='二'\t%a='火'\t%A='火曜日'\n"),
203         lfmt,
204         std::chrono::weekday_indexed{std::chrono::weekday(2), 2});
205   check(loc,
206         SV("%u='3'\t%Ou='三'\t%w='3'\t%Ow='三'\t%a='水'\t%A='水曜日'\n"),
207         lfmt,
208         std::chrono::weekday_indexed{std::chrono::weekday(3), 3});
209   check(loc,
210         SV("%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\t%a='木'\t%A='木曜日'\n"),
211         lfmt,
212         std::chrono::weekday_indexed{std::chrono::weekday(4), 4});
213   check(loc,
214         SV("%u='5'\t%Ou='五'\t%w='5'\t%Ow='五'\t%a='金'\t%A='金曜日'\n"),
215         lfmt,
216         std::chrono::weekday_indexed{std::chrono::weekday(5), 5});
217   check(loc,
218         SV("%u='6'\t%Ou='六'\t%w='6'\t%Ow='六'\t%a='土'\t%A='土曜日'\n"),
219         lfmt,
220         std::chrono::weekday_indexed{std::chrono::weekday(6), 6});
221   check(loc,
222         SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"),
223         lfmt,
224         std::chrono::weekday_indexed{std::chrono::weekday(7), 7});
225 #endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
226 
227   std::locale::global(std::locale::classic());
228 }
229 
230 template <class CharT>
231 static void test_invalid_values() {
232   // Test that %a and %A throw an exception.
233   check_exception("Formatting a weekday name needs a valid weekday",
234                   SV("{:%a}"),
235                   std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
236   check_exception("Formatting a weekday name needs a valid weekday",
237                   SV("{:%a}"),
238                   std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
239   check_exception("Formatting a weekday name needs a valid weekday",
240                   SV("{:%A}"),
241                   std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
242   check_exception("Formatting a weekday name needs a valid weekday",
243                   SV("{:%A}"),
244                   std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
245 
246   const std::locale loc(LOCALE_ja_JP_UTF_8);
247   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
248 
249   { // Invalid weekday, can't test %a and %A
250     constexpr std::basic_string_view<CharT> fmt  = SV("{:%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
251     constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
252 #if defined(__APPLE__) || defined(__FreeBSD__)
253     // Non localized output using C-locale
254     check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
255     check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
256     check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"),
257           fmt,
258           std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
259     check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"),
260           fmt,
261           std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
262 
263     // Use the global locale (fr_FR)
264     check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
265     check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
266     check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"),
267           lfmt,
268           std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
269     check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"),
270           lfmt,
271           std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
272 
273     // Use supplied locale (ja_JP). This locale has a different alternate.
274     check(
275         loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
276     check(
277         loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
278     check(loc,
279           SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"),
280           lfmt,
281           std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
282     check(loc,
283           SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"),
284           lfmt,
285           std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
286 #elif defined(_WIN32) //  defined(__APPLE__) || defined(__FreeBSD__)
287     // Non localized output using C-locale
288     check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
289     check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
290     check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
291     check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
292 
293     // Use the global locale (fr_FR)
294     check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
295     check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
296     check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
297     check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
298 
299     // Use supplied locale (ja_JP). This locale has a different alternate.
300     check(loc, SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
301     check(loc, SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
302     check(loc, SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
303     check(loc, SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
304 #elif defined(_AIX)   //  defined(__APPLE__) || defined(__FreeBSD__)
305     // Non localized output using C-locale
306     check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
307     check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
308     check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
309     check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
310 
311     // Use the global locale (fr_FR)
312     check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
313     check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
314     check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
315     check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
316 
317     // Use supplied locale (ja_JP). This locale has a different alternate.
318     check(
319         loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
320     check(
321         loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
322     check(loc,
323           SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"),
324           lfmt,
325           std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
326     check(loc,
327           SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"),
328           lfmt,
329           std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
330 #else                 // defined(__APPLE__) || defined(__FreeBSD__)
331     // Non localized output using C-locale
332     check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
333     check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
334     check(
335         SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
336     check(
337         SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
338 
339     // Use the global locale (fr_FR)
340     check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
341     check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
342     check(
343         SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
344     check(
345         SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
346 
347     // Use supplied locale (ja_JP). This locale has a different alternate.
348     check(loc,
349           SV("%u='1'\t%Ou='一'\t%w='8'\t%Ow='八'\n"),
350           lfmt,
351           std::chrono::weekday_indexed{std::chrono::weekday(8), 0});
352     check(loc,
353           SV("%u='1'\t%Ou='一'\t%w='8'\t%Ow='八'\n"),
354           lfmt,
355           std::chrono::weekday_indexed{std::chrono::weekday(8), 1});
356     check(loc,
357           SV("%u='3'\t%Ou='三'\t%w='255'\t%Ow='255'\n"),
358           lfmt,
359           std::chrono::weekday_indexed{std::chrono::weekday(255), 0});
360     check(loc,
361           SV("%u='3'\t%Ou='三'\t%w='255'\t%Ow='255'\n"),
362           lfmt,
363           std::chrono::weekday_indexed{std::chrono::weekday(255), 1});
364 #endif                // defined(__APPLE__) || defined(__FreeBSD__)
365   }
366 
367   { // Valid weekday, tests %a and %A
368     constexpr std::basic_string_view<CharT> fmt  = SV("{:%%a='%a'%t%%A='%A'%n}");
369     constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%a='%a'%t%%A='%A'%n}");
370 
371     // Non localized output using C-locale
372     check(SV("%a='Sun'\t%A='Sunday'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
373     check(SV("%a='Sun'\t%A='Sunday'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 6});
374 
375     // Use the global locale (fr_FR)
376 #if defined(__APPLE__)
377     check(SV("%a='Dim'\t%A='Dimanche'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
378     check(SV("%a='Dim'\t%A='Dimanche'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 6});
379 #else  // defined(__APPLE__)
380     check(SV("%a='dim.'\t%A='dimanche'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
381     check(SV("%a='dim.'\t%A='dimanche'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 6});
382 #endif // defined(__APPLE__)
383 
384     // Use supplied locale (ja_JP)
385     check(loc, SV("%a='日'\t%A='日曜日'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 0});
386     check(loc, SV("%a='日'\t%A='日曜日'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 6});
387   }
388 
389   std::locale::global(std::locale::classic());
390 }
391 
392 template <class CharT>
393 static void test() {
394   test_no_chrono_specs<CharT>();
395   test_valid_values<CharT>();
396   test_invalid_values<CharT>();
397   check_invalid_types<CharT>({SV("a"), SV("A"), SV("t"), SV("u"), SV("w"), SV("Ou"), SV("Ow")},
398                              std::chrono::weekday_indexed{std::chrono::weekday(0), 1});
399 
400   check_exception("The format specifier expects a '%' or a '}'",
401                   SV("{:A"),
402                   std::chrono::weekday_indexed{std::chrono::weekday(0), 1});
403   check_exception(
404       "The chrono specifiers contain a '{'", SV("{:%%{"), std::chrono::weekday_indexed{std::chrono::weekday(0), 1});
405   check_exception("End of input while parsing a conversion specifier",
406                   SV("{:%"),
407                   std::chrono::weekday_indexed{std::chrono::weekday(0), 1});
408   check_exception("End of input while parsing the modifier E",
409                   SV("{:%E"),
410                   std::chrono::weekday_indexed{std::chrono::weekday(0), 1});
411   check_exception("End of input while parsing the modifier O",
412                   SV("{:%O"),
413                   std::chrono::weekday_indexed{std::chrono::weekday(0), 1});
414 
415   // Precision not allowed
416   check_exception("The format specifier expects a '%' or a '}'",
417                   SV("{:.3}"),
418                   std::chrono::weekday_indexed{std::chrono::weekday(0), 1});
419 }
420 
421 int main(int, char**) {
422   test<char>();
423 
424 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
425   test<wchar_t>();
426 #endif
427 
428   return 0;
429 }
430