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_last, charT>;
25
26#include <chrono>
27#include <format>
28
29#include <cassert>
30#include <concepts>
31#include <locale>
32#include <iostream>
33#include <type_traits>
34
35#include "formatter_tests.h"
36#include "make_string.h"
37#include "platform_support.h" // locale name macros
38#include "test_macros.h"
39
40template <class CharT>
41static void test_no_chrono_specs() {
42 using namespace std::literals::chrono_literals;
43
44 // Valid day
45 check(SV("Sun[last]"), SV("{}"), std::chrono::weekday_last{std::chrono::weekday(0)});
46
47 // Invalid day
48 check(SV("8 is not a valid weekday[last]"), SV("{}"), std::chrono::weekday_last{std::chrono::weekday(8)});
49}
50
51template <class CharT>
52static void test_valid_values() {
53 constexpr std::basic_string_view<CharT> fmt =
54 SV("{:%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%n}");
55 constexpr std::basic_string_view<CharT> lfmt =
56 SV("{:L%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%n}");
57
58 const std::locale loc(LOCALE_ja_JP_UTF_8);
59 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
60
61 // Non localized output using C-locale
62 check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"),
63 fmt,
64 std::chrono::weekday_last{std::chrono::weekday(0)});
65 check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Mon'\t%A='Monday'\n"),
66 fmt,
67 std::chrono::weekday_last{std::chrono::weekday(1)});
68 check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Tue'\t%A='Tuesday'\n"),
69 fmt,
70 std::chrono::weekday_last{std::chrono::weekday(2)});
71 check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Wed'\t%A='Wednesday'\n"),
72 fmt,
73 std::chrono::weekday_last{std::chrono::weekday(3)});
74 check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Thu'\t%A='Thursday'\n"),
75 fmt,
76 std::chrono::weekday_last{std::chrono::weekday(4)});
77 check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Fri'\t%A='Friday'\n"),
78 fmt,
79 std::chrono::weekday_last{std::chrono::weekday(5)});
80 check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sat'\t%A='Saturday'\n"),
81 fmt,
82 std::chrono::weekday_last{std::chrono::weekday(6)});
83 check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"),
84 fmt,
85 std::chrono::weekday_last{std::chrono::weekday(7)});
86
87 // Use the global locale (fr_FR)
88#if defined(__APPLE__)
89 check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"),
90 lfmt,
91 std::chrono::weekday_last{std::chrono::weekday(0)});
92 check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Lun'\t%A='Lundi'\n"),
93 lfmt,
94 std::chrono::weekday_last{std::chrono::weekday(1)});
95 check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Mar'\t%A='Mardi'\n"),
96 lfmt,
97 std::chrono::weekday_last{std::chrono::weekday(2)});
98 check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Mer'\t%A='Mercredi'\n"),
99 lfmt,
100 std::chrono::weekday_last{std::chrono::weekday(3)});
101 check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Jeu'\t%A='Jeudi'\n"),
102 lfmt,
103 std::chrono::weekday_last{std::chrono::weekday(4)});
104 check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Ven'\t%A='Vendredi'\n"),
105 lfmt,
106 std::chrono::weekday_last{std::chrono::weekday(5)});
107 check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sam'\t%A='Samedi'\n"),
108 lfmt,
109 std::chrono::weekday_last{std::chrono::weekday(6)});
110 check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"),
111 lfmt,
112 std::chrono::weekday_last{std::chrono::weekday(7)});
113#else // defined(__APPLE__)
114 check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"),
115 lfmt,
116 std::chrono::weekday_last{std::chrono::weekday(0)});
117 check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='lun.'\t%A='lundi'\n"),
118 lfmt,
119 std::chrono::weekday_last{std::chrono::weekday(1)});
120 check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='mar.'\t%A='mardi'\n"),
121 lfmt,
122 std::chrono::weekday_last{std::chrono::weekday(2)});
123 check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='mer.'\t%A='mercredi'\n"),
124 lfmt,
125 std::chrono::weekday_last{std::chrono::weekday(3)});
126 check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='jeu.'\t%A='jeudi'\n"),
127 lfmt,
128 std::chrono::weekday_last{std::chrono::weekday(4)});
129 check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='ven.'\t%A='vendredi'\n"),
130 lfmt,
131 std::chrono::weekday_last{std::chrono::weekday(5)});
132 check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='sam.'\t%A='samedi'\n"),
133 lfmt,
134 std::chrono::weekday_last{std::chrono::weekday(6)});
135 check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"),
136 lfmt,
137 std::chrono::weekday_last{std::chrono::weekday(7)});
138#endif // defined(__APPLE__)
139
140 // Use supplied locale (ja_JP).
141 // This locale has a different alternate, but not on all platforms
142#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
143 check(loc,
144 SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"),
145 lfmt,
146 std::chrono::weekday_last{std::chrono::weekday(0)});
147 check(loc,
148 SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='月'\t%A='月曜日'\n"),
149 lfmt,
150 std::chrono::weekday_last{std::chrono::weekday(1)});
151 check(loc,
152 SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='火'\t%A='火曜日'\n"),
153 lfmt,
154 std::chrono::weekday_last{std::chrono::weekday(2)});
155 check(loc,
156 SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='水'\t%A='水曜日'\n"),
157 lfmt,
158 std::chrono::weekday_last{std::chrono::weekday(3)});
159 check(loc,
160 SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='木'\t%A='木曜日'\n"),
161 lfmt,
162 std::chrono::weekday_last{std::chrono::weekday(4)});
163 check(loc,
164 SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='金'\t%A='金曜日'\n"),
165 lfmt,
166 std::chrono::weekday_last{std::chrono::weekday(5)});
167 check(loc,
168 SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='土'\t%A='土曜日'\n"),
169 lfmt,
170 std::chrono::weekday_last{std::chrono::weekday(6)});
171 check(loc,
172 SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"),
173 lfmt,
174 std::chrono::weekday_last{std::chrono::weekday(7)});
175#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
176 check(loc,
177 SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"),
178 lfmt,
179 std::chrono::weekday_last{std::chrono::weekday(0)});
180 check(loc,
181 SV("%u='1'\t%Ou='一'\t%w='1'\t%Ow='一'\t%a='月'\t%A='月曜日'\n"),
182 lfmt,
183 std::chrono::weekday_last{std::chrono::weekday(1)});
184 check(loc,
185 SV("%u='2'\t%Ou='二'\t%w='2'\t%Ow='二'\t%a='火'\t%A='火曜日'\n"),
186 lfmt,
187 std::chrono::weekday_last{std::chrono::weekday(2)});
188 check(loc,
189 SV("%u='3'\t%Ou='三'\t%w='3'\t%Ow='三'\t%a='水'\t%A='水曜日'\n"),
190 lfmt,
191 std::chrono::weekday_last{std::chrono::weekday(3)});
192 check(loc,
193 SV("%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\t%a='木'\t%A='木曜日'\n"),
194 lfmt,
195 std::chrono::weekday_last{std::chrono::weekday(4)});
196 check(loc,
197 SV("%u='5'\t%Ou='五'\t%w='5'\t%Ow='五'\t%a='金'\t%A='金曜日'\n"),
198 lfmt,
199 std::chrono::weekday_last{std::chrono::weekday(5)});
200 check(loc,
201 SV("%u='6'\t%Ou='六'\t%w='6'\t%Ow='六'\t%a='土'\t%A='土曜日'\n"),
202 lfmt,
203 std::chrono::weekday_last{std::chrono::weekday(6)});
204 check(loc,
205 SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"),
206 lfmt,
207 std::chrono::weekday_last{std::chrono::weekday(7)});
208#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
209
210 std::locale::global(loc: std::locale::classic());
211}
212
213template <class CharT>
214static void test_invalid_values() {
215 // Test that %a and %A throw an exception.
216 check_exception("Formatting a weekday name needs a valid weekday",
217 SV("{:%a}"),
218 std::chrono::weekday_last{std::chrono::weekday(8)});
219 check_exception("Formatting a weekday name needs a valid weekday",
220 SV("{:%a}"),
221 std::chrono::weekday_last{std::chrono::weekday(255)});
222 check_exception("Formatting a weekday name needs a valid weekday",
223 SV("{:%A}"),
224 std::chrono::weekday_last{std::chrono::weekday(8)});
225 check_exception("Formatting a weekday name needs a valid weekday",
226 SV("{:%A}"),
227 std::chrono::weekday_last{std::chrono::weekday(255)});
228
229 constexpr std::basic_string_view<CharT> fmt = SV("{:%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
230 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
231
232 const std::locale loc(LOCALE_ja_JP_UTF_8);
233 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
234
235#if defined(__APPLE__) || defined(__FreeBSD__)
236 // Non localized output using C-locale
237 check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(8)});
238 check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(255)});
239
240 // Use the global locale (fr_FR)
241 check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)});
242 check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)});
243
244 // Use supplied locale (ja_JP). This locale has a different alternate.
245 check(loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)});
246 check(loc,
247 SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"),
248 lfmt,
249 std::chrono::weekday_last{std::chrono::weekday(255)});
250#elif defined(_WIN32) // defined(__APPLE__) || defined(__FreeBSD__)
251 // Non localized output using C-locale
252 check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(8)});
253 check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(255)});
254
255 // Use the global locale (fr_FR)
256 check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)});
257 check(SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)});
258
259 // Use supplied locale (ja_JP). This locale has a different alternate.
260 check(loc, SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)});
261 check(loc, SV("%u=''\t%Ou=''\t%w=''\t%Ow=''\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)});
262#elif defined(_AIX) // defined(__APPLE__) || defined(__FreeBSD__)
263 // Non localized output using C-locale
264 check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(8)});
265 check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(255)});
266
267 // Use the global locale (fr_FR)
268 check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)});
269 check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)});
270
271 // Use supplied locale (ja_JP). This locale has a different alternate.
272 check(loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)});
273 check(loc, SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)});
274#else // defined(__APPLE__) || defined(__FreeBSD__)
275 // Non localized output using C-locale
276 check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(8)});
277 check(SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(255)});
278
279 // Use the global locale (fr_FR)
280 check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)});
281 check(SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)});
282
283 // Use supplied locale (ja_JP). This locale has a different alternate.
284 check(loc, SV("%u='1'\t%Ou='一'\t%w='8'\t%Ow='八'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)});
285 check(loc, SV("%u='3'\t%Ou='三'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)});
286#endif // defined(__APPLE__) || defined(__FreeBSD__)
287
288 std::locale::global(loc: std::locale::classic());
289}
290
291template <class CharT>
292static void test() {
293 test_no_chrono_specs<CharT>();
294 test_valid_values<CharT>();
295 test_invalid_values<CharT>();
296 check_invalid_types<CharT>({SV("a"), SV("A"), SV("t"), SV("u"), SV("w"), SV("Ou"), SV("Ow")},
297 std::chrono::weekday_last{std::chrono::weekday(0)});
298
299 check_exception(
300 "The format specifier expects a '%' or a '}'", SV("{:A"), std::chrono::weekday_last{std::chrono::weekday(0)});
301 check_exception(
302 "The chrono specifiers contain a '{'", SV("{:%%{"), std::chrono::weekday_last{std::chrono::weekday(0)});
303 check_exception("End of input while parsing a conversion specifier",
304 SV("{:%"),
305 std::chrono::weekday_last{std::chrono::weekday(0)});
306 check_exception(
307 "End of input while parsing the modifier E", SV("{:%E"), std::chrono::weekday_last{std::chrono::weekday(0)});
308 check_exception(
309 "End of input while parsing the modifier O", SV("{:%O"), std::chrono::weekday_last{std::chrono::weekday(0)});
310
311 // Precision not allowed
312 check_exception(
313 "The format specifier expects a '%' or a '}'", SV("{:.3}"), std::chrono::weekday_last{std::chrono::weekday(0)});
314}
315
316int main(int, char**) {
317 test<char>();
318
319#ifndef TEST_HAS_NO_WIDE_CHARACTERS
320 test<wchar_t>();
321#endif
322
323 return 0;
324}
325

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