938 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710// UNSUPPORTED: no-localization11// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME12 13// TODO FMT This test should not require std::to_chars(floating-point)14// XFAIL: availability-fp_to_chars-missing15 16// REQUIRES: locale.fr_FR.UTF-817// REQUIRES: locale.ja_JP.UTF-818 19// <chrono>20//21// template<class charT> struct formatter<chrono::day, charT>;22 23#include <chrono>24#include <format>25 26#include <cassert>27#include <concepts>28#include <locale>29#include <iostream>30#include <type_traits>31 32#include "formatter_tests.h"33#include "make_string.h"34#include "platform_support.h" // locale name macros35#include "test_macros.h"36 37template <class CharT>38static void test_no_chrono_specs() {39 using namespace std::literals::chrono_literals;40 41 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));42 43 // Non localized output44 45 // [time.syn]46 // using nanoseconds = duration<signed integer type of at least 64 bits, nano>;47 // using microseconds = duration<signed integer type of at least 55 bits, micro>;48 // using milliseconds = duration<signed integer type of at least 45 bits, milli>;49 // using seconds = duration<signed integer type of at least 35 bits>;50 // using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>;51 // using hours = duration<signed integer type of at least 23 bits, ratio<3600>>;52 check(53 SV("1425-08-04 22:06:56"), SV("{}"), std::chrono::local_seconds(-17'179'869'184s)); // Minimum value for 35 bits.54 check(SV("1901-12-13 20:45:52"), SV("{}"), std::chrono::local_seconds(-2'147'483'648s));55 56 check(SV("1969-12-31 00:00:00"), SV("{}"), std::chrono::local_seconds(-24h));57 check(SV("1969-12-31 06:00:00"), SV("{}"), std::chrono::local_seconds(-18h));58 check(SV("1969-12-31 12:00:00"), SV("{}"), std::chrono::local_seconds(-12h));59 check(SV("1969-12-31 18:00:00"), SV("{}"), std::chrono::local_seconds(-6h));60 check(SV("1969-12-31 23:59:59"), SV("{}"), std::chrono::local_seconds(-1s));61 62 check(SV("1970-01-01 00:00:00"), SV("{}"), std::chrono::local_seconds(0s));63 check(SV("2000-01-01 00:00:00"), SV("{}"), std::chrono::local_seconds(946'684'800s));64 check(SV("2000-01-01 01:02:03"), SV("{}"), std::chrono::local_seconds(946'688'523s));65 66 check(SV("2038-01-19 03:14:07"), SV("{}"), std::chrono::local_seconds(2'147'483'647s));67 check(SV("2514-05-30 01:53:03"), SV("{}"), std::chrono::local_seconds(17'179'869'183s)); // Maximum value for 35 bits.68 69 check(SV("2000-01-01 01:02:03.123"), SV("{}"), std::chrono::local_time<std::chrono::milliseconds>(946'688'523'123ms));70 71 std::locale::global(std::locale::classic());72}73 74template <class CharT>75static void test_valid_values_year() {76 using namespace std::literals::chrono_literals;77 78 constexpr std::basic_string_view<CharT> fmt =79 SV("{:%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");80 constexpr std::basic_string_view<CharT> lfmt =81 SV("{:L%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");82 83 const std::locale loc(LOCALE_ja_JP_UTF_8);84 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));85 86 // Non localized output using C-locale87 check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),88 fmt,89 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 197090 91 check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),92 fmt,93 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 200994 95 // Use the global locale (fr_FR)96 check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),97 lfmt,98 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 197099 100 check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),101 lfmt,102 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009103 104 // Use supplied locale (ja_JP). This locale has a different alternate.105#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)106 check(loc,107 SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),108 lfmt,109 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970110 111 check(loc,112 SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),113 lfmt,114 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009115#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)116 check(loc,117 SV("%C='19'\t%EC='昭和'\t%y='70'\t%Oy='七十'\t%Ey='45'\t%Y='1970'\t%EY='昭和45年'\n"),118 lfmt,119 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970120 121 check(loc,122 SV("%C='20'\t%EC='平成'\t%y='09'\t%Oy='九'\t%Ey='21'\t%Y='2009'\t%EY='平成21年'\n"),123 lfmt,124 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009125#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)126 127 std::locale::global(std::locale::classic());128}129 130template <class CharT>131static void test_valid_values_month() {132 using namespace std::literals::chrono_literals;133 134 constexpr std::basic_string_view<CharT> fmt = SV("{:%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");135 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");136 137 const std::locale loc(LOCALE_ja_JP_UTF_8);138 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));139 140 // Non localized output using C-locale141 check(SV("%b='Jan'\t%h='Jan'\t%B='January'\t%m='01'\t%Om='01'\n"),142 fmt,143 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970144 145 check(SV("%b='May'\t%h='May'\t%B='May'\t%m='05'\t%Om='05'\n"),146 fmt,147 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033148 149 // Use the global locale (fr_FR)150#if defined(__APPLE__)151 check(SV("%b='jan'\t%h='jan'\t%B='janvier'\t%m='01'\t%Om='01'\n"),152 lfmt,153 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970154#else155 check(SV("%b='janv.'\t%h='janv.'\t%B='janvier'\t%m='01'\t%Om='01'\n"),156 lfmt,157 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970158#endif159 160 check(SV("%b='mai'\t%h='mai'\t%B='mai'\t%m='05'\t%Om='05'\n"),161 lfmt,162 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033163 164 // Use supplied locale (ja_JP). This locale has a different alternate.165#ifdef _WIN32166 check(loc,167 SV("%b='1'\t%h='1'\t%B='1月'\t%m='01'\t%Om='01'\n"),168 lfmt,169 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970170 171 check(loc,172 SV("%b='5'\t%h='5'\t%B='5月'\t%m='05'\t%Om='05'\n"),173 lfmt,174 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033175#elif defined(_AIX) // _WIN32176 check(loc,177 SV("%b='1月'\t%h='1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),178 lfmt,179 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970180 181 check(loc,182 SV("%b='5月'\t%h='5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),183 lfmt,184 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033185#elif defined(__APPLE__) // _WIN32186 check(loc,187 SV("%b=' 1'\t%h=' 1'\t%B='1月'\t%m='01'\t%Om='01'\n"),188 lfmt,189 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970190 191 check(loc,192 SV("%b=' 5'\t%h=' 5'\t%B='5月'\t%m='05'\t%Om='05'\n"),193 lfmt,194 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033195#elif defined(__FreeBSD__) // _WIN32196 check(loc,197 SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),198 lfmt,199 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970200 201 check(loc,202 SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),203 lfmt,204 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033205#else // _WIN32206 check(loc,207 SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='一'\n"),208 lfmt,209 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970210 211 check(loc,212 SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='五'\n"),213 lfmt,214 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033215#endif // _WIN32216 217 std::locale::global(std::locale::classic());218}219 220template <class CharT>221static void test_valid_values_day() {222 using namespace std::literals::chrono_literals;223 224 constexpr std::basic_string_view<CharT> fmt = SV("{:%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");225 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");226 227 const std::locale loc(LOCALE_ja_JP_UTF_8);228 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));229 230 // Non localized output using C-locale231 check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),232 fmt,233 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970234 235 check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),236 fmt,237 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009238 239 // Use the global locale (fr_FR)240 check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),241 lfmt,242 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970243 244 check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),245 lfmt,246 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009247 248 // Use supplied locale (ja_JP). This locale has a different alternate.249#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)250 check(loc,251 SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),252 lfmt,253 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970254 255 check(loc,256 SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),257 lfmt,258 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009259#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)260 check(loc,261 SV("%d='01'\t%Od='一'\t%e=' 1'\t%Oe='一'\n"),262 lfmt,263 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970264 265 check(loc,266 SV("%d='13'\t%Od='十三'\t%e='13'\t%Oe='十三'\n"),267 lfmt,268 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009269 270#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)271 272 std::locale::global(std::locale::classic());273}274 275template <class CharT>276static void test_valid_values_weekday() {277 using namespace std::literals::chrono_literals;278 279 constexpr std::basic_string_view<CharT> fmt =280 SV("{:%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");281 constexpr std::basic_string_view<CharT> lfmt =282 SV("{:L%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");283 284 const std::locale loc(LOCALE_ja_JP_UTF_8);285 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));286 287 // Non localized output using C-locale288 check(SV("%a='Thu'\t%A='Thursday'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),289 fmt,290 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970291 292 check(SV("%a='Sun'\t%A='Sunday'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),293 fmt,294 std::chrono::local_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106295 296 // Use the global locale (fr_FR)297#if defined(__APPLE__)298 check(SV("%a='Jeu'\t%A='Jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),299 lfmt,300 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970301 302 check(SV("%a='Dim'\t%A='Dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),303 lfmt,304 std::chrono::local_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106305#else306 check(SV("%a='jeu.'\t%A='jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),307 lfmt,308 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970309 310 check(SV("%a='dim.'\t%A='dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),311 lfmt,312 std::chrono::local_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106313#endif314 315 // Use supplied locale (ja_JP).316 // This locale has a different alternate, but not on all platforms317#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)318 check(loc,319 SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),320 lfmt,321 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970322 323 check(loc,324 SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),325 lfmt,326 std::chrono::local_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106327#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)328 check(loc,329 SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\n"),330 lfmt,331 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970332 333 check(loc,334 SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\n"),335 lfmt,336 std::chrono::local_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106337#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)338 339 std::locale::global(std::locale::classic());340}341 342template <class CharT>343static void test_valid_values_day_of_year() {344 using namespace std::literals::chrono_literals;345 346 constexpr std::basic_string_view<CharT> fmt = SV("{:%%j='%j'%n}");347 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%j='%j'%n}");348 349 const std::locale loc(LOCALE_ja_JP_UTF_8);350 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));351 352 // Non localized output using C-locale353 check(SV("%j='001'\n"), fmt, std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970354 check(SV("%j='138'\n"), fmt, std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033355 356 // Use the global locale (fr_FR)357 check(SV("%j='001'\n"), lfmt, std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970358 check(SV("%j='138'\n"), lfmt, std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033359 360 // Use supplied locale (ja_JP). This locale has a different alternate.361 check(loc, SV("%j='001'\n"), lfmt, std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970362 363 check(loc,364 SV("%j='138'\n"),365 lfmt,366 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033367 368 std::locale::global(std::locale::classic());369}370 371template <class CharT>372static void test_valid_values_week() {373 using namespace std::literals::chrono_literals;374 375 constexpr std::basic_string_view<CharT> fmt = SV("{:%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");376 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");377 378 const std::locale loc(LOCALE_ja_JP_UTF_8);379 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));380 381 // Non localized output using C-locale382 check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),383 fmt,384 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970385 386 check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),387 fmt,388 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033389 390 // Use the global locale (fr_FR)391 check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),392 lfmt,393 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970394 395 check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),396 lfmt,397 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033398 399 // Use supplied locale (ja_JP). This locale has a different alternate.400#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)401 check(loc,402 SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),403 lfmt,404 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970405 406 check(loc,407 SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),408 lfmt,409 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033410#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)411 check(loc,412 SV("%U='00'\t%OU='〇'\t%W='00'\t%OW='〇'\n"),413 lfmt,414 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970415 416 check(loc,417 SV("%U='20'\t%OU='二十'\t%W='20'\t%OW='二十'\n"),418 lfmt,419 std::chrono::local_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033420#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)421 std::locale::global(std::locale::classic());422}423 424template <class CharT>425static void test_valid_values_iso_8601_week() {426 using namespace std::literals::chrono_literals;427 428 constexpr std::basic_string_view<CharT> fmt = SV("{:%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");429 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");430 431 const std::locale loc(LOCALE_ja_JP_UTF_8);432 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));433 434 // Non localized output using C-locale435 check(SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),436 fmt,437 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970438 439 check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),440 fmt,441 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009442 443 // Use the global locale (fr_FR)444 check(SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),445 lfmt,446 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970447 448 check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),449 lfmt,450 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009451 452 // Use supplied locale (ja_JP). This locale has a different alternate.453#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)454 check(loc,455 SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),456 lfmt,457 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970458 459 check(loc,460 SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),461 lfmt,462 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009463#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)464 check(loc,465 SV("%g='70'\t%G='1970'\t%V='01'\t%OV='一'\n"),466 lfmt,467 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970468 469 check(loc,470 SV("%g='09'\t%G='2009'\t%V='07'\t%OV='七'\n"),471 lfmt,472 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009473#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)474 475 std::locale::global(std::locale::classic());476}477 478template <class CharT>479static void test_valid_values_date() {480 using namespace std::literals::chrono_literals;481 482 constexpr std::basic_string_view<CharT> fmt = SV("{:%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");483 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");484 485 const std::locale loc(LOCALE_ja_JP_UTF_8);486 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));487 488 // Non localized output using C-locale489 check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/70'\t%Ex='01/01/70'\n"),490 fmt,491 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970492 493 check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='02/13/09'\t%Ex='02/13/09'\n"),494 fmt,495 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009496 497 // Use the global locale (fr_FR)498#if defined(__APPLE__) || defined(__FreeBSD__)499 check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01.01.1970'\t%Ex='01.01.1970'\n"),500 lfmt,501 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970502 503 check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13.02.2009'\t%Ex='13.02.2009'\n"),504 lfmt,505 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009506#else507 check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/1970'\t%Ex='01/01/1970'\n"),508 lfmt,509 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970510 511 check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13/02/2009'\t%Ex='13/02/2009'\n"),512 lfmt,513 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009514#endif515 516 // Use supplied locale (ja_JP). This locale has a different alternate.517#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)518 check(loc,519 SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970/01/01'\t%Ex='1970/01/01'\n"),520 lfmt,521 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970522 523 check(loc,524 SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009/02/13'\t%Ex='2009/02/13'\n"),525 lfmt,526 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009527#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)528 check(loc,529 SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970年01月01日'\t%Ex='昭和45年01月01日'\n"),530 lfmt,531 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970532 533 check(loc,534 SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009年02月13日'\t%Ex='平成21年02月13日'\n"),535 lfmt,536 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009537#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)538 539 std::locale::global(std::locale::classic());540}541 542template <class CharT>543static void test_valid_values_time() {544 using namespace std::literals::chrono_literals;545 546 constexpr std::basic_string_view<CharT> fmt = SV(547 "{:"548 "%%H='%H'%t"549 "%%OH='%OH'%t"550 "%%I='%I'%t"551 "%%OI='%OI'%t"552 "%%M='%M'%t"553 "%%OM='%OM'%t"554 "%%S='%S'%t"555 "%%OS='%OS'%t"556 "%%p='%p'%t"557 "%%R='%R'%t"558 "%%T='%T'%t"559 "%%r='%r'%t"560 "%%X='%X'%t"561 "%%EX='%EX'%t"562 "%n}");563 constexpr std::basic_string_view<CharT> lfmt = SV(564 "{:L"565 "%%H='%H'%t"566 "%%OH='%OH'%t"567 "%%I='%I'%t"568 "%%OI='%OI'%t"569 "%%M='%M'%t"570 "%%OM='%OM'%t"571 "%%S='%S'%t"572 "%%OS='%OS'%t"573 "%%p='%p'%t"574 "%%R='%R'%t"575 "%%T='%T'%t"576 "%%r='%r'%t"577 "%%X='%X'%t"578 "%%EX='%EX'%t"579 "%n}");580 581 const std::locale loc(LOCALE_ja_JP_UTF_8);582 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));583 584 // Non localized output using C-locale585 check(SV("%H='00'\t"586 "%OH='00'\t"587 "%I='12'\t"588 "%OI='12'\t"589 "%M='00'\t"590 "%OM='00'\t"591 "%S='00'\t"592 "%OS='00'\t"593 "%p='AM'\t"594 "%R='00:00'\t"595 "%T='00:00:00'\t"596 "%r='12:00:00 AM'\t"597 "%X='00:00:00'\t"598 "%EX='00:00:00'\t"599 "\n"),600 fmt,601 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970602 603 check(SV("%H='23'\t"604 "%OH='23'\t"605 "%I='11'\t"606 "%OI='11'\t"607 "%M='31'\t"608 "%OM='31'\t"609 "%S='30.123'\t"610 "%OS='30.123'\t"611 "%p='PM'\t"612 "%R='23:31'\t"613 "%T='23:31:30.123'\t"614 "%r='11:31:30 PM'\t"615 "%X='23:31:30'\t"616 "%EX='23:31:30'\t"617 "\n"),618 fmt,619 std::chrono::local_time<std::chrono::milliseconds>(620 1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009621 // Use the global locale (fr_FR)622 check(SV("%H='00'\t"623 "%OH='00'\t"624 "%I='12'\t"625 "%OI='12'\t"626 "%M='00'\t"627 "%OM='00'\t"628 "%S='00'\t"629 "%OS='00'\t"630#if defined(_AIX)631 "%p='AM'\t"632#else633 "%p=''\t"634#endif635 "%R='00:00'\t"636 "%T='00:00:00'\t"637#ifdef _WIN32638 "%r='00:00:00'\t"639#elif defined(_AIX)640 "%r='12:00:00 AM'\t"641#elif defined(__APPLE__) || defined(__FreeBSD__)642 "%r=''\t"643#else644 "%r='12:00:00 '\t"645#endif646 "%X='00:00:00'\t"647 "%EX='00:00:00'\t"648 "\n"),649 lfmt,650 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970651 652 check(SV("%H='23'\t"653 "%OH='23'\t"654 "%I='11'\t"655 "%OI='11'\t"656 "%M='31'\t"657 "%OM='31'\t"658 "%S='30,123'\t"659 "%OS='30,123'\t"660#if defined(_AIX)661 "%p='PM'\t"662#else663 "%p=''\t"664#endif665 "%R='23:31'\t"666 "%T='23:31:30,123'\t"667#ifdef _WIN32668 "%r='23:31:30'\t"669#elif defined(_AIX)670 "%r='11:31:30 PM'\t"671#elif defined(__APPLE__) || defined(__FreeBSD__)672 "%r=''\t"673#else674 "%r='11:31:30 '\t"675#endif676 "%X='23:31:30'\t"677 "%EX='23:31:30'\t"678 "\n"),679 lfmt,680 std::chrono::local_time<std::chrono::milliseconds>(681 1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009682 683 // Use supplied locale (ja_JP). This locale has a different alternate.a684#if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)685 check(loc,686 SV("%H='00'\t"687 "%OH='00'\t"688 "%I='12'\t"689 "%OI='12'\t"690 "%M='00'\t"691 "%OM='00'\t"692 "%S='00'\t"693 "%OS='00'\t"694 "%p='午前'\t"695 "%R='00:00'\t"696 "%T='00:00:00'\t"697# if defined(__APPLE__) || defined(__FreeBSD__)698 "%r='12:00:00 午前'\t"699 "%X='00時00分00秒'\t"700 "%EX='00時00分00秒'\t"701# elif defined(_WIN32)702 "%r='0:00:00'\t"703 "%X='0:00:00'\t"704 "%EX='0:00:00'\t"705# else706 "%r='午前12:00:00'\t"707 "%X='00:00:00'\t"708 "%EX='00:00:00'\t"709# endif710 "\n"),711 lfmt,712 std::chrono::hh_mm_ss(0s));713 714 check(loc,715 SV("%H='23'\t"716 "%OH='23'\t"717 "%I='11'\t"718 "%OI='11'\t"719 "%M='31'\t"720 "%OM='31'\t"721 "%S='30.123'\t"722 "%OS='30.123'\t"723 "%p='午後'\t"724 "%R='23:31'\t"725 "%T='23:31:30.123'\t"726# if defined(__APPLE__) || defined(__FreeBSD__)727 "%r='11:31:30 午後'\t"728 "%X='23時31分30秒'\t"729 "%EX='23時31分30秒'\t"730# elif defined(_WIN32)731 "%r='23:31:30'\t"732 "%X='23:31:30'\t"733 "%EX='23:31:30'\t"734# else735 "%r='午後11:31:30'\t"736 "%X='23:31:30'\t"737 "%EX='23:31:30'\t"738# endif739 "\n"),740 lfmt,741 std::chrono::hh_mm_ss(23h + 31min + 30s + 123ms));742#else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)743 check(loc,744 SV("%H='00'\t"745 "%OH='〇'\t"746 "%I='12'\t"747 "%OI='十二'\t"748 "%M='00'\t"749 "%OM='〇'\t"750 "%S='00'\t"751 "%OS='〇'\t"752 "%p='午前'\t"753 "%R='00:00'\t"754 "%T='00:00:00'\t"755 "%r='午前12時00分00秒'\t"756 "%X='00時00分00秒'\t"757 "%EX='00時00分00秒'\t"758 "\n"),759 lfmt,760 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970761 762 check(loc,763 SV("%H='23'\t"764 "%OH='二十三'\t"765 "%I='11'\t"766 "%OI='十一'\t"767 "%M='31'\t"768 "%OM='三十一'\t"769 "%S='30.123'\t"770 "%OS='三十.123'\t"771 "%p='午後'\t"772 "%R='23:31'\t"773 "%T='23:31:30.123'\t"774 "%r='午後11時31分30秒'\t"775 "%X='23時31分30秒'\t"776 "%EX='23時31分30秒'\t"777 "\n"),778 lfmt,779 std::chrono::local_time<std::chrono::milliseconds>(780 1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009781#endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)782 783 std::locale::global(std::locale::classic());784}785 786template <class CharT>787static void test_valid_values_date_time() {788 using namespace std::literals::chrono_literals;789 790 constexpr std::basic_string_view<CharT> fmt = SV("{:%%c='%c'%t%%Ec='%Ec'%n}");791 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%c='%c'%t%%Ec='%Ec'%n}");792 793 const std::locale loc(LOCALE_ja_JP_UTF_8);794 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));795 796 // Non localized output using C-locale797 check(SV("%c='Thu Jan 1 00:00:00 1970'\t%Ec='Thu Jan 1 00:00:00 1970'\n"),798 fmt,799 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970800 801 check(SV("%c='Fri Feb 13 23:31:30 2009'\t%Ec='Fri Feb 13 23:31:30 2009'\n"),802 fmt,803 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009804 805 // Use the global locale (fr_FR)806 check(807// https://sourceware.org/bugzilla/show_bug.cgi?id=24054808#if defined(__powerpc__) && defined(__linux__)809 SV("%c='jeu. 01 janv. 1970 00:00:00 UTC'\t%Ec='jeu. 01 janv. 1970 00:00:00 UTC'\n"),810#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29811 SV("%c='jeu. 01 janv. 1970 00:00:00 GMT'\t%Ec='jeu. 01 janv. 1970 00:00:00 GMT'\n"),812#elif defined(_AIX)813 SV("%c=' 1 janvier 1970 à 00:00:00 UTC'\t%Ec=' 1 janvier 1970 à 00:00:00 UTC'\n"),814#elif defined(__APPLE__)815 SV("%c='Jeu 1 jan 00:00:00 1970'\t%Ec='Jeu 1 jan 00:00:00 1970'\n"),816#elif defined(_WIN32)817 SV("%c='01/01/1970 00:00:00'\t%Ec='01/01/1970 00:00:00'\n"),818#elif defined(__FreeBSD__)819 SV("%c='jeu. 1 janv. 00:00:00 1970'\t%Ec='jeu. 1 janv. 00:00:00 1970'\n"),820#else821 SV("%c='jeu. 01 janv. 1970 00:00:00'\t%Ec='jeu. 01 janv. 1970 00:00:00'\n"),822#endif823 lfmt,824 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970825 826 check(827// https://sourceware.org/bugzilla/show_bug.cgi?id=24054828#if defined(__powerpc__) && defined(__linux__)829 SV("%c='ven. 13 févr. 2009 23:31:30 UTC'\t%Ec='ven. 13 févr. 2009 23:31:30 UTC'\n"),830#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29831 SV("%c='ven. 13 févr. 2009 23:31:30 GMT'\t%Ec='ven. 13 févr. 2009 23:31:30 GMT'\n"),832#elif defined(_AIX)833 SV("%c='13 février 2009 à 23:31:30 UTC'\t%Ec='13 février 2009 à 23:31:30 UTC'\n"),834#elif defined(__APPLE__)835 SV("%c='Ven 13 fév 23:31:30 2009'\t%Ec='Ven 13 fév 23:31:30 2009'\n"),836#elif defined(_WIN32)837 SV("%c='13/02/2009 23:31:30'\t%Ec='13/02/2009 23:31:30'\n"),838#elif defined(__FreeBSD__)839 SV("%c='ven. 13 févr. 23:31:30 2009'\t%Ec='ven. 13 févr. 23:31:30 2009'\n"),840#else841 SV("%c='ven. 13 févr. 2009 23:31:30'\t%Ec='ven. 13 févr. 2009 23:31:30'\n"),842#endif843 lfmt,844 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009845 846 // Use supplied locale (ja_JP). This locale has a different alternate.a847#if defined(__APPLE__) || defined(__FreeBSD__)848 check(loc,849 SV("%c='木 1/ 1 00:00:00 1970'\t%Ec='木 1/ 1 00:00:00 1970'\n"),850 lfmt,851 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970852 check(loc,853 SV("%c='金 2/13 23:31:30 2009'\t%Ec='金 2/13 23:31:30 2009'\n"),854 lfmt,855 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009856#elif defined(_AIX) // defined(__APPLE__)|| defined(__FreeBSD__)857 check(loc,858 SV("%c='1970年01月 1日 00:00:00 UTC'\t%Ec='1970年01月 1日 00:00:00 UTC'\n"),859 lfmt,860 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970861 check(loc,862 SV("%c='2009年02月13日 23:31:30 UTC'\t%Ec='2009年02月13日 23:31:30 UTC'\n"),863 lfmt,864 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009865#elif defined(_WIN32) // defined(__APPLE__)|| defined(__FreeBSD__)866 check(loc,867 SV("%c='1970/01/01 0:00:00'\t%Ec='1970/01/01 0:00:00'\n"),868 lfmt,869 std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970870 check(loc,871 SV("%c='2009/02/13 23:31:30'\t%Ec='2009/02/13 23:31:30'\n"),872 lfmt,873 std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009874#else // defined(__APPLE__)|| defined(__FreeBSD__)875 check(loc,876 SV("%c='1970年01月01日 00時00分00秒'\t%Ec='昭和45年01月01日 00時00分00秒'\n"),877 lfmt,878 std::chrono::local_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970879 880 check(loc,881 SV("%c='2009年02月13日 23時31分30秒'\t%Ec='平成21年02月13日 23時31分30秒'\n"),882 lfmt,883 std::chrono::local_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009884#endif // defined(__APPLE__)|| defined(__FreeBSD__)885 886 std::locale::global(std::locale::classic());887}888 889template <class CharT>890static void test_valid_values() {891 test_valid_values_year<CharT>();892 test_valid_values_month<CharT>();893 test_valid_values_day<CharT>();894 test_valid_values_weekday<CharT>();895 test_valid_values_day_of_year<CharT>();896 test_valid_values_week<CharT>();897 test_valid_values_iso_8601_week<CharT>();898 test_valid_values_date<CharT>();899 test_valid_values_time<CharT>();900 test_valid_values_date_time<CharT>();901}902 903template <class CharT>904static void test() {905 using namespace std::literals::chrono_literals;906 907 test_no_chrono_specs<CharT>();908 test_valid_values<CharT>();909 check_invalid_types<CharT>(910 {911 SV("a"), SV("A"), SV("b"), SV("B"), SV("c"), SV("C"), SV("d"), SV("D"), SV("e"), SV("F"), SV("g"),912 SV("G"), SV("h"), SV("H"), SV("I"), SV("j"), SV("m"), SV("M"), SV("p"), SV("r"), SV("R"), SV("S"),913 SV("T"), SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("X"), SV("y"), SV("Y"), SV("Ec"),914 SV("EC"), SV("Ex"), SV("EX"), SV("Ey"), SV("EY"), SV("Od"), SV("Oe"), SV("OH"), SV("OI"), SV("Om"), SV("OM"),915 SV("OS"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"),916 },917 std::chrono::local_seconds(0s));918 919 check_exception("The format specifier expects a '%' or a '}'", SV("{:A"), std::chrono::local_seconds(0s));920 check_exception("The chrono specifiers contain a '{'", SV("{:%%{"), std::chrono::local_seconds(0s));921 check_exception("End of input while parsing a conversion specifier", SV("{:%"), std::chrono::local_seconds(0s));922 check_exception("End of input while parsing the modifier E", SV("{:%E"), std::chrono::local_seconds(0s));923 check_exception("End of input while parsing the modifier O", SV("{:%O"), std::chrono::local_seconds(0s));924 925 // Precision not allowed926 check_exception("The format specifier expects a '%' or a '}'", SV("{:.3}"), std::chrono::local_seconds(0s));927}928 929int main(int, char**) {930 test<char>();931 932#ifndef TEST_HAS_NO_WIDE_CHARACTERS933 test<wchar_t>();934#endif935 936 return 0;937}938