// { dg-do run { target c++20 } } // { dg-require-namedlocale "fr_FR.ISO8859-15" } // { dg-timeout-factor 2 } #include #include #include void test_ostream() { using std::ostringstream; using namespace std::chrono; ostringstream ss; ss << day(1) << ' ' << day(11) << ' ' << day(21) << ' ' << day(31) << ' ' << day(41); auto s = ss.str(); VERIFY( s == "01 11 21 31 41 is not a valid day" ); ss.str(""); ss.imbue(std::locale(ISO_8859(15,fr_FR))); ss << day(1); VERIFY( ss.str() == "01" ); } void test_format() { using std::chrono::day; auto s = std::format("{:%d%%%e%t}{:%d%%%e%n}", day(1), day(11)); VERIFY( s == "01% 1\t11%11\n" ); auto ws = std::format(L"{:%d%%%e%t}{:%d%%%e%n}", day(1), day(11)); VERIFY( ws == L"01% 1\t11%11\n" ); VERIFY( std::format("{} {}", day(8), day(0)) == "08 00 is not a valid day" ); s = std::format("{:%Od}", day(1)); VERIFY( s == "01" ); s = std::format(std::locale::classic(), "{:%Od}", day(1)); VERIFY( s == "01" ); s = std::format(std::locale::classic(), "{:L%Od}", day(1)); VERIFY( s == "01" ); // TODO test "{:L%Od}" with locale that has alternative numeric rep. std::string_view specs = "aAbBcCdDeFgGhHIjmMpqQrRSTuUVwWxXyYzZ"; std::string_view my_specs = "de"; for (char c : specs) { char fmt[] = { '{', ':', '%', c, '}' }; try { day d(1); (void) std::vformat(std::string_view(fmt, 5), std::make_format_args(d)); // The call above should throw for any conversion-spec not in my_specs: VERIFY(my_specs.find(c) != my_specs.npos); } catch (const std::format_error& e) { VERIFY(my_specs.find(c) == my_specs.npos); std::string_view s = e.what(); // Libstdc++-specific message: VERIFY(s.find("format argument does not contain the information " "required by the chrono-specs") != s.npos); } } } void test_parse() { using namespace std::chrono; day d(0); minutes offset; std::string abbrev; std::istringstream is("2023-08-10 12:46 +01 BST<"); VERIFY( is >> parse("%F %R %z %Z", d, abbrev, offset) ); VERIFY( ! is.eof() ); VERIFY( d == 10d ); VERIFY( abbrev == "BST" ); VERIFY( offset == 60min ); abbrev = "nope"; offset = 999min; is.clear(); is.str("30"); VERIFY( is >> parse("%d", d, abbrev, offset) ); VERIFY( ! is.eof() ); VERIFY( d == 30d ); VERIFY( abbrev == "nope" ); VERIFY( offset == 999min ); d = day(255); is.clear(); is.str("2023-02-30"); is >> parse("%F", d); // Feb 30 is not a valid day VERIFY( is.fail() ); VERIFY( d == day(255) ); is.clear(); is.str("February 30"); is >> parse("%B %d", d); // Feb 30 is not a valid day VERIFY( is.fail() ); VERIFY( d == day(255) ); is.clear(); is.str("February 29"); is >> parse("%B %d", d); // But Feb 29 could be valid. VERIFY( is.good() ); VERIFY( d == 29d ); d = day(255); is.clear(); is.str("2023 Feb 29"); is >> parse("%Y %B %d", d); // But 2023 is not a leap year. VERIFY( is.fail() ); VERIFY( d == day(255) ); d = day(255); is.clear(); is.str("20 Feb 29"); is >> parse("%y %B %d", d); // But 2020 is a leap year. VERIFY( is.good() ); VERIFY( d == 29d ); } int main() { test_ostream(); test_format(); test_parse(); }