• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===----------------------------------------------------------------------===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 
8 // UNSUPPORTED: c++03, c++11, c++14, c++17
9 // UNSUPPORTED: no-localization
10 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
11 
12 // TODO FMT This test should not require std::to_chars(floating-point)
13 // XFAIL: availability-fp_to_chars-missing
14 
15 // REQUIRES: locale.fr_FR.UTF-8
16 // REQUIRES: locale.ja_JP.UTF-8
17 
18 // <chrono>
19 //
20 // template<class charT> struct formatter<chrono::day, charT>;
21 
22 #include <chrono>
23 #include <format>
24 
25 #include <cassert>
26 #include <concepts>
27 #include <locale>
28 #include <iostream>
29 #include <type_traits>
30 
31 #include "formatter_tests.h"
32 #include "make_string.h"
33 #include "platform_support.h" // locale name macros
34 #include "test_macros.h"
35 
36 template <class CharT>
test_no_chrono_specs()37 static void test_no_chrono_specs() {
38   using namespace std::literals::chrono_literals;
39 
40   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
41 
42   // Non localized output
43 
44   // [time.syn]
45   //   using nanoseconds  = duration<signed integer type of at least 64 bits, nano>;
46   //   using microseconds = duration<signed integer type of at least 55 bits, micro>;
47   //   using milliseconds = duration<signed integer type of at least 45 bits, milli>;
48   //   using seconds      = duration<signed integer type of at least 35 bits>;
49   //   using minutes      = duration<signed integer type of at least 29 bits, ratio<  60>>;
50   //   using hours        = duration<signed integer type of at least 23 bits, ratio<3600>>;
51   check(SV("1425-08-04 22:06:56"), SV("{}"), std::chrono::sys_seconds(-17'179'869'184s)); // Minimum value for 35 bits.
52   check(SV("1901-12-13 20:45:52"), SV("{}"), std::chrono::sys_seconds(-2'147'483'648s));
53 
54   check(SV("1969-12-31 00:00:00"), SV("{}"), std::chrono::sys_seconds(-24h));
55   check(SV("1969-12-31 06:00:00"), SV("{}"), std::chrono::sys_seconds(-18h));
56   check(SV("1969-12-31 12:00:00"), SV("{}"), std::chrono::sys_seconds(-12h));
57   check(SV("1969-12-31 18:00:00"), SV("{}"), std::chrono::sys_seconds(-6h));
58   check(SV("1969-12-31 23:59:59"), SV("{}"), std::chrono::sys_seconds(-1s));
59 
60   check(SV("1970-01-01 00:00:00"), SV("{}"), std::chrono::sys_seconds(0s));
61   check(SV("2000-01-01 00:00:00"), SV("{}"), std::chrono::sys_seconds(946'684'800s));
62   check(SV("2000-01-01 01:02:03"), SV("{}"), std::chrono::sys_seconds(946'688'523s));
63 
64   check(SV("2038-01-19 03:14:07"), SV("{}"), std::chrono::sys_seconds(2'147'483'647s));
65   check(SV("2514-05-30 01:53:03"), SV("{}"), std::chrono::sys_seconds(17'179'869'183s)); // Maximum value for 35 bits.
66 
67   check(SV("2000-01-01 01:02:03.123"), SV("{}"), std::chrono::sys_time<std::chrono::milliseconds>(946'688'523'123ms));
68 
69   std::locale::global(std::locale::classic());
70 }
71 
72 template <class CharT>
test_valid_values_year()73 static void test_valid_values_year() {
74   using namespace std::literals::chrono_literals;
75 
76   constexpr std::basic_string_view<CharT> fmt =
77       SV("{:%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
78   constexpr std::basic_string_view<CharT> lfmt =
79       SV("{:L%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
80 
81   const std::locale loc(LOCALE_ja_JP_UTF_8);
82   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
83 
84   // Non localized output using C-locale
85   check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),
86         fmt,
87         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
88 
89   check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
90         fmt,
91         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
92 
93   // Use the global locale (fr_FR)
94   check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),
95         lfmt,
96         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
97 
98   check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
99         lfmt,
100         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
101 
102   // Use supplied locale (ja_JP). This locale has a different alternate.
103 #if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
104   check(loc,
105         SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),
106         lfmt,
107         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
108 
109   check(loc,
110         SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
111         lfmt,
112         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
113 #else  // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)
114   check(loc,
115         SV("%C='19'\t%EC='昭和'\t%y='70'\t%Oy='七十'\t%Ey='45'\t%Y='1970'\t%EY='昭和45年'\n"),
116         lfmt,
117         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
118 
119   check(loc,
120         SV("%C='20'\t%EC='平成'\t%y='09'\t%Oy='九'\t%Ey='21'\t%Y='2009'\t%EY='平成21年'\n"),
121         lfmt,
122         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
123 #endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)
124 
125   std::locale::global(std::locale::classic());
126 }
127 
128 template <class CharT>
test_valid_values_month()129 static void test_valid_values_month() {
130   using namespace std::literals::chrono_literals;
131 
132   constexpr std::basic_string_view<CharT> fmt  = SV("{:%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
133   constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
134 
135   const std::locale loc(LOCALE_ja_JP_UTF_8);
136   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
137 
138   // Non localized output using C-locale
139   check(SV("%b='Jan'\t%h='Jan'\t%B='January'\t%m='01'\t%Om='01'\n"),
140         fmt,
141         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
142 
143   check(SV("%b='May'\t%h='May'\t%B='May'\t%m='05'\t%Om='05'\n"),
144         fmt,
145         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
146 
147   // Use the global locale (fr_FR)
148 #if defined(__APPLE__)
149   check(SV("%b='jan'\t%h='jan'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
150         lfmt,
151         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
152 #else
153   check(SV("%b='janv.'\t%h='janv.'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
154         lfmt,
155         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
156 #endif
157 
158   check(SV("%b='mai'\t%h='mai'\t%B='mai'\t%m='05'\t%Om='05'\n"),
159         lfmt,
160         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
161 
162   // Use supplied locale (ja_JP). This locale has a different alternate.
163 #ifdef _WIN32
164   check(loc,
165         SV("%b='1'\t%h='1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
166         lfmt,
167         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
168 
169   check(loc,
170         SV("%b='5'\t%h='5'\t%B='5月'\t%m='05'\t%Om='05'\n"),
171         lfmt,
172         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
173 #elif defined(_AIX)                                // _WIN32
174   check(loc,
175         SV("%b='1月'\t%h='1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),
176         lfmt,
177         std::chrono::sys_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         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
183 #elif defined(__APPLE__)                           // _WIN32
184   check(loc,
185         SV("%b=' 1'\t%h=' 1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
186         lfmt,
187         std::chrono::sys_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         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
193 #elif defined(__FreeBSD__)                         // _WIN32
194   check(loc,
195         SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),
196         lfmt,
197         std::chrono::sys_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         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
203 #else                                              // _WIN32
204   check(loc,
205         SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='一'\n"),
206         lfmt,
207         std::chrono::sys_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='五'\n"),
211         lfmt,
212         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
213 #endif                                             // _WIN32
214 
215   std::locale::global(std::locale::classic());
216 }
217 
218 template <class CharT>
test_valid_values_day()219 static void test_valid_values_day() {
220   using namespace std::literals::chrono_literals;
221 
222   constexpr std::basic_string_view<CharT> fmt  = SV("{:%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
223   constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
224 
225   const std::locale loc(LOCALE_ja_JP_UTF_8);
226   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
227 
228   // Non localized output using C-locale
229   check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),
230         fmt,
231         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
232 
233   check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
234         fmt,
235         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
236 
237   // Use the global locale (fr_FR)
238   check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),
239         lfmt,
240         std::chrono::sys_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         lfmt,
244         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
245 
246   // Use supplied locale (ja_JP). This locale has a different alternate.
247 #if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
248   check(loc,
249         SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),
250         lfmt,
251         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
252 
253   check(loc,
254         SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
255         lfmt,
256         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
257 #else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
258   check(loc,
259         SV("%d='01'\t%Od='一'\t%e=' 1'\t%Oe='一'\n"),
260         lfmt,
261         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
262 
263   check(loc,
264         SV("%d='13'\t%Od='十三'\t%e='13'\t%Oe='十三'\n"),
265         lfmt,
266         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
267 
268 #endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
269 
270   std::locale::global(std::locale::classic());
271 }
272 
273 template <class CharT>
test_valid_values_weekday()274 static void test_valid_values_weekday() {
275   using namespace std::literals::chrono_literals;
276 
277   constexpr std::basic_string_view<CharT> fmt =
278       SV("{:%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
279   constexpr std::basic_string_view<CharT> lfmt =
280       SV("{:L%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
281 
282   const std::locale loc(LOCALE_ja_JP_UTF_8);
283   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
284 
285   // Non localized output using C-locale
286   check(SV("%a='Thu'\t%A='Thursday'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
287         fmt,
288         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
289 
290   check(SV("%a='Sun'\t%A='Sunday'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
291         fmt,
292         std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
293 
294   // Use the global locale (fr_FR)
295 #if defined(__APPLE__)
296   check(SV("%a='Jeu'\t%A='Jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
297         lfmt,
298         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
299 
300   check(SV("%a='Dim'\t%A='Dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
301         lfmt,
302         std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
303 #else
304   check(SV("%a='jeu.'\t%A='jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
305         lfmt,
306         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
307 
308   check(SV("%a='dim.'\t%A='dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
309         lfmt,
310         std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
311 #endif
312 
313   // Use supplied locale (ja_JP).
314   // This locale has a different alternate, but not on all platforms
315 #if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
316   check(loc,
317         SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
318         lfmt,
319         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
320 
321   check(loc,
322         SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
323         lfmt,
324         std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
325 #else  // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
326   check(loc,
327         SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\n"),
328         lfmt,
329         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
330 
331   check(loc,
332         SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\n"),
333         lfmt,
334         std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
335 #endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
336 
337   std::locale::global(std::locale::classic());
338 }
339 
340 template <class CharT>
test_valid_values_day_of_year()341 static void test_valid_values_day_of_year() {
342   using namespace std::literals::chrono_literals;
343 
344   constexpr std::basic_string_view<CharT> fmt  = SV("{:%%j='%j'%n}");
345   constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%j='%j'%n}");
346 
347   const std::locale loc(LOCALE_ja_JP_UTF_8);
348   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
349 
350   // Non localized output using C-locale
351   check(SV("%j='001'\n"), fmt, std::chrono::sys_seconds(0s));             // 00:00:00 UTC Thursday, 1 January 1970
352   check(SV("%j='138'\n"), fmt, std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
353 
354   // Use the global locale (fr_FR)
355   check(SV("%j='001'\n"), lfmt, std::chrono::sys_seconds(0s));             // 00:00:00 UTC Thursday, 1 January 1970
356   check(SV("%j='138'\n"), lfmt, std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
357 
358   // Use supplied locale (ja_JP). This locale has a different alternate.
359   check(loc, SV("%j='001'\n"), lfmt, std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
360 
361   check(
362       loc, SV("%j='138'\n"), lfmt, std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
363 
364   std::locale::global(std::locale::classic());
365 }
366 
367 template <class CharT>
test_valid_values_week()368 static void test_valid_values_week() {
369   using namespace std::literals::chrono_literals;
370 
371   constexpr std::basic_string_view<CharT> fmt  = SV("{:%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
372   constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
373 
374   const std::locale loc(LOCALE_ja_JP_UTF_8);
375   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
376 
377   // Non localized output using C-locale
378   check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),
379         fmt,
380         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
381 
382   check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
383         fmt,
384         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
385 
386   // Use the global locale (fr_FR)
387   check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),
388         lfmt,
389         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
390 
391   check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
392         lfmt,
393         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
394 
395   // Use supplied locale (ja_JP). This locale has a different alternate.
396 #if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
397   check(loc,
398         SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),
399         lfmt,
400         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
401 
402   check(loc,
403         SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
404         lfmt,
405         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
406 #else  // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
407   check(loc,
408         SV("%U='00'\t%OU='〇'\t%W='00'\t%OW='〇'\n"),
409         lfmt,
410         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
411 
412   check(loc,
413         SV("%U='20'\t%OU='二十'\t%W='20'\t%OW='二十'\n"),
414         lfmt,
415         std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
416 #endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
417   std::locale::global(std::locale::classic());
418 }
419 
420 template <class CharT>
test_valid_values_iso_8601_week()421 static void test_valid_values_iso_8601_week() {
422   using namespace std::literals::chrono_literals;
423 
424   constexpr std::basic_string_view<CharT> fmt  = SV("{:%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
425   constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
426 
427   const std::locale loc(LOCALE_ja_JP_UTF_8);
428   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
429 
430   // Non localized output using C-locale
431   check(SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),
432         fmt,
433         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
434 
435   check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
436         fmt,
437         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
438 
439   // Use the global locale (fr_FR)
440   check(SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),
441         lfmt,
442         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
443 
444   check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
445         lfmt,
446         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
447 
448   // Use supplied locale (ja_JP). This locale has a different alternate.
449 #if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
450   check(loc,
451         SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),
452         lfmt,
453         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
454 
455   check(loc,
456         SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
457         lfmt,
458         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
459 #else  // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
460   check(loc,
461         SV("%g='70'\t%G='1970'\t%V='01'\t%OV='一'\n"),
462         lfmt,
463         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
464 
465   check(loc,
466         SV("%g='09'\t%G='2009'\t%V='07'\t%OV='七'\n"),
467         lfmt,
468         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
469 #endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
470 
471   std::locale::global(std::locale::classic());
472 }
473 
474 template <class CharT>
test_valid_values_date()475 static void test_valid_values_date() {
476   using namespace std::literals::chrono_literals;
477 
478   constexpr std::basic_string_view<CharT> fmt  = SV("{:%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
479   constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
480 
481   const std::locale loc(LOCALE_ja_JP_UTF_8);
482   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
483 
484   // Non localized output using C-locale
485   check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/70'\t%Ex='01/01/70'\n"),
486         fmt,
487         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
488 
489   check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='02/13/09'\t%Ex='02/13/09'\n"),
490         fmt,
491         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
492 
493   // Use the global locale (fr_FR)
494 #if defined(__APPLE__) || defined(__FreeBSD__)
495   check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01.01.1970'\t%Ex='01.01.1970'\n"),
496         lfmt,
497         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
498 
499   check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13.02.2009'\t%Ex='13.02.2009'\n"),
500         lfmt,
501         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
502 #else
503   check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/1970'\t%Ex='01/01/1970'\n"),
504         lfmt,
505         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
506 
507   check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13/02/2009'\t%Ex='13/02/2009'\n"),
508         lfmt,
509         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
510 #endif
511 
512   // Use supplied locale (ja_JP). This locale has a different alternate.
513 #if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
514   check(loc,
515         SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970/01/01'\t%Ex='1970/01/01'\n"),
516         lfmt,
517         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
518 
519   check(loc,
520         SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009/02/13'\t%Ex='2009/02/13'\n"),
521         lfmt,
522         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
523 #else  // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
524   check(loc,
525         SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970年01月01日'\t%Ex='昭和45年01月01日'\n"),
526         lfmt,
527         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
528 
529   check(loc,
530         SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009年02月13日'\t%Ex='平成21年02月13日'\n"),
531         lfmt,
532         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
533 #endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
534 
535   std::locale::global(std::locale::classic());
536 }
537 
538 template <class CharT>
test_valid_values_time()539 static void test_valid_values_time() {
540   using namespace std::literals::chrono_literals;
541 
542   constexpr std::basic_string_view<CharT> fmt = SV(
543       "{:"
544       "%%H='%H'%t"
545       "%%OH='%OH'%t"
546       "%%I='%I'%t"
547       "%%OI='%OI'%t"
548       "%%M='%M'%t"
549       "%%OM='%OM'%t"
550       "%%S='%S'%t"
551       "%%OS='%OS'%t"
552       "%%p='%p'%t"
553       "%%R='%R'%t"
554       "%%T='%T'%t"
555       "%%r='%r'%t"
556       "%%X='%X'%t"
557       "%%EX='%EX'%t"
558       "%n}");
559   constexpr std::basic_string_view<CharT> lfmt = SV(
560       "{:L"
561       "%%H='%H'%t"
562       "%%OH='%OH'%t"
563       "%%I='%I'%t"
564       "%%OI='%OI'%t"
565       "%%M='%M'%t"
566       "%%OM='%OM'%t"
567       "%%S='%S'%t"
568       "%%OS='%OS'%t"
569       "%%p='%p'%t"
570       "%%R='%R'%t"
571       "%%T='%T'%t"
572       "%%r='%r'%t"
573       "%%X='%X'%t"
574       "%%EX='%EX'%t"
575       "%n}");
576 
577   const std::locale loc(LOCALE_ja_JP_UTF_8);
578   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
579 
580   // Non localized output using C-locale
581   check(SV("%H='00'\t"
582            "%OH='00'\t"
583            "%I='12'\t"
584            "%OI='12'\t"
585            "%M='00'\t"
586            "%OM='00'\t"
587            "%S='00'\t"
588            "%OS='00'\t"
589            "%p='AM'\t"
590            "%R='00:00'\t"
591            "%T='00:00:00'\t"
592            "%r='12:00:00 AM'\t"
593            "%X='00:00:00'\t"
594            "%EX='00:00:00'\t"
595            "\n"),
596         fmt,
597         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
598 
599   check(SV("%H='23'\t"
600            "%OH='23'\t"
601            "%I='11'\t"
602            "%OI='11'\t"
603            "%M='31'\t"
604            "%OM='31'\t"
605            "%S='30.123'\t"
606            "%OS='30.123'\t"
607            "%p='PM'\t"
608            "%R='23:31'\t"
609            "%T='23:31:30.123'\t"
610            "%r='11:31:30 PM'\t"
611            "%X='23:31:30'\t"
612            "%EX='23:31:30'\t"
613            "\n"),
614         fmt,
615         std::chrono::sys_time<std::chrono::milliseconds>(
616             1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009
617   // Use the global locale (fr_FR)
618   check(SV("%H='00'\t"
619            "%OH='00'\t"
620            "%I='12'\t"
621            "%OI='12'\t"
622            "%M='00'\t"
623            "%OM='00'\t"
624            "%S='00'\t"
625            "%OS='00'\t"
626 #if defined(_AIX)
627            "%p='AM'\t"
628 #else
629            "%p=''\t"
630 #endif
631            "%R='00:00'\t"
632            "%T='00:00:00'\t"
633 #ifdef _WIN32
634            "%r='00:00:00'\t"
635 #elif defined(_AIX)
636            "%r='12:00:00 AM'\t"
637 #elif defined(__APPLE__) || defined(__FreeBSD__)
638            "%r=''\t"
639 #else
640            "%r='12:00:00 '\t"
641 #endif
642            "%X='00:00:00'\t"
643            "%EX='00:00:00'\t"
644            "\n"),
645         lfmt,
646         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
647 
648   check(SV("%H='23'\t"
649            "%OH='23'\t"
650            "%I='11'\t"
651            "%OI='11'\t"
652            "%M='31'\t"
653            "%OM='31'\t"
654            "%S='30,123'\t"
655            "%OS='30,123'\t"
656 #if defined(_AIX)
657            "%p='PM'\t"
658 #else
659            "%p=''\t"
660 #endif
661            "%R='23:31'\t"
662            "%T='23:31:30,123'\t"
663 #ifdef _WIN32
664            "%r='23:31:30'\t"
665 #elif defined(_AIX)
666            "%r='11:31:30 PM'\t"
667 #elif defined(__APPLE__) || defined(__FreeBSD__)
668            "%r=''\t"
669 #else
670            "%r='11:31:30 '\t"
671 #endif
672            "%X='23:31:30'\t"
673            "%EX='23:31:30'\t"
674            "\n"),
675         lfmt,
676         std::chrono::sys_time<std::chrono::milliseconds>(
677             1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009
678 
679   // Use supplied locale (ja_JP). This locale has a different alternate.
680 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
681   check(loc,
682         SV("%H='00'\t"
683            "%OH='00'\t"
684            "%I='12'\t"
685            "%OI='12'\t"
686            "%M='00'\t"
687            "%OM='00'\t"
688            "%S='00'\t"
689            "%OS='00'\t"
690 #  if defined(__APPLE__)
691            "%p='AM'\t"
692 #  else
693            "%p='午前'\t"
694 #  endif
695            "%R='00:00'\t"
696            "%T='00:00:00'\t"
697 #  if defined(__APPLE__) || defined(__FreeBSD__)
698 #    if defined(__APPLE__)
699            "%r='12:00:00 AM'\t"
700 #    else
701            "%r='12:00:00 午前'\t"
702 #    endif
703            "%X='00時00分00秒'\t"
704            "%EX='00時00分00秒'\t"
705 #  elif defined(_WIN32)
706            "%r='0:00:00'\t"
707            "%X='0:00:00'\t"
708            "%EX='0:00:00'\t"
709 #  else
710            "%r='午前12:00:00'\t"
711            "%X='00:00:00'\t"
712            "%EX='00:00:00'\t"
713 #  endif
714            "\n"),
715         lfmt,
716         std::chrono::hh_mm_ss(0s));
717 
718   check(loc,
719         SV("%H='23'\t"
720            "%OH='23'\t"
721            "%I='11'\t"
722            "%OI='11'\t"
723            "%M='31'\t"
724            "%OM='31'\t"
725            "%S='30.123'\t"
726            "%OS='30.123'\t"
727 #  if defined(__APPLE__)
728            "%p='PM'\t"
729 #  else
730            "%p='午後'\t"
731 #  endif
732            "%R='23:31'\t"
733            "%T='23:31:30.123'\t"
734 #  if defined(__APPLE__) || defined(__FreeBSD__)
735 #    if defined(__APPLE__)
736            "%r='11:31:30 PM'\t"
737 #    else
738            "%r='11:31:30 午後'\t"
739 #    endif
740            "%X='23時31分30秒'\t"
741            "%EX='23時31分30秒'\t"
742 #  elif defined(_WIN32)
743            "%r='23:31:30'\t"
744            "%X='23:31:30'\t"
745            "%EX='23:31:30'\t"
746 #  else
747            "%r='午後11:31:30'\t"
748            "%X='23:31:30'\t"
749            "%EX='23:31:30'\t"
750 #  endif
751            "\n"),
752         lfmt,
753         std::chrono::hh_mm_ss(23h + 31min + 30s + 123ms));
754 #else  // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
755   check(loc,
756         SV("%H='00'\t"
757            "%OH='〇'\t"
758            "%I='12'\t"
759            "%OI='十二'\t"
760            "%M='00'\t"
761            "%OM='〇'\t"
762            "%S='00'\t"
763            "%OS='〇'\t"
764            "%p='午前'\t"
765            "%R='00:00'\t"
766            "%T='00:00:00'\t"
767            "%r='午前12時00分00秒'\t"
768            "%X='00時00分00秒'\t"
769            "%EX='00時00分00秒'\t"
770            "\n"),
771         lfmt,
772         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
773 
774   check(loc,
775         SV("%H='23'\t"
776            "%OH='二十三'\t"
777            "%I='11'\t"
778            "%OI='十一'\t"
779            "%M='31'\t"
780            "%OM='三十一'\t"
781            "%S='30.123'\t"
782            "%OS='三十.123'\t"
783            "%p='午後'\t"
784            "%R='23:31'\t"
785            "%T='23:31:30.123'\t"
786            "%r='午後11時31分30秒'\t"
787            "%X='23時31分30秒'\t"
788            "%EX='23時31分30秒'\t"
789            "\n"),
790         lfmt,
791         std::chrono::sys_time<std::chrono::milliseconds>(
792             1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009
793 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
794 
795   std::locale::global(std::locale::classic());
796 }
797 
798 template <class CharT>
test_valid_values_date_time()799 static void test_valid_values_date_time() {
800   using namespace std::literals::chrono_literals;
801 
802   constexpr std::basic_string_view<CharT> fmt  = SV("{:%%c='%c'%t%%Ec='%Ec'%n}");
803   constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%c='%c'%t%%Ec='%Ec'%n}");
804 
805   const std::locale loc(LOCALE_ja_JP_UTF_8);
806   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
807 
808   // Non localized output using C-locale
809   check(SV("%c='Thu Jan  1 00:00:00 1970'\t%Ec='Thu Jan  1 00:00:00 1970'\n"),
810         fmt,
811         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
812 
813   check(SV("%c='Fri Feb 13 23:31:30 2009'\t%Ec='Fri Feb 13 23:31:30 2009'\n"),
814         fmt,
815         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
816 
817   // Use the global locale (fr_FR)
818   check(
819 // https://sourceware.org/bugzilla/show_bug.cgi?id=24054
820 #if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
821       SV("%c='jeu. 01 janv. 1970 00:00:00 GMT'\t%Ec='jeu. 01 janv. 1970 00:00:00 GMT'\n"),
822 #elif defined(_AIX)
823       SV("%c=' 1 janvier 1970 à 00:00:00 UTC'\t%Ec=' 1 janvier 1970 à 00:00:00 UTC'\n"),
824 #elif defined(__APPLE__)
825       SV("%c='Jeu  1 jan 00:00:00 1970'\t%Ec='Jeu  1 jan 00:00:00 1970'\n"),
826 #elif defined(_WIN32)
827       SV("%c='01/01/1970 00:00:00'\t%Ec='01/01/1970 00:00:00'\n"),
828 #elif defined(__FreeBSD__)
829       SV("%c='jeu.  1 janv. 00:00:00 1970'\t%Ec='jeu.  1 janv. 00:00:00 1970'\n"),
830 #else
831       SV("%c='jeu. 01 janv. 1970 00:00:00'\t%Ec='jeu. 01 janv. 1970 00:00:00'\n"),
832 #endif
833       lfmt,
834       std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
835 
836   check(
837 // https://sourceware.org/bugzilla/show_bug.cgi?id=24054
838 #if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
839       SV("%c='ven. 13 févr. 2009 23:31:30 GMT'\t%Ec='ven. 13 févr. 2009 23:31:30 GMT'\n"),
840 #elif defined(_AIX)
841       SV("%c='13 février 2009 à 23:31:30 UTC'\t%Ec='13 février 2009 à 23:31:30 UTC'\n"),
842 #elif defined(__APPLE__)
843       SV("%c='Ven 13 fév 23:31:30 2009'\t%Ec='Ven 13 fév 23:31:30 2009'\n"),
844 #elif defined(_WIN32)
845       SV("%c='13/02/2009 23:31:30'\t%Ec='13/02/2009 23:31:30'\n"),
846 #elif defined(__FreeBSD__)
847       SV("%c='ven. 13 févr. 23:31:30 2009'\t%Ec='ven. 13 févr. 23:31:30 2009'\n"),
848 #else
849       SV("%c='ven. 13 févr. 2009 23:31:30'\t%Ec='ven. 13 févr. 2009 23:31:30'\n"),
850 #endif
851       lfmt,
852       std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
853 
854   // Use supplied locale (ja_JP). This locale has a different alternate.a
855 #if defined(__APPLE__) || defined(__FreeBSD__)
856   check(loc,
857         SV("%c='木  1/ 1 00:00:00 1970'\t%Ec='木  1/ 1 00:00:00 1970'\n"),
858         lfmt,
859         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
860   check(loc,
861         SV("%c='金  2/13 23:31:30 2009'\t%Ec='金  2/13 23:31:30 2009'\n"),
862         lfmt,
863         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
864 #elif defined(_AIX)                                // defined(__APPLE__)|| defined(__FreeBSD__)
865   check(loc,
866         SV("%c='1970年01月 1日 00:00:00 UTC'\t%Ec='1970年01月 1日 00:00:00 UTC'\n"),
867         lfmt,
868         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
869   check(loc,
870         SV("%c='2009年02月13日 23:31:30 UTC'\t%Ec='2009年02月13日 23:31:30 UTC'\n"),
871         lfmt,
872         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
873 #elif defined(_WIN32)                              // defined(__APPLE__)|| defined(__FreeBSD__)
874   check(loc,
875         SV("%c='1970/01/01 0:00:00'\t%Ec='1970/01/01 0:00:00'\n"),
876         lfmt,
877         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
878   check(loc,
879         SV("%c='2009/02/13 23:31:30'\t%Ec='2009/02/13 23:31:30'\n"),
880         lfmt,
881         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
882 #else                                              // defined(__APPLE__)|| defined(__FreeBSD__)
883   check(loc,
884         SV("%c='1970年01月01日 00時00分00秒'\t%Ec='昭和45年01月01日 00時00分00秒'\n"),
885         lfmt,
886         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
887 
888   check(loc,
889         SV("%c='2009年02月13日 23時31分30秒'\t%Ec='平成21年02月13日 23時31分30秒'\n"),
890         lfmt,
891         std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
892 #endif                                             // defined(__APPLE__)|| defined(__FreeBSD__)
893 
894   std::locale::global(std::locale::classic());
895 }
896 
897 template <class CharT>
test_valid_values_time_zone()898 static void test_valid_values_time_zone() {
899 // The Apple CI gives %z='-0700'	%Ez='-0700'	%Oz='-0700'	%Z='UTC'
900 // -0700 looks like the local time where the CI happens to reside, therefore
901 // omit this test on Apple.
902 // The Windows CI gives %z='-0000', but on local machines set to a different
903 // timezone, it gives e.g. %z='+0200'.
904 #if !defined(__APPLE__) && !defined(_WIN32)
905   using namespace std::literals::chrono_literals;
906 
907   constexpr std::basic_string_view<CharT> fmt  = SV("{:%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
908   constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
909 
910   const std::locale loc(LOCALE_ja_JP_UTF_8);
911   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
912 
913 #  if defined(_AIX)
914   // Non localized output using C-locale
915   check(SV("%z='UTC'\t%Ez='UTC'\t%Oz='UTC'\t%Z='UTC'\n"),
916         fmt,
917         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
918 
919   // Use the global locale (fr_FR)
920   check(SV("%z='UTC'\t%Ez='UTC'\t%Oz='UTC'\t%Z='UTC'\n"),
921         lfmt,
922         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
923 
924   // Use supplied locale (ja_JP). This locale has a different alternate.a
925   check(loc,
926         SV("%z='UTC'\t%Ez='UTC'\t%Oz='UTC'\t%Z='UTC'\n"),
927         lfmt,
928         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
929 #  else                                // defined(_AIX)
930   // Non localized output using C-locale
931   check(SV("%z='+0000'\t%Ez='+0000'\t%Oz='+0000'\t%Z='UTC'\n"),
932         fmt,
933         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
934 
935   // Use the global locale (fr_FR)
936   check(SV("%z='+0000'\t%Ez='+0000'\t%Oz='+0000'\t%Z='UTC'\n"),
937         lfmt,
938         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
939 
940   // Use supplied locale (ja_JP). This locale has a different alternate.a
941 #    if defined(__FreeBSD__)
942   check(loc,
943         SV("%z='+0000'\t%Ez='+0000'\t%Oz='+0000'\t%Z='UTC'\n"),
944         lfmt,
945         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
946 #    else
947   check(loc,
948         SV("%z='+0000'\t%Ez='+0000'\t%Oz='+〇'\t%Z='UTC'\n"),
949         lfmt,
950         std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
951 #    endif
952 #  endif                               // defined(_AIX)
953   std::locale::global(std::locale::classic());
954 #endif // !defined(__APPLE__) && !defined(_WIN32)
955 }
956 
957 template <class CharT>
test_valid_values()958 static void test_valid_values() {
959   test_valid_values_year<CharT>();
960   test_valid_values_month<CharT>();
961   test_valid_values_day<CharT>();
962   test_valid_values_weekday<CharT>();
963   test_valid_values_day_of_year<CharT>();
964   test_valid_values_week<CharT>();
965   test_valid_values_iso_8601_week<CharT>();
966   test_valid_values_date<CharT>();
967   test_valid_values_time<CharT>();
968   test_valid_values_date_time<CharT>();
969   test_valid_values_time_zone<CharT>();
970 }
971 
972 template <class CharT>
test()973 static void test() {
974   using namespace std::literals::chrono_literals;
975 
976   test_no_chrono_specs<CharT>();
977   test_valid_values<CharT>();
978   check_invalid_types<CharT>(
979       {SV("a"),  SV("A"),  SV("b"),  SV("B"),  SV("c"),  SV("C"),  SV("d"),  SV("D"),  SV("e"),  SV("F"),  SV("g"),
980        SV("G"),  SV("h"),  SV("H"),  SV("I"),  SV("j"),  SV("m"),  SV("M"),  SV("p"),  SV("r"),  SV("R"),  SV("S"),
981        SV("T"),  SV("u"),  SV("U"),  SV("V"),  SV("w"),  SV("W"),  SV("x"),  SV("X"),  SV("y"),  SV("Y"),  SV("z"),
982        SV("Z"),  SV("Ec"), SV("EC"), SV("Ex"), SV("EX"), SV("Ey"), SV("EY"), SV("Ez"), SV("Od"), SV("Oe"), SV("OH"),
983        SV("OI"), SV("Om"), SV("OM"), SV("OS"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), SV("Oz")},
984       std::chrono::sys_seconds(0s));
985 
986   check_exception("The format specifier expects a '%' or a '}'", SV("{:A"), std::chrono::sys_seconds(0s));
987   check_exception("The chrono specifiers contain a '{'", SV("{:%%{"), std::chrono::sys_seconds(0s));
988   check_exception("End of input while parsing a conversion specifier", SV("{:%"), std::chrono::sys_seconds(0s));
989   check_exception("End of input while parsing the modifier E", SV("{:%E"), std::chrono::sys_seconds(0s));
990   check_exception("End of input while parsing the modifier O", SV("{:%O"), std::chrono::sys_seconds(0s));
991 
992   // Precision not allowed
993   check_exception("The format specifier expects a '%' or a '}'", SV("{:.3}"), std::chrono::sys_seconds(0s));
994 }
995 
main(int,char **)996 int main(int, char**) {
997   test<char>();
998 
999 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
1000   test<wchar_t>();
1001 #endif
1002 
1003   return 0;
1004 }
1005