diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -270,20 +270,19 @@ // // TODO FMT evaluate the comment above. -# if defined(__GLIBC__) || defined(_AIX) +# if defined(__GLIBC__) || defined(_AIX) || defined(_WIN32) case _CharT('y'): // Glibc fails for negative values, AIX for positive values too. __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), (std::abs(__t.tm_year + 1900)) % 100); break; -# endif // defined(__GLIBC__) || defined(_AIX) +# endif // defined(__GLIBC__) || defined(_AIX) || defined(_WIN32) - case _CharT('Y'): { - int __year = __t.tm_year + 1900; - if (__year < 1000) - __formatter::__format_year(__year, __sstr); - else - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); - } break; + case _CharT('Y'): + // Depending on the platform's libc the range of supported years is + // limited. Intead of of testing all conditions use the internal + // implementation unconditionally. + __formatter::__format_year(__t.tm_year + 1900, __sstr); + break; case _CharT('F'): { int __year = __t.tm_year + 1900; diff --git a/libcxx/test/std/time/time.cal/time.cal.year/time.cal.year.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.year/time.cal.year.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.year/time.cal.year.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.year/time.cal.year.nonmembers/ostream.pass.cpp @@ -9,9 +9,6 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-localization -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT Fix this test using GCC, it currently crashes. // UNSUPPORTED: gcc-12 @@ -35,9 +32,16 @@ #include "make_string.h" #include "platform_support.h" // locale name macros #include "test_macros.h" +#include "assert_macros.h" +#include "concat_macros.h" #define SV(S) MAKE_STRING_VIEW(CharT, S) +#define TEST_EQUAL(OUT, EXPECTED) \ + TEST_REQUIRE(OUT == EXPECTED, \ + TEST_WRITE_CONCATENATED( \ + "\nExpression ", #OUT, "\nExpected output ", EXPECTED, "\nActual output ", OUT, '\n')); + template static std::basic_string stream_c_locale(std::chrono::year year) { std::basic_stringstream sstr; @@ -65,23 +69,23 @@ template static void test() { - assert(stream_c_locale(std::chrono::year{-32'768}) == SV("-32768 is not a valid year")); - assert(stream_c_locale(std::chrono::year{-32'767}) == SV("-32767")); - assert(stream_c_locale(std::chrono::year{0}) == SV("0000")); - assert(stream_c_locale(std::chrono::year{1970}) == SV("1970")); - assert(stream_c_locale(std::chrono::year{32'767}) == SV("32767")); - - assert(stream_fr_FR_locale(std::chrono::year{-32'768}) == SV("-32768 is not a valid year")); - assert(stream_fr_FR_locale(std::chrono::year{-32'767}) == SV("-32767")); - assert(stream_fr_FR_locale(std::chrono::year{0}) == SV("0000")); - assert(stream_fr_FR_locale(std::chrono::year{1970}) == SV("1970")); - assert(stream_fr_FR_locale(std::chrono::year{32'767}) == SV("32767")); - - assert(stream_ja_JP_locale(std::chrono::year{-32'768}) == SV("-32768 is not a valid year")); - assert(stream_ja_JP_locale(std::chrono::year{-32'767}) == SV("-32767")); - assert(stream_ja_JP_locale(std::chrono::year{0}) == SV("0000")); - assert(stream_ja_JP_locale(std::chrono::year{1970}) == SV("1970")); - assert(stream_ja_JP_locale(std::chrono::year{32'767}) == SV("32767")); + TEST_EQUAL(stream_c_locale(std::chrono::year{-32'768}), SV("-32768 is not a valid year")); + TEST_EQUAL(stream_c_locale(std::chrono::year{-32'767}), SV("-32767")); + TEST_EQUAL(stream_c_locale(std::chrono::year{0}), SV("0000")); + TEST_EQUAL(stream_c_locale(std::chrono::year{1970}), SV("1970")); + TEST_EQUAL(stream_c_locale(std::chrono::year{32'767}), SV("32767")); + + TEST_EQUAL(stream_fr_FR_locale(std::chrono::year{-32'768}), SV("-32768 is not a valid year")); + TEST_EQUAL(stream_fr_FR_locale(std::chrono::year{-32'767}), SV("-32767")); + TEST_EQUAL(stream_fr_FR_locale(std::chrono::year{0}), SV("0000")); + TEST_EQUAL(stream_fr_FR_locale(std::chrono::year{1970}), SV("1970")); + TEST_EQUAL(stream_fr_FR_locale(std::chrono::year{32'767}), SV("32767")); + + TEST_EQUAL(stream_ja_JP_locale(std::chrono::year{-32'768}), SV("-32768 is not a valid year")); + TEST_EQUAL(stream_ja_JP_locale(std::chrono::year{-32'767}), SV("-32767")); + TEST_EQUAL(stream_ja_JP_locale(std::chrono::year{0}), SV("0000")); + TEST_EQUAL(stream_ja_JP_locale(std::chrono::year{1970}), SV("1970")); + TEST_EQUAL(stream_ja_JP_locale(std::chrono::year{32'767}), SV("32767")); } int main(int, char**) { diff --git a/libcxx/test/std/time/time.syn/formatter.year.pass.cpp b/libcxx/test/std/time/time.syn/formatter.year.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.year.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.year.pass.cpp @@ -10,9 +10,6 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-localization -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT Fix this test using GCC, it currently crashes. // UNSUPPORTED: gcc-12 @@ -88,7 +85,7 @@ // Non localized output using C-locale check(SV("%C='00'\t" -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(_WIN32) "%EC='00'\t" #else "%EC='0'\t" @@ -97,7 +94,7 @@ "%Ey='00'\t" "%Oy='00'\t" "%Y='0000'\t" -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(_WIN32) "%EY='0000'\t" #elif defined(_AIX) "%EY=''\t" @@ -132,7 +129,7 @@ // Use the global locale (fr_FR) check(SV("%C='00'\t" -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(_WIN32) "%EC='00'\t" #else "%EC='0'\t" @@ -141,7 +138,7 @@ "%Ey='00'\t" "%Oy='00'\t" "%Y='0000'\t" -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(_WIN32) "%EY='0000'\t" #elif defined(_AIX) "%EY=''\t" @@ -175,10 +172,10 @@ std::chrono::year{2038}); // Use supplied locale (ja_JP). This locale has a different alternate. -#if defined(__APPLE__) || defined(_AIX) +#if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) check(SV("%C='00'\t" -# if defined(__APPLE__) +# if defined(__APPLE__) || defined(_WIN32) "%EC='00'\t" # else "%EC='0'\t" @@ -218,12 +215,12 @@ lfmt, std::chrono::year{2038}); -#else // defined(__APPLE__) || defined(_AIX) +#else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) check(loc, SV("%C='00'\t" "%EC='紀元前'\t" "%y='00'\t" -// https://sourceware.org/bugzilla/show_bug.cgi?id=23758 + // https://sourceware.org/bugzilla/show_bug.cgi?id=23758 # if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29 "%Ey='1'\t" # else @@ -231,7 +228,7 @@ # endif "%Oy='〇'\t" "%Y='0000'\t" -// https://sourceware.org/bugzilla/show_bug.cgi?id=23758 + // https://sourceware.org/bugzilla/show_bug.cgi?id=23758 # if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29 "%EY='紀元前1年'\t" # else @@ -265,7 +262,7 @@ "\n"), lfmt, std::chrono::year{2038}); -#endif // defined(__APPLE__) || defined(_AIX) +#endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) std::locale::global(std::locale::classic()); } @@ -273,7 +270,6 @@ template static void test_padding() { constexpr std::basic_string_view fmt = SV("{:%%C='%C'%t%%y='%y'%t%%Y='%Y'%t%n}"); - check(SV("%C='-100'\t%y='99'\t%Y='-9999'\t\n"), fmt, std::chrono::year{-9'999}); check(SV("%C='-10'\t%y='99'\t%Y='-0999'\t\n"), fmt, std::chrono::year{-999}); check(SV("%C='-1'\t%y='99'\t%Y='-0099'\t\n"), fmt, std::chrono::year{-99});