968 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::file_time, 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 37// Modeled after the system clock's usings, this make adapting the38// tests easier.39template <class Duration>40using file_time = std::chrono::time_point<std::chrono::file_clock, Duration>;41using file_seconds = file_time<std::chrono::seconds>;42using file_days = file_time<std::chrono::days>;43 44template <class CharT>45static void test_no_chrono_specs() {46 using namespace std::literals::chrono_literals;47 48 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));49 50 // Non localized output51 52 // [time.syn]53 // using nanoseconds = duration<signed integer type of at least 64 bits, nano>;54 // using microseconds = duration<signed integer type of at least 55 bits, micro>;55 // using milliseconds = duration<signed integer type of at least 45 bits, milli>;56 // using seconds = duration<signed integer type of at least 35 bits>;57 // using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>;58 // using hours = duration<signed integer type of at least 23 bits, ratio<3600>>;59 check(SV("1425-08-04 22:06:56"), SV("{}"), file_seconds(-17'179'869'184s)); // Minimum value for 35 bits.60 check(SV("1901-12-13 20:45:52"), SV("{}"), file_seconds(-2'147'483'648s));61 62 check(SV("1969-12-31 00:00:00"), SV("{}"), file_seconds(-24h));63 check(SV("1969-12-31 06:00:00"), SV("{}"), file_seconds(-18h));64 check(SV("1969-12-31 12:00:00"), SV("{}"), file_seconds(-12h));65 check(SV("1969-12-31 18:00:00"), SV("{}"), file_seconds(-6h));66 check(SV("1969-12-31 23:59:59"), SV("{}"), file_seconds(-1s));67 68 check(SV("1970-01-01 00:00:00"), SV("{}"), file_seconds(0s));69 check(SV("2000-01-01 00:00:00"), SV("{}"), file_seconds(946'684'800s));70 check(SV("2000-01-01 01:02:03"), SV("{}"), file_seconds(946'688'523s));71 72 check(SV("2038-01-19 03:14:07"), SV("{}"), file_seconds(2'147'483'647s));73 check(SV("2514-05-30 01:53:03"), SV("{}"), file_seconds(17'179'869'183s)); // Maximum value for 35 bits.74 75 check(SV("2000-01-01 01:02:03.123"), SV("{}"), file_time<std::chrono::milliseconds>(946'688'523'123ms));76 77 std::locale::global(std::locale::classic());78}79 80template <class CharT>81static void test_valid_values_year() {82 using namespace std::literals::chrono_literals;83 84 constexpr std::basic_string_view<CharT> fmt =85 SV("{:%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");86 constexpr std::basic_string_view<CharT> lfmt =87 SV("{:L%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");88 89 const std::locale loc(LOCALE_ja_JP_UTF_8);90 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));91 92 // Non localized output using C-locale93 check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),94 fmt,95 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 197096 97 check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),98 fmt,99 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009100 101 // Use the global locale (fr_FR)102 check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),103 lfmt,104 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970105 106 check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),107 lfmt,108 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009109 110 // Use supplied locale (ja_JP). This locale has a different alternate.111#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)112 113 check(loc,114 SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),115 lfmt,116 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970117 118 check(loc,119 SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),120 lfmt,121 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009122#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)|| defined(__FreeBSD__)123 124 check(loc,125 SV("%C='19'\t%EC='昭和'\t%y='70'\t%Oy='七十'\t%Ey='45'\t%Y='1970'\t%EY='昭和45年'\n"),126 lfmt,127 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970128 129 check(loc,130 SV("%C='20'\t%EC='平成'\t%y='09'\t%Oy='九'\t%Ey='21'\t%Y='2009'\t%EY='平成21年'\n"),131 lfmt,132 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009133#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)|| defined(__FreeBSD__)134 135 std::locale::global(std::locale::classic());136}137 138template <class CharT>139static void test_valid_values_month() {140 using namespace std::literals::chrono_literals;141 142 constexpr std::basic_string_view<CharT> fmt = SV("{:%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");143 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");144 145 const std::locale loc(LOCALE_ja_JP_UTF_8);146 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));147 148 // Non localized output using C-locale149 check(SV("%b='Jan'\t%h='Jan'\t%B='January'\t%m='01'\t%Om='01'\n"),150 fmt,151 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970152 153 check(SV("%b='May'\t%h='May'\t%B='May'\t%m='05'\t%Om='05'\n"),154 fmt,155 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033156 157 // Use the global locale (fr_FR)158#if defined(__APPLE__)159 check(SV("%b='jan'\t%h='jan'\t%B='janvier'\t%m='01'\t%Om='01'\n"),160 lfmt,161 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970162#else163 check(SV("%b='janv.'\t%h='janv.'\t%B='janvier'\t%m='01'\t%Om='01'\n"),164 lfmt,165 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970166#endif167 168 check(SV("%b='mai'\t%h='mai'\t%B='mai'\t%m='05'\t%Om='05'\n"),169 lfmt,170 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033171 172 // Use supplied locale (ja_JP). This locale has a different alternate.173#ifdef _WIN32174 check(loc,175 SV("%b='1'\t%h='1'\t%B='1月'\t%m='01'\t%Om='01'\n"),176 lfmt,177 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970178 179 check(loc,180 SV("%b='5'\t%h='5'\t%B='5月'\t%m='05'\t%Om='05'\n"),181 lfmt,182 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033183#elif defined(_AIX) // _WIN32184 check(loc,185 SV("%b='1月'\t%h='1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),186 lfmt,187 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970188 189 check(loc,190 SV("%b='5月'\t%h='5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),191 lfmt,192 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033193#elif defined(__APPLE__) // _WIN32194 check(loc,195 SV("%b=' 1'\t%h=' 1'\t%B='1月'\t%m='01'\t%Om='01'\n"),196 lfmt,197 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970198 199 check(loc,200 SV("%b=' 5'\t%h=' 5'\t%B='5月'\t%m='05'\t%Om='05'\n"),201 lfmt,202 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033203#elif defined(__FreeBSD__) // _WIN32204 check(loc,205 SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),206 lfmt,207 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970208 209 check(loc,210 SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),211 lfmt,212 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033213#else // _WIN32214 check(loc,215 SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='一'\n"),216 lfmt,217 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970218 219 check(loc,220 SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='五'\n"),221 lfmt,222 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033223#endif // _WIN32224 225 std::locale::global(std::locale::classic());226}227 228template <class CharT>229static void test_valid_values_day() {230 using namespace std::literals::chrono_literals;231 232 constexpr std::basic_string_view<CharT> fmt = SV("{:%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");233 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");234 235 const std::locale loc(LOCALE_ja_JP_UTF_8);236 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));237 238 // Non localized output using C-locale239 check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"), fmt,240 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970241 242 check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),243 fmt,244 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009245 246 // Use the global locale (fr_FR)247 check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"), lfmt,248 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970249 250 check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),251 lfmt,252 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009253 254 // Use supplied locale (ja_JP). This locale has a different alternate.255#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)256 check(loc,257 SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),258 lfmt,259 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970260 261 check(loc,262 SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),263 lfmt,264 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009265#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)266 check(loc,267 SV("%d='01'\t%Od='一'\t%e=' 1'\t%Oe='一'\n"),268 lfmt,269 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970270 271 check(loc,272 SV("%d='13'\t%Od='十三'\t%e='13'\t%Oe='十三'\n"),273 lfmt,274 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009275 276#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)277 278 std::locale::global(std::locale::classic());279}280 281template <class CharT>282static void test_valid_values_weekday() {283 using namespace std::literals::chrono_literals;284 285 constexpr std::basic_string_view<CharT> fmt =286 SV("{:%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");287 constexpr std::basic_string_view<CharT> lfmt =288 SV("{:L%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");289 290 const std::locale loc(LOCALE_ja_JP_UTF_8);291 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));292 293 // Non localized output using C-locale294 check(SV("%a='Thu'\t%A='Thursday'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),295 fmt,296 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970297 298 check(SV("%a='Sun'\t%A='Sunday'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),299 fmt,300 file_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106301 302 // Use the global locale (fr_FR)303#if defined(__APPLE__)304 check(SV("%a='Jeu'\t%A='Jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),305 lfmt,306 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970307 308 check(SV("%a='Dim'\t%A='Dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),309 lfmt,310 file_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106311#else312 check(SV("%a='jeu.'\t%A='jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),313 lfmt,314 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970315 316 check(SV("%a='dim.'\t%A='dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),317 lfmt,318 file_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106319#endif320 321 // Use supplied locale (ja_JP).322 // This locale has a different alternate, but not on all platforms323#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)324 check(loc,325 SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),326 lfmt,327 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970328 329 check(loc,330 SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),331 lfmt,332 file_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106333#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)334 check(loc,335 SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\n"),336 lfmt,337 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970338 339 check(loc,340 SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\n"),341 lfmt,342 file_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106343#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)344 345 std::locale::global(std::locale::classic());346}347 348template <class CharT>349static void test_valid_values_day_of_year() {350 using namespace std::literals::chrono_literals;351 352 constexpr std::basic_string_view<CharT> fmt = SV("{:%%j='%j'%n}");353 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%j='%j'%n}");354 355 const std::locale loc(LOCALE_ja_JP_UTF_8);356 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));357 358 // Non localized output using C-locale359 check(SV("%j='001'\n"), fmt, file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970360 check(SV("%j='138'\n"), fmt, file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033361 362 // Use the global locale (fr_FR)363 check(SV("%j='001'\n"), lfmt, file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970364 check(SV("%j='138'\n"), lfmt, file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033365 366 // Use supplied locale (ja_JP). This locale has a different alternate.367 check(loc, SV("%j='001'\n"), lfmt, file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970368 369 check(loc, SV("%j='138'\n"), lfmt, file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033370 371 std::locale::global(std::locale::classic());372}373 374template <class CharT>375static void test_valid_values_week() {376 using namespace std::literals::chrono_literals;377 378 constexpr std::basic_string_view<CharT> fmt = SV("{:%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");379 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");380 381 const std::locale loc(LOCALE_ja_JP_UTF_8);382 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));383 384 // Non localized output using C-locale385 check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"), fmt,386 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970387 388 check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),389 fmt,390 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033391 392 // Use the global locale (fr_FR)393 check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"), lfmt,394 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970395 396 check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),397 lfmt,398 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033399 400 // Use supplied locale (ja_JP). This locale has a different alternate.401#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)402 check(loc,403 SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),404 lfmt,405 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970406 407 check(loc,408 SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),409 lfmt,410 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033411#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)412 check(loc,413 SV("%U='00'\t%OU='〇'\t%W='00'\t%OW='〇'\n"),414 lfmt,415 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970416 417 check(loc,418 SV("%U='20'\t%OU='二十'\t%W='20'\t%OW='二十'\n"),419 lfmt,420 file_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033421#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)422 std::locale::global(std::locale::classic());423}424 425template <class CharT>426static void test_valid_values_iso_8601_week() {427 using namespace std::literals::chrono_literals;428 429 constexpr std::basic_string_view<CharT> fmt = SV("{:%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");430 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");431 432 const std::locale loc(LOCALE_ja_JP_UTF_8);433 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));434 435 // Non localized output using C-locale436 check(SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"), fmt,437 file_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 file_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"), lfmt,445 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970446 447 check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),448 lfmt,449 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009450 451 // Use supplied locale (ja_JP). This locale has a different alternate.452#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)453 check(loc,454 SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),455 lfmt,456 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970457 458 check(loc,459 SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),460 lfmt,461 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009462#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)463 check(loc,464 SV("%g='70'\t%G='1970'\t%V='01'\t%OV='一'\n"),465 lfmt,466 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970467 468 check(loc,469 SV("%g='09'\t%G='2009'\t%V='07'\t%OV='七'\n"),470 lfmt,471 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009472#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)473 474 std::locale::global(std::locale::classic());475}476 477template <class CharT>478static void test_valid_values_date() {479 using namespace std::literals::chrono_literals;480 481 constexpr std::basic_string_view<CharT> fmt = SV("{:%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");482 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");483 484 const std::locale loc(LOCALE_ja_JP_UTF_8);485 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));486 487 // Non localized output using C-locale488 check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/70'\t%Ex='01/01/70'\n"),489 fmt,490 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970491 492 check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='02/13/09'\t%Ex='02/13/09'\n"),493 fmt,494 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009495 496 // Use the global locale (fr_FR)497#if defined(__APPLE__) || defined(__FreeBSD__)498 check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01.01.1970'\t%Ex='01.01.1970'\n"),499 lfmt,500 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970501 502 check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13.02.2009'\t%Ex='13.02.2009'\n"),503 lfmt,504 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009505#else506 check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/1970'\t%Ex='01/01/1970'\n"),507 lfmt,508 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970509 510 check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13/02/2009'\t%Ex='13/02/2009'\n"),511 lfmt,512 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009513#endif514 515 // Use supplied locale (ja_JP). This locale has a different alternate.516#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)517 check(loc,518 SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970/01/01'\t%Ex='1970/01/01'\n"),519 lfmt,520 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970521 522 check(loc,523 SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009/02/13'\t%Ex='2009/02/13'\n"),524 lfmt,525 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009526#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)527 check(loc,528 SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970年01月01日'\t%Ex='昭和45年01月01日'\n"),529 lfmt,530 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970531 532 check(loc,533 SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009年02月13日'\t%Ex='平成21年02月13日'\n"),534 lfmt,535 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009536#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)537 538 std::locale::global(std::locale::classic());539}540 541template <class CharT>542static void test_valid_values_time() {543 using namespace std::literals::chrono_literals;544 545 constexpr std::basic_string_view<CharT> fmt = SV(546 "{:"547 "%%H='%H'%t"548 "%%OH='%OH'%t"549 "%%I='%I'%t"550 "%%OI='%OI'%t"551 "%%M='%M'%t"552 "%%OM='%OM'%t"553 "%%S='%S'%t"554 "%%OS='%OS'%t"555 "%%p='%p'%t"556 "%%R='%R'%t"557 "%%T='%T'%t"558 "%%r='%r'%t"559 "%%X='%X'%t"560 "%%EX='%EX'%t"561 "%n}");562 constexpr std::basic_string_view<CharT> lfmt = SV(563 "{:L"564 "%%H='%H'%t"565 "%%OH='%OH'%t"566 "%%I='%I'%t"567 "%%OI='%OI'%t"568 "%%M='%M'%t"569 "%%OM='%OM'%t"570 "%%S='%S'%t"571 "%%OS='%OS'%t"572 "%%p='%p'%t"573 "%%R='%R'%t"574 "%%T='%T'%t"575 "%%r='%r'%t"576 "%%X='%X'%t"577 "%%EX='%EX'%t"578 "%n}");579 580 const std::locale loc(LOCALE_ja_JP_UTF_8);581 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));582 583 // Non localized output using C-locale584 check(SV("%H='00'\t"585 "%OH='00'\t"586 "%I='12'\t"587 "%OI='12'\t"588 "%M='00'\t"589 "%OM='00'\t"590 "%S='00'\t"591 "%OS='00'\t"592 "%p='AM'\t"593 "%R='00:00'\t"594 "%T='00:00:00'\t"595 "%r='12:00:00 AM'\t"596 "%X='00:00:00'\t"597 "%EX='00:00:00'\t"598 "\n"),599 fmt,600 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970601 602 check(SV("%H='23'\t"603 "%OH='23'\t"604 "%I='11'\t"605 "%OI='11'\t"606 "%M='31'\t"607 "%OM='31'\t"608 "%S='30.123'\t"609 "%OS='30.123'\t"610 "%p='PM'\t"611 "%R='23:31'\t"612 "%T='23:31:30.123'\t"613 "%r='11:31:30 PM'\t"614 "%X='23:31:30'\t"615 "%EX='23:31:30'\t"616 "\n"),617 fmt,618 std::chrono::sys_time<std::chrono::milliseconds>(619 1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009620 // Use the global locale (fr_FR)621 check(SV("%H='00'\t"622 "%OH='00'\t"623 "%I='12'\t"624 "%OI='12'\t"625 "%M='00'\t"626 "%OM='00'\t"627 "%S='00'\t"628 "%OS='00'\t"629#if defined(_AIX)630 "%p='AM'\t"631#else632 "%p=''\t"633#endif634 "%R='00:00'\t"635 "%T='00:00:00'\t"636#ifdef _WIN32637 "%r='00:00:00'\t"638#elif defined(_AIX)639 "%r='12:00:00 AM'\t"640#elif defined(__APPLE__) || defined(__FreeBSD__)641 "%r=''\t"642#else643 "%r='12:00:00 '\t"644#endif645 "%X='00:00:00'\t"646 "%EX='00:00:00'\t"647 "\n"),648 lfmt,649 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970650 651 check(SV("%H='23'\t"652 "%OH='23'\t"653 "%I='11'\t"654 "%OI='11'\t"655 "%M='31'\t"656 "%OM='31'\t"657 "%S='30,123'\t"658 "%OS='30,123'\t"659#if defined(_AIX)660 "%p='PM'\t"661#else662 "%p=''\t"663#endif664 "%R='23:31'\t"665 "%T='23:31:30,123'\t"666#ifdef _WIN32667 "%r='23:31:30'\t"668#elif defined(_AIX)669 "%r='11:31:30 PM'\t"670#elif defined(__APPLE__) || defined(__FreeBSD__)671 "%r=''\t"672#elif defined(_WIN32)673 "%r='23:31:30 '\t"674#else675 "%r='11:31:30 '\t"676#endif677 "%X='23:31:30'\t"678 "%EX='23:31:30'\t"679 "\n"),680 lfmt,681 std::chrono::sys_time<std::chrono::milliseconds>(682 1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009683 684 // Use supplied locale (ja_JP). This locale has a different alternate.a685#if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)686 check(loc,687 SV("%H='00'\t"688 "%OH='00'\t"689 "%I='12'\t"690 "%OI='12'\t"691 "%M='00'\t"692 "%OM='00'\t"693 "%S='00'\t"694 "%OS='00'\t"695 "%p='午前'\t"696 "%R='00:00'\t"697 "%T='00:00:00'\t"698# if defined(__APPLE__) || defined(__FreeBSD__)699 "%r='12:00:00 午前'\t"700 "%X='00時00分00秒'\t"701 "%EX='00時00分00秒'\t"702# elif defined(_WIN32)703 "%r='0:00:00'\t"704 "%X='0:00:00'\t"705 "%EX='0:00:00'\t"706# else707 "%r='午前12:00:00'\t"708 "%X='00:00:00'\t"709 "%EX='00:00:00'\t"710# endif711 "\n"),712 lfmt,713 std::chrono::hh_mm_ss(0s));714 715 check(loc,716 SV("%H='23'\t"717 "%OH='23'\t"718 "%I='11'\t"719 "%OI='11'\t"720 "%M='31'\t"721 "%OM='31'\t"722 "%S='30.123'\t"723 "%OS='30.123'\t"724 "%p='午後'\t"725 "%R='23:31'\t"726 "%T='23:31:30.123'\t"727# if defined(__APPLE__) || defined(__FreeBSD__)728 "%r='11:31:30 午後'\t"729 "%X='23時31分30秒'\t"730 "%EX='23時31分30秒'\t"731# elif defined(_WIN32)732 "%r='23:31:30'\t"733 "%X='23:31:30'\t"734 "%EX='23:31:30'\t"735# else736 "%r='午後11:31:30'\t"737 "%X='23:31:30'\t"738 "%EX='23:31:30'\t"739# endif740 "\n"),741 lfmt,742 std::chrono::hh_mm_ss(23h + 31min + 30s + 123ms));743#else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)744 check(loc,745 SV("%H='00'\t"746 "%OH='〇'\t"747 "%I='12'\t"748 "%OI='十二'\t"749 "%M='00'\t"750 "%OM='〇'\t"751 "%S='00'\t"752 "%OS='〇'\t"753 "%p='午前'\t"754 "%R='00:00'\t"755 "%T='00:00:00'\t"756 "%r='午前12時00分00秒'\t"757 "%X='00時00分00秒'\t"758 "%EX='00時00分00秒'\t"759 "\n"),760 lfmt,761 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970762 763 check(loc,764 SV("%H='23'\t"765 "%OH='二十三'\t"766 "%I='11'\t"767 "%OI='十一'\t"768 "%M='31'\t"769 "%OM='三十一'\t"770 "%S='30.123'\t"771 "%OS='三十.123'\t"772 "%p='午後'\t"773 "%R='23:31'\t"774 "%T='23:31:30.123'\t"775 "%r='午後11時31分30秒'\t"776 "%X='23時31分30秒'\t"777 "%EX='23時31分30秒'\t"778 "\n"),779 lfmt,780 std::chrono::sys_time<std::chrono::milliseconds>(781 1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009782#endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)783 784 std::locale::global(std::locale::classic());785}786 787template <class CharT>788static void test_valid_values_date_time() {789 using namespace std::literals::chrono_literals;790 791 constexpr std::basic_string_view<CharT> fmt = SV("{:%%c='%c'%t%%Ec='%Ec'%n}");792 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%c='%c'%t%%Ec='%Ec'%n}");793 794 const std::locale loc(LOCALE_ja_JP_UTF_8);795 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));796 797 // Non localized output using C-locale798 check(SV("%c='Thu Jan 1 00:00:00 1970'\t%Ec='Thu Jan 1 00:00:00 1970'\n"),799 fmt,800 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970801 802 check(SV("%c='Fri Feb 13 23:31:30 2009'\t%Ec='Fri Feb 13 23:31:30 2009'\n"),803 fmt,804 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009805 806 // Use the global locale (fr_FR)807 check(808// https://sourceware.org/bugzilla/show_bug.cgi?id=24054809#if defined(__powerpc__) && defined(__linux__)810 SV("%c='jeu. 01 janv. 1970 00:00:00 UTC'\t%Ec='jeu. 01 janv. 1970 00:00:00 UTC'\n"),811#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29812 SV("%c='jeu. 01 janv. 1970 00:00:00 GMT'\t%Ec='jeu. 01 janv. 1970 00:00:00 GMT'\n"),813#elif defined(_AIX)814 SV("%c=' 1 janvier 1970 à 00:00:00 UTC'\t%Ec=' 1 janvier 1970 à 00:00:00 UTC'\n"),815#elif defined(__APPLE__)816 SV("%c='Jeu 1 jan 00:00:00 1970'\t%Ec='Jeu 1 jan 00:00:00 1970'\n"),817#elif defined(_WIN32)818 SV("%c='01/01/1970 00:00:00'\t%Ec='01/01/1970 00:00:00'\n"),819#elif defined(__FreeBSD__)820 SV("%c='jeu. 1 janv. 00:00:00 1970'\t%Ec='jeu. 1 janv. 00:00:00 1970'\n"),821#else822 SV("%c='jeu. 01 janv. 1970 00:00:00'\t%Ec='jeu. 01 janv. 1970 00:00:00'\n"),823#endif824 lfmt,825 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970826 827 check(828// https://sourceware.org/bugzilla/show_bug.cgi?id=24054829#if defined(__powerpc__) && defined(__linux__)830 SV("%c='ven. 13 févr. 2009 23:31:30 UTC'\t%Ec='ven. 13 févr. 2009 23:31:30 UTC'\n"),831#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29832 SV("%c='ven. 13 févr. 2009 23:31:30 GMT'\t%Ec='ven. 13 févr. 2009 23:31:30 GMT'\n"),833#elif defined(_AIX)834 SV("%c='13 février 2009 à 23:31:30 UTC'\t%Ec='13 février 2009 à 23:31:30 UTC'\n"),835#elif defined(__APPLE__)836 SV("%c='Ven 13 fév 23:31:30 2009'\t%Ec='Ven 13 fév 23:31:30 2009'\n"),837#elif defined(_WIN32)838 SV("%c='13/02/2009 23:31:30'\t%Ec='13/02/2009 23:31:30'\n"),839#elif defined(__FreeBSD__)840 SV("%c='ven. 13 févr. 23:31:30 2009'\t%Ec='ven. 13 févr. 23:31:30 2009'\n"),841#else842 SV("%c='ven. 13 févr. 2009 23:31:30'\t%Ec='ven. 13 févr. 2009 23:31:30'\n"),843#endif844 lfmt,845 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009846 847 // Use supplied locale (ja_JP). This locale has a different alternate.a848#if defined(__APPLE__) || defined(__FreeBSD__)849 check(loc,850 SV("%c='木 1/ 1 00:00:00 1970'\t%Ec='木 1/ 1 00:00:00 1970'\n"),851 lfmt,852 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970853 check(loc,854 SV("%c='金 2/13 23:31:30 2009'\t%Ec='金 2/13 23:31:30 2009'\n"),855 lfmt,856 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009857#elif defined(_AIX) // defined(__APPLE__)|| defined(__FreeBSD__)858 check(loc,859 SV("%c='1970年01月 1日 00:00:00 UTC'\t%Ec='1970年01月 1日 00:00:00 UTC'\n"),860 lfmt,861 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970862 check(loc,863 SV("%c='2009年02月13日 23:31:30 UTC'\t%Ec='2009年02月13日 23:31:30 UTC'\n"),864 lfmt,865 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009866#elif defined(_WIN32) // defined(__APPLE__)|| defined(__FreeBSD__)867 check(loc,868 SV("%c='1970/01/01 0:00:00'\t%Ec='1970/01/01 0:00:00'\n"),869 lfmt,870 std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970871 check(loc,872 SV("%c='2009/02/13 23:31:30'\t%Ec='2009/02/13 23:31:30'\n"),873 lfmt,874 std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009875#else // defined(__APPLE__)|| defined(__FreeBSD__)876 check(loc,877 SV("%c='1970年01月01日 00時00分00秒'\t%Ec='昭和45年01月01日 00時00分00秒'\n"),878 lfmt,879 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970880 881 check(loc,882 SV("%c='2009年02月13日 23時31分30秒'\t%Ec='平成21年02月13日 23時31分30秒'\n"),883 lfmt,884 file_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009885#endif // defined(__APPLE__)|| defined(__FreeBSD__)886 887 std::locale::global(std::locale::classic());888}889 890template <class CharT>891static void test_valid_values_time_zone() {892 using namespace std::literals::chrono_literals;893 894 constexpr std::basic_string_view<CharT> fmt = SV("{:%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");895 constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");896 897 const std::locale loc(LOCALE_ja_JP_UTF_8);898 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));899 900 // Non localized output using C-locale901 check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='UTC'\n"),902 fmt,903 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970904 905 // Use the global locale (fr_FR)906 check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='UTC'\n"),907 lfmt,908 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970909 910 // Use supplied locale (ja_JP).911 check(loc,912 SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='UTC'\n"),913 lfmt,914 file_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970915 916 std::locale::global(std::locale::classic());917}918 919template <class CharT>920static void test_valid_values() {921 test_valid_values_year<CharT>();922 test_valid_values_month<CharT>();923 test_valid_values_day<CharT>();924 test_valid_values_weekday<CharT>();925 test_valid_values_day_of_year<CharT>();926 test_valid_values_week<CharT>();927 test_valid_values_iso_8601_week<CharT>();928 test_valid_values_date<CharT>();929 test_valid_values_time<CharT>();930 test_valid_values_date_time<CharT>();931 test_valid_values_time_zone<CharT>();932}933 934template <class CharT>935static void test() {936 using namespace std::literals::chrono_literals;937 938 test_no_chrono_specs<CharT>();939 test_valid_values<CharT>();940 941 check_invalid_types<CharT>(942 {SV("a"), SV("A"), SV("b"), SV("B"), SV("c"), SV("C"), SV("d"), SV("D"), SV("e"), SV("F"), SV("g"),943 SV("G"), SV("h"), SV("H"), SV("I"), SV("j"), SV("m"), SV("M"), SV("p"), SV("r"), SV("R"), SV("S"),944 SV("T"), SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("X"), SV("y"), SV("Y"), SV("z"),945 SV("Z"), SV("Ec"), SV("EC"), SV("Ex"), SV("EX"), SV("Ey"), SV("EY"), SV("Ez"), SV("Od"), SV("Oe"), SV("OH"),946 SV("OI"), SV("Om"), SV("OM"), SV("OS"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), SV("Oz")},947 file_seconds(0s));948 949 check_exception("The format specifier expects a '%' or a '}'", SV("{:A"), file_seconds(0s));950 check_exception("The chrono specifiers contain a '{'", SV("{:%%{"), file_seconds(0s));951 check_exception("End of input while parsing a conversion specifier", SV("{:%"), file_seconds(0s));952 check_exception("End of input while parsing the modifier E", SV("{:%E"), file_seconds(0s));953 check_exception("End of input while parsing the modifier O", SV("{:%O"), file_seconds(0s));954 955 // Precision not allowed956 check_exception("The format specifier expects a '%' or a '}'", SV("{:.3}"), file_seconds(0s));957}958 959int main(int, char**) {960 test<char>();961 962#ifndef TEST_HAS_NO_WIDE_CHARACTERS963 test<wchar_t>();964#endif965 966 return 0;967}968