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