blob: edfa196b71ca675a3e53f4899cda29e985e74bb6 [file] [log] [blame]
// { dg-do run { target c++20 } }
// { dg-require-namedlocale "fr_FR.ISO8859-15" }
// { dg-timeout-factor 2 }
#include <chrono>
#include <sstream>
#include <testsuite_hooks.h>
void
test_ostream()
{
using std::ostringstream;
using namespace std::chrono;
ostringstream ss;
for (int i = 1; i <= 12; ++i)
ss << month(i);
VERIFY( ss.str() == "JanFebMarAprMayJunJulAugSepOctNovDec" );
ss.str("");
ss << month(0) << '|' << month(13);
VERIFY( ss.str() == "0 is not a valid month|13 is not a valid month" );
ss.str("");
ss.imbue(std::locale(ISO_8859(15,fr_FR)));
ss << month(1);
VERIFY( ss.str() == "janv." );
ss.str("");
ss << month(0) << '|' << month(13);
VERIFY( ss.str() == "0 is not a valid month|13 is not a valid month" );
}
void
test_format()
{
using std::chrono::month;
auto s = std::format("{:%b%%%B%t%m%n}", month(1));
VERIFY( s == "Jan%January\t01\n" );
auto ws = std::format(L"{:%b%%%B%t%m%n}", month(12));
VERIFY( ws == L"Dec%December\t12\n" );
try
{
(void) std::format("{:%b}", month(13));
VERIFY(false);
}
catch (const std::format_error&)
{
}
s = std::format("{} is OK, but {:L}", month(2), month(13));
VERIFY( s == "Feb is OK, but 13 is not a valid month" );
std::locale loc_fr(ISO_8859(15,fr_FR));
s = std::format("{:%Om}", month(1));
VERIFY( s == "01" );
s = std::format(std::locale::classic(), "{:%Om}", month(1));
VERIFY( s == "01" );
s = std::format(std::locale::classic(), "{:L%Om}", month(1));
VERIFY( s == "01" );
s = std::format(loc_fr, "{:%Om}", month(1));
VERIFY( s == "01" );
s = std::format(loc_fr, "{:L%Om}", month(1));
VERIFY( s == "01" );
// TODO test "{:L%Om}" with locale that has alternative numeric rep.
s = std::format(loc_fr, "{:%b}", month(1));
VERIFY( s == "Jan" );
s = std::format(loc_fr, "{:L%b}", month(1));
VERIFY( s == "janv." );
s = std::format(loc_fr, "{:L}", month(0));
VERIFY( s == "0 is not a valid month" );
s = std::format(loc_fr, "{:L}", month(13));
VERIFY( s == "13 is not a valid month" );
std::string_view specs = "aAbBcCdDeFgGhHIjmMpqQrRSTuUVwWxXyYzZ";
std::string_view my_specs = "bBhm";
for (char c : specs)
{
char fmt[] = { '{', ':', '%', c, '}' };
try
{
month m(1);
(void) std::vformat(std::string_view(fmt, 5), std::make_format_args(m));
// 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;
std::istringstream is;
month m{};
is.str("JUL");
VERIFY( is >> parse("%B", m) );
VERIFY( is.eof() );
VERIFY( m == July );
is.clear();
is.str("junE bug");
VERIFY( is >> parse(" %b bug ", m) );
VERIFY( is.eof() );
VERIFY( m == June );
is.clear();
is.str("012");
VERIFY( is >> parse("%m", m) );
VERIFY( ! is.eof() );
VERIFY( is.peek() == '2' );
VERIFY( m == January );
is.clear();
is.str("012");
VERIFY( is >> parse("%4m", m) );
VERIFY( is.eof() );
VERIFY( m == December );
m = month(15);
is.clear();
is.str("Janvember");
VERIFY( is >> parse("%B", m) ); // Stops parsing after "Jan"
VERIFY( ! is.eof() );
VERIFY( is.peek() == 'v' );
VERIFY( m == January );
m = month(15);
is.clear();
is.str("Junuary");
VERIFY( is >> parse("%B", m) ); // Stops parsing after "Jun"
VERIFY( ! is.eof() );
VERIFY( is.peek() == 'u' );
VERIFY( m == June );
m = month(15);
is.clear();
is.str("Jebruary");
VERIFY( ! (is >> parse("%B", m)) );
VERIFY( is.fail() );
VERIFY( ! is.eof() );
is.clear();
VERIFY( is.peek() == 'e' );
VERIFY( m == month(15) );
m = month(13);
is.clear();
is.str("2023-6-31");
VERIFY( ! (is >> parse("%F", m)) ); // June only has 30 days.
VERIFY( ! is.eof() );
VERIFY( m == month(13) );
m = month(14);
is.clear();
is.str("2023-2-29");
VERIFY( ! (is >> parse("%Y-%m-%e", m)) ); // Feb only has 28 days in 2023.
VERIFY( ! is.eof() );
VERIFY( m == month(14) );
is.clear();
is.str("2-29");
VERIFY( is >> parse("%m-%d", m) ); // But Feb has 29 days in some years.
VERIFY( ! is.eof() );
VERIFY( m == February );
m = month(14);
is.clear();
is.str("6-31");
VERIFY( ! (is >> parse("%m-%d", m)) ); // June only has 30 days in all years.
VERIFY( ! is.eof() );
VERIFY( m == month(14) );
m = month(15);
is.clear();
is.str("2023-13-1");
VERIFY( ! (is >> parse("%F", m)) );
VERIFY( is.eof() );
VERIFY( m == month(15) );
m = month(16);
is.clear();
is.str("13/1/23");
VERIFY( ! (is >> parse("%D", m)) );
VERIFY( m == month(16) );
m = month(17);
is.clear();
is.str("13");
VERIFY( ! (is >> parse("%m", m)) );
VERIFY( ! is.eof() );
VERIFY( m == month(17) );
m = month(18);
is.clear();
is.str("1234");
VERIFY( ! (is >> parse("%3m", m)) );
VERIFY( ! is.eof() );
is.clear();
VERIFY( is.peek() == '4' );
VERIFY( m == month(18) );
is.clear();
is.str("2023-W32-5");
VERIFY( is >> parse("%G-W%V-%u", m) );
VERIFY( ! is.eof() );
VERIFY( m == August );
}
int main()
{
test_ostream();
test_format();
test_parse();
}