blob: ef1b19d688c7093160dc0546b7eabc012c696467 [file] [log] [blame]
// { dg-do run { target c++20 } }
// { dg-require-effective-target hosted }
// { dg-timeout-factor 5 }
#include <chrono>
#include <ranges>
#include <sstream>
#include <testsuite_hooks.h>
using namespace std::chrono;
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
#define WIDEN(S) WIDEN_(CharT, S)
template<typename CharT, typename T>
void
test_no_empty_spec()
{
try
{
T t{};
if constexpr (std::is_same_v<CharT, char>)
(void)std::vformat("{}", std::make_format_args(t));
#ifdef _GLIBCXX_USE_WCHAR_T
else
(void)std::vformat(L"{}", std::make_wformat_args(t));
#endif // _GLIBCXX_USE_WCHAR_T
VERIFY(false);
}
catch (const std::format_error&)
{
VERIFY(true);
}
}
template<typename T, typename CharT>
void verify(const T& t, std::basic_string_view<CharT> str)
{
std::basic_string<CharT> res;
res = std::format(WIDEN("{}"), t);
VERIFY( res == str );
std::basic_stringstream<CharT> os;
os << t;
res = std::move(os).str();
VERIFY( res == str );
}
template<typename T, typename CharT>
void verify(const T& t, const CharT* str)
{ verify(t, std::basic_string_view<CharT>(str)); }
template<typename CharT>
void
test_padding()
{
std::basic_string<CharT> res;
res = std::format(WIDEN("{:5}"), day(2));
VERIFY( res == WIDEN("02 ") );
res = std::format(WIDEN("{:>6}"), weekday(4));
VERIFY( res == WIDEN(" Thu") );
res = std::format(WIDEN("{:^7}"), month(3));
VERIFY( res == WIDEN(" Mar ") );
res = std::format(WIDEN("{:-<4}"), day(30));
VERIFY( res == WIDEN("30--") );
res = std::format(WIDEN("{:+>30}"), weekday(9));
VERIFY( res == WIDEN("++++++9 is not a valid weekday") );
res = std::format(WIDEN("{:=^27}"), month(16));
VERIFY( res == WIDEN("==16 is not a valid month==") );
}
template<typename Ret = void, typename Under = long>
struct Rep
{
using Return
= std::conditional_t<std::is_void_v<Ret>, Rep, Ret>;
Rep(Under v = 0) : val(v) {}
template<typename ORet, typename OUnder>
Rep(Rep<ORet, OUnder> o) : val(o.val) {}
operator Under() const
{ return val; }
Return
operator+() const
{ return val; }
Rep
operator-() const
{ return -val; }
friend Rep
operator+(Rep lhs, Rep rhs)
{ return lhs.val + rhs.val; }
friend Rep
operator-(Rep lhs, Rep rhs)
{ return lhs.val - rhs.val; }
friend Rep
operator*(Rep lhs, Rep rhs)
{ return lhs.val * rhs.val; }
friend Rep
operator/(Rep lhs, Rep rhs)
{ return lhs.val / rhs.val; }
friend auto operator<=>(Rep, Rep) = default;
template<typename CharT>
friend std::basic_ostream<CharT>&
operator<<(std::basic_ostream<CharT>& os, const Rep& t)
{ return os << t.val << WIDEN("[via <<]"); }
Under val;
};
template<typename Ret, typename Under1, typename Under2>
struct std::common_type<Rep<Ret, Under1>, Rep<Ret, Under2>>
{
using type = Rep<Ret, std::common_type_t<Under1, Under2>>;
};
template<typename Ret, typename Under, typename Other>
requires std::is_integral_v<Other>
struct std::common_type<Rep<Ret, Under>, Other>
{
using type = Rep<Ret, std::common_type_t<Under, Other>>;
};
template<typename Ret, typename Under, typename Other>
requires std::is_integral_v<Other>
struct std::common_type<Other, Rep<Ret, Under>>
: std::common_type<Rep<Ret, Under>, Other>
{ };
template<typename Ret, typename Under>
struct std::numeric_limits<Rep<Ret, Under>>
: std::numeric_limits<Under>
{ };
template<typename Ret, typename Under, typename CharT>
struct std::formatter<Rep<Ret, Under>, CharT>
: std::formatter<Under, CharT>
{
template<typename Out>
typename std::basic_format_context<Out, CharT>::iterator
format(const Rep<Ret>& t, std::basic_format_context<Out, CharT>& ctx) const
{
constexpr std::basic_string_view<CharT> suffix = WIDEN("[via format]");
auto out = std::formatter<Under, CharT>::format(t.val, ctx);
return std::ranges::copy(suffix, out).out;
}
};
using deciseconds = duration<seconds::rep, std::deci>;
template<typename CharT>
void
test_duration()
{
std::basic_string<CharT> res;
const milliseconds di(40);
verify( di, WIDEN("40ms") );
res = std::format(WIDEN("{:>6}"), di);
VERIFY( res == WIDEN(" 40ms") );
verify( -di, WIDEN("-40ms") );
res = std::format(WIDEN("{:>6}"), -di);
VERIFY( res == WIDEN(" -40ms") );
}
template<typename CharT>
void
test_duration_fp()
{
std::basic_string<CharT> res;
const duration<double> df(11.22);
verify( df, WIDEN("11.22s") );
res = std::format(WIDEN("{:=^12}"), df);
VERIFY( res == WIDEN("===11.22s===") );
verify( -df, WIDEN("-11.22s") );
res = std::format(WIDEN("{:=^12}"), -df);
VERIFY( res == WIDEN("==-11.22s===") );
// precision accepted but ignored
res = std::format(WIDEN("{:.6}"), df);
VERIFY( res == WIDEN("11.22s") );
}
template<typename CharT>
void
test_duration_cust()
{
std::basic_string<CharT> res;
const duration<char, std::ratio<1, 10>> charRep(123);
verify( charRep, WIDEN("123ds") );
// +asLong returns long, so formatted as long
const duration<Rep<long>> asLong(20);
verify( asLong, WIDEN("20s") );
res = std::format(WIDEN("{:>6}"), asLong);
VERIFY( res == WIDEN(" 20s") );
verify( -asLong, WIDEN("-20s") );
res = std::format(WIDEN("{:>6}"), -asLong);
VERIFY( res == WIDEN(" -20s") );
res = std::format(WIDEN("{:%Q}"), asLong);
VERIFY( res == WIDEN("20") );
res = std::format(WIDEN("{:+<7%Q}"), asLong);
VERIFY( res == WIDEN("20+++++") );
// +asRep returns Rep<>, so formatted as Rep<>
const duration<Rep<>> asRep(10);
verify( asRep, WIDEN("10[via <<]s") );
res = std::format(WIDEN("{:=^15}"), asRep);
VERIFY( res == WIDEN("==10[via <<]s==") );
verify( -asRep, WIDEN("-10[via <<]s") );
res = std::format(WIDEN("{:=^15}"), -asRep);
VERIFY( res == WIDEN("=-10[via <<]s==") );
res = std::format(WIDEN("{:%Q}"), asRep);
VERIFY( res == WIDEN("10[via format]") );
res = std::format(WIDEN("{:=^18%Q}"), asRep);
VERIFY( res == WIDEN("==10[via format]==") );
const duration<Rep<>, std::milli> milliRep(10);
verify( milliRep, WIDEN("10[via <<]ms") );
res = std::format(WIDEN("{:=^15}"), milliRep);
VERIFY( res == WIDEN("=10[via <<]ms==") );
verify( -milliRep, WIDEN("-10[via <<]ms") );
res = std::format(WIDEN("{:=^15}"), -milliRep);
VERIFY( res == WIDEN("=-10[via <<]ms=") );
res = std::format(WIDEN("{:%Q}"), milliRep);
VERIFY( res == WIDEN("10[via format]") );
res = std::format(WIDEN("{:=^18%Q}"), milliRep);
VERIFY( res == WIDEN("==10[via format]==") );
}
template<typename Ratio, typename Rep, typename Period>
constexpr auto
hms(const duration<Rep, Period>& d)
{
using Dur = duration<Rep, typename Ratio::period>;
return hh_mm_ss<Dur>(duration_cast<Dur>(d));
}
template<typename CharT>
void
test_hh_mm_ss()
{
auto dt = 22h + 24min + 54s + 111222333ns;
verify( hms<nanoseconds>(dt),
WIDEN("22:24:54.111222333") );
verify( hms<microseconds>(dt),
WIDEN("22:24:54.111222") );
verify( hms<milliseconds>(dt),
WIDEN("22:24:54.111") );
verify( hms<deciseconds>(dt),
WIDEN("22:24:54.1") );
verify( hms<seconds>(dt),
WIDEN("22:24:54") );
verify( hms<minutes>(dt),
WIDEN("22:24:00") );
verify( hms<hours>(dt),
WIDEN("22:00:00") );
verify( hms<nanoseconds>(-dt),
WIDEN("-22:24:54.111222333") );
verify( hms<microseconds>(-dt),
WIDEN("-22:24:54.111222") );
verify( hms<milliseconds>(-dt),
WIDEN("-22:24:54.111") );
verify( hms<deciseconds>(-dt),
WIDEN("-22:24:54.1") );
verify( hms<seconds>(-dt),
WIDEN("-22:24:54") );
verify( hms<minutes>(-dt),
WIDEN("-22:24:00") );
verify( hms<hours>(-dt),
WIDEN("-22:00:00") );
verify( hms<nanoseconds>(-dt),
WIDEN("-22:24:54.111222333") );
dt += 300h;
verify( hms<nanoseconds>(dt),
WIDEN("322:24:54.111222333") );
verify( hms<nanoseconds>(-dt),
WIDEN("-322:24:54.111222333") );
dt += 14000h;
verify( hms<nanoseconds>(dt),
WIDEN("14322:24:54.111222333") );
verify( hms<nanoseconds>(-dt),
WIDEN("-14322:24:54.111222333") );
}
template<typename CharT>
void
test_hh_mm_ss_fp()
{
duration<double> dt = 22h + 24min + 54s + 111222333ns;
// period controls number of subseconds
verify( hms<nanoseconds>(dt),
WIDEN("22:24:54.111222333") );
verify( hms<microseconds>(dt),
WIDEN("22:24:54.111222") );
verify( hms<milliseconds>(dt),
WIDEN("22:24:54.111") );
verify( hms<deciseconds>(dt),
WIDEN("22:24:54.1") );
verify( hms<seconds>(dt),
WIDEN("22:24:54") );
verify( hms<nanoseconds>(-dt),
WIDEN("-22:24:54.111222333") );
verify( hms<microseconds>(-dt),
WIDEN("-22:24:54.111222") );
verify( hms<milliseconds>(-dt),
WIDEN("-22:24:54.111") );
verify( hms<deciseconds>(-dt),
WIDEN("-22:24:54.1") );
verify( hms<seconds>(-dt),
WIDEN("-22:24:54") );
// but hour and minutes are preserved
verify( hms<minutes>(dt),
WIDEN("22:24:54") );
verify( hms<hours>(dt),
WIDEN("22:24:54") );
verify( hms<minutes>(-dt),
WIDEN("-22:24:54") );
verify( hms<hours>(-dt),
WIDEN("-22:24:54") );
}
template<typename CharT>
void
test_hh_mm_ss_cust()
{
const duration<char, deciseconds::period> charRep(123);
verify( hms<deciseconds>(charRep),
WIDEN("00:00:12.3") );
verify( hms<seconds>(charRep),
WIDEN("00:00:12") );
auto dt = 22h + 24min + 54s + 123ms;
// +plus returns long, so formatted as long
const duration<Rep<long>, std::milli> asLong(dt.count());
verify( hms<milliseconds>(asLong),
WIDEN("22:24:54.123") );
verify( hms<deciseconds>(asLong),
WIDEN("22:24:54.1") );
verify( hms<seconds>(asLong),
WIDEN("22:24:54") );
verify( hms<milliseconds>(-asLong),
WIDEN("-22:24:54.123") );
verify( hms<deciseconds>(-asLong),
WIDEN("-22:24:54.1") );
verify( hms<seconds>(-asLong),
WIDEN("-22:24:54") );
// +asRep returns Rep<>, so formatted as Rep<>
const duration<Rep<>, std::milli> asRep(dt.count());
verify( hms<milliseconds>(asRep),
WIDEN("22:24:54.123") );
verify( hms<deciseconds>(asRep),
WIDEN("22:24:54.1") );
verify( hms<seconds>(asLong),
WIDEN("22:24:54") );
verify( hms<milliseconds>(-asLong),
WIDEN("-22:24:54.123") );
verify( hms<deciseconds>(-asLong),
WIDEN("-22:24:54.1") );
verify( hms<seconds>(-asLong),
WIDEN("-22:24:54") );
}
template<typename CharT>
void
test_durations()
{
test_duration<CharT>();
test_duration_fp<CharT>();
test_duration_cust<CharT>();
test_hh_mm_ss<CharT>();
test_hh_mm_ss_fp<CharT>();
test_hh_mm_ss_cust<CharT>();
}
template<typename CharT>
void
test_day()
{
verify( day(0), WIDEN("00 is not a valid day") );
verify( day(1), WIDEN("01") );
verify( day(10), WIDEN("10") );
verify( day(32), WIDEN("32 is not a valid day") );
verify( day(110), WIDEN("110 is not a valid day") );
verify( day(255), WIDEN("255 is not a valid day") );
}
template<typename CharT>
void
test_month()
{
verify( month(0), WIDEN("0 is not a valid month") );
verify( month(1), WIDEN("Jan") );
verify( month(10), WIDEN("Oct") );
verify( month(32), WIDEN("32 is not a valid month") );
verify( month(110), WIDEN("110 is not a valid month") );
verify( month(100), WIDEN("100 is not a valid month") );
verify( month(110), WIDEN("110 is not a valid month") );
verify( month(255), WIDEN("255 is not a valid month") );
}
template<typename CharT>
void
test_year()
{
verify( year(-32768), WIDEN("-32768 is not a valid year") );
verify( year(-32767), WIDEN("-32767") );
verify( year(-67), WIDEN( "-0067") );
verify( year(-1), WIDEN( "-0001") );
verify( year(0), WIDEN( "0000") );
verify( year(1), WIDEN( "0001") );
verify( year(123), WIDEN( "0123") );
verify( year(2025), WIDEN( "2025") );
verify( year(32767), WIDEN( "32767") );
}
template<typename CharT>
void
test_weekday()
{
verify( weekday(0), WIDEN("Sun") );
verify( weekday(2), WIDEN("Tue") );
verify( weekday(6), WIDEN("Sat") );
verify( weekday(7), WIDEN("Sun") );
verify( weekday(9), WIDEN("9 is not a valid weekday") );
verify( weekday(32), WIDEN("32 is not a valid weekday") );
verify( weekday(110), WIDEN("110 is not a valid weekday") );
verify( weekday(255), WIDEN("255 is not a valid weekday") );
}
template<typename CharT>
void
test_weekday_indexed()
{
verify( weekday(0)[0], WIDEN("Sun[0 is not a valid index]") );
verify( weekday(2)[1], WIDEN("Tue[1]") );
verify( weekday(6)[5], WIDEN("Sat[5]") );
verify( weekday(7)[6], WIDEN("Sun[6 is not a valid index]") );
verify( weekday(7)[12], WIDEN("Sun[12 is not a valid index]") );
verify( weekday(5)[117], WIDEN("Fri[117 is not a valid index]") );
verify( weekday(7)[255], WIDEN("Sun[255 is not a valid index]") );
verify( weekday(9)[1], WIDEN("9 is not a valid weekday[1]") );
verify( weekday(32)[7], WIDEN("32 is not a valid weekday[7 is not a valid index]") );
}
template<typename CharT>
void
test_weekday_last()
{
verify( weekday(0)[last], WIDEN("Sun[last]") );
verify( weekday(9)[last], WIDEN("9 is not a valid weekday[last]") );
}
template<typename CharT>
void
test_month_day()
{
verify( month(1)/30, WIDEN("Jan/30") );
verify( month(3)/32, WIDEN("Mar/32 is not a valid day") );
verify( month(13)/30, WIDEN("13 is not a valid month/30") );
verify( month(13)/32, WIDEN("13 is not a valid month/32 is not a valid day") );
}
template<typename CharT>
void
test_month_day_last()
{
verify( month(1)/last, WIDEN("Jan/last") );
verify( month(14)/last, WIDEN("14 is not a valid month/last") );
}
template<typename CharT>
void
test_month_weekday()
{
verify( month(1)/weekday(2)[1],
WIDEN("Jan/Tue[1]") );
verify( month(3)/weekday(9)[2],
WIDEN("Mar/9 is not a valid weekday[2]") );
verify( month(13)/weekday(1)[7],
WIDEN("13 is not a valid month/Mon[7 is not a valid index]") );
verify( month(13)/weekday(10)[3],
WIDEN("13 is not a valid month/10 is not a valid weekday[3]") );
verify( month(13)/weekday(130)[0],
WIDEN("13 is not a valid month/130 is not a valid weekday[0 is not a valid index]") );
}
template<typename CharT>
void
test_month_weekday_last()
{
verify( month(1)/weekday(2)[last],
WIDEN("Jan/Tue[last]") );
verify( month(3)/weekday(9)[last],
WIDEN("Mar/9 is not a valid weekday[last]") );
verify( month(13)/weekday(1)[last],
WIDEN("13 is not a valid month/Mon[last]") );
verify( month(13)/weekday(10)[last],
WIDEN("13 is not a valid month/10 is not a valid weekday[last]") );
}
template<typename CharT>
void
test_year_month()
{
verify( year(2024)/month(1),
WIDEN("2024/Jan") );
verify( year(2025)/month(14),
WIDEN("2025/14 is not a valid month") );
verify( year(-32768)/month(2),
WIDEN("-32768 is not a valid year/Feb") );
verify( year(-32768)/month(0),
WIDEN("-32768 is not a valid year/0 is not a valid month") );
}
template<typename CharT>
void
test_year_month_day()
{
verify( year(2024)/month(1)/30,
WIDEN("2024-01-30") );
verify( year(-100)/month(14)/1,
WIDEN("-0100-14-01 is not a valid date") );
verify( year(2025)/month(11)/100,
WIDEN("2025-11-100 is not a valid date") );
verify( year(-32768)/month(2)/10,
WIDEN("-32768-02-10 is not a valid date") );
verify( year(-32768)/month(212)/10,
WIDEN("-32768-212-10 is not a valid date") );
verify( year(-32768)/month(2)/105,
WIDEN("-32768-02-105 is not a valid date") );
verify( year(-32768)/month(14)/55,
WIDEN("-32768-14-55 is not a valid date") );
}
template<typename CharT>
void
test_year_month_last()
{
verify( year(2024)/month(1)/last,
WIDEN("2024/Jan/last") );
verify( year(2025)/month(14)/last,
WIDEN("2025/14 is not a valid month/last") );
verify( year(-32768)/month(2)/last,
WIDEN("-32768 is not a valid year/Feb/last") );
verify( year(-32768)/month(0)/last,
WIDEN("-32768 is not a valid year/0 is not a valid month/last") );
}
template<typename CharT>
void
test_year_month_weekday()
{
verify( year(2024)/month(1)/weekday(2)[1],
WIDEN("2024/Jan/Tue[1]") );
verify( year(-1)/month(3)/weekday(9)[2],
WIDEN("-0001/Mar/9 is not a valid weekday[2]") );
verify( year(-32768)/month(13)/weekday(1)[7],
WIDEN("-32768 is not a valid year/13 is not a valid month/Mon[7 is not a valid index]") );
verify( year(-100)/month(13)/weekday(10)[3],
WIDEN("-0100/13 is not a valid month/10 is not a valid weekday[3]") );
verify( year(-32768)/month(13)/weekday(130)[0],
WIDEN("-32768 is not a valid year/13 is not a valid month/130 is not a valid weekday[0 is not a valid index]") );
}
template<typename CharT>
void
test_year_month_weekday_last()
{
verify( year(2024)/month(1)/weekday(2)[last],
WIDEN("2024/Jan/Tue[last]") );
verify( year(-1)/month(3)/weekday(9)[last],
WIDEN("-0001/Mar/9 is not a valid weekday[last]") );
verify( year(-32768)/month(13)/weekday(1)[last],
WIDEN("-32768 is not a valid year/13 is not a valid month/Mon[last]") );
verify( year(-100)/month(13)/weekday(10)[last],
WIDEN("-0100/13 is not a valid month/10 is not a valid weekday[last]") );
verify( year(-32768)/month(13)/weekday(130)[last],
WIDEN("-32768 is not a valid year/13 is not a valid month/130 is not a valid weekday[last]") );
}
template<typename CharT>
void
test_calendar()
{
test_day<CharT>();
test_month<CharT>();
test_year<CharT>();
test_weekday<CharT>();
test_weekday_indexed<CharT>();
test_weekday_last<CharT>();
test_month_day<CharT>();
test_month_day_last<CharT>();
test_month_weekday<CharT>();
test_month_weekday_last<CharT>();
test_year_month<CharT>();
test_year_month_day<CharT>();
test_year_month_last<CharT>();
test_year_month_weekday<CharT>();
test_year_month_weekday_last<CharT>();
}
template<typename Clock, typename Dur, typename Dur2>
constexpr auto
wall_cast(const local_time<Dur2>& tp)
{
using TP = time_point<Clock, std::common_type_t<Dur, days>>;
if constexpr (std::is_same_v<Clock, utc_clock> || std::is_same_v<Clock, file_clock>)
return clock_cast<Clock>(wall_cast<system_clock, Dur>(tp));
else if constexpr (std::is_same_v<Clock, tai_clock>)
return TP(floor<Dur>(tp.time_since_epoch()) + days(4383));
else if constexpr (std::is_same_v<Clock, gps_clock>)
return TP(floor<Dur>(tp.time_since_epoch()) - days(3657));
else // system_clock, local_t
return time_point<Clock, Dur>(floor<Dur>(tp.time_since_epoch()));
}
using decadays = duration<days::rep, std::ratio_multiply<std::deca, days::period>>;
using kilodays = duration<days::rep, std::ratio_multiply<std::kilo, days::period>>;
template<typename CharT, typename Clock>
void
test_time_point(bool daysAsTime)
{
std::basic_string<CharT> res;
const auto lt = local_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns;
auto strip_time = [daysAsTime](std::basic_string_view<CharT> sv)
{ return daysAsTime ? sv : sv.substr(0, 10); };
verify( wall_cast<Clock, nanoseconds>(lt),
WIDEN("2024-03-22 13:24:54.111222333") );
verify( wall_cast<Clock, microseconds>(lt),
WIDEN("2024-03-22 13:24:54.111222") );
verify( wall_cast<Clock, milliseconds>(lt),
WIDEN("2024-03-22 13:24:54.111") );
verify( wall_cast<Clock, seconds>(lt),
WIDEN("2024-03-22 13:24:54") );
verify( wall_cast<Clock, minutes>(lt),
WIDEN("2024-03-22 13:24:00") );
verify( wall_cast<Clock, hours>(lt),
WIDEN("2024-03-22 13:00:00") );
verify( wall_cast<Clock, days>(lt),
strip_time(WIDEN("2024-03-22 00:00:00")) );
verify( wall_cast<Clock, decadays>(lt),
strip_time(WIDEN("2024-03-18 00:00:00")) );
verify( wall_cast<Clock, kilodays>(lt),
strip_time(WIDEN("2022-01-08 00:00:00")) );
}
template<typename CharT>
void
test_leap_second()
{
std::basic_string<CharT> res;
const auto st = sys_days(2012y/June/30) + 23h + 59min + 59s + 111222333ns;
auto tp = clock_cast<utc_clock>(st);
tp += 1s;
verify( floor<nanoseconds>(tp),
WIDEN("2012-06-30 23:59:60.111222333") );
verify( floor<microseconds>(tp),
WIDEN("2012-06-30 23:59:60.111222") );
verify( floor<milliseconds>(tp),
WIDEN("2012-06-30 23:59:60.111") );
verify( floor<seconds>(tp),
WIDEN("2012-06-30 23:59:60") );
}
#if _GLIBCXX_USE_CXX11_ABI || !_GLIBCXX_USE_DUAL_ABI
template<typename Dur, typename Dur2>
auto
make_zoned(const sys_time<Dur2>& st, const time_zone* tz)
{ return zoned_time<Dur>(tz, floor<Dur>(st)); }
template<typename CharT>
void
test_zoned_time()
{
const auto st = sys_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns;
const time_zone* tz = locate_zone("Europe/Sofia");
VERIFY( tz != nullptr );
verify( make_zoned<nanoseconds>(st, tz),
WIDEN("2024-03-22 15:24:54.111222333 EET") );
verify( make_zoned<microseconds>(st, tz),
WIDEN("2024-03-22 15:24:54.111222 EET") );
verify( make_zoned<milliseconds>(st, tz),
WIDEN("2024-03-22 15:24:54.111 EET") );
verify( make_zoned<seconds>(st, tz),
WIDEN("2024-03-22 15:24:54 EET") );
verify( make_zoned<minutes>(st, tz),
WIDEN("2024-03-22 15:24:00 EET") );
verify( make_zoned<hours>(st, tz),
WIDEN("2024-03-22 15:00:00 EET") );
verify( make_zoned<days>(st, tz),
WIDEN("2024-03-22 02:00:00 EET") );
verify( make_zoned<decadays>(st, tz),
WIDEN("2024-03-18 02:00:00 EET") );
verify( make_zoned<kilodays>(st, tz),
WIDEN("2022-01-08 02:00:00 EET") );
}
#endif
template<typename Dur, typename Dur2>
auto
local_fmt(const local_time<Dur2>& lt, std::string* zone)
{ return local_time_format(floor<Dur>(lt), zone); }
template<typename CharT>
void
test_local_time_format()
{
std::basic_string<CharT> res;
std::string abbrev = "Zone";
const auto lt = local_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns;
res = std::format(WIDEN("{}"), local_fmt<nanoseconds>(lt, &abbrev));
VERIFY( res == WIDEN("2024-03-22 13:24:54.111222333 Zone") );
res = std::format(WIDEN("{}"), local_fmt<microseconds>(lt, &abbrev));
VERIFY( res == WIDEN("2024-03-22 13:24:54.111222 Zone") );
res = std::format(WIDEN("{}"), local_fmt<milliseconds>(lt, &abbrev));
VERIFY( res == WIDEN("2024-03-22 13:24:54.111 Zone") );
res = std::format(WIDEN("{}"), local_fmt<seconds>(lt, &abbrev));
VERIFY( res == WIDEN("2024-03-22 13:24:54 Zone") );
res = std::format(WIDEN("{}"), local_fmt<minutes>(lt, &abbrev));
VERIFY( res == WIDEN("2024-03-22 13:24:00 Zone") );
res = std::format(WIDEN("{}"), local_fmt<hours>(lt, &abbrev));
VERIFY( res == WIDEN("2024-03-22 13:00:00 Zone") );
res = std::format(WIDEN("{}"), local_fmt<days>(lt, &abbrev));
VERIFY( res == WIDEN("2024-03-22 00:00:00 Zone") );
res = std::format(WIDEN("{}"), local_fmt<decadays>(lt, &abbrev));
VERIFY( res == WIDEN("2024-03-18 00:00:00 Zone") );
res = std::format(WIDEN("{}"), local_fmt<kilodays>(lt, &abbrev));
VERIFY( res == WIDEN("2022-01-08 00:00:00 Zone") );
}
template<typename CharT>
void
test_time_points()
{
test_time_point<CharT, local_t>(false);
test_time_point<CharT, system_clock>(false);
test_time_point<CharT, utc_clock>(true);
test_time_point<CharT, tai_clock>(true);
test_time_point<CharT, gps_clock>(true);
test_time_point<CharT, file_clock>(true);
test_leap_second<CharT>();
#if _GLIBCXX_USE_CXX11_ABI || !_GLIBCXX_USE_DUAL_ABI
test_zoned_time<CharT>();
#endif
test_local_time_format<CharT>();
test_no_empty_spec<CharT, sys_time<years>>();
test_no_empty_spec<CharT, sys_time<duration<float>>>();
}
#if _GLIBCXX_USE_CXX11_ABI || !_GLIBCXX_USE_DUAL_ABI
template<typename CharT>
void
test_sys_info()
{
const sys_info si
{
sys_days(2024y/March/22) + 2h,
sys_days(2025y/April/11) + 23h + 15min + 10s,
2h + 13min + 4s,
15min,
"Zone"
};
const std::basic_string_view<CharT> txt
= WIDEN("[2024-03-22 02:00:00,2025-04-11 23:15:10,02:13:04,15min,Zone]");
verify( si, txt );
std::basic_string<CharT> res;
std::basic_string_view<CharT> sv;
sv = res = std::format(WIDEN("{:65}"), si);
VERIFY( sv.ends_with(WIDEN(" ")) );
sv.remove_suffix(4);
VERIFY( sv == txt );
sv = res = std::format(WIDEN("{:=^67}"), si);
VERIFY( sv.starts_with(WIDEN("===")) );
VERIFY( sv.ends_with(WIDEN("===")) );
sv.remove_prefix(3);
sv.remove_suffix(3);
VERIFY( sv == txt );
}
template<typename CharT>
void test_local_info()
{
using String = std::basic_string<CharT>;
using StringView = std::basic_string_view<CharT>;
const sys_info s1
{
sys_days(2015y/September/11) + 2h,
sys_days(2016y/March/13) + 2h,
-5h,
0h,
"EET"
};
const sys_info s2
{
sys_days(2016y/March/13) + 2h,
sys_days(2015y/September/15) + 2h,
-4h,
1h,
"EDT"
};
const StringView single
= WIDEN("[2015-09-11 02:00:00,2016-03-13 02:00:00,-05:00:00,0min,EET]");
const StringView both
= WIDEN(" local time between "
"[2015-09-11 02:00:00,2016-03-13 02:00:00,-05:00:00,0min,EET]"
" and "
"[2016-03-13 02:00:00,2015-09-15 02:00:00,-04:00:00,60min,EDT]");
const local_info l1{local_info::nonexistent, s1, s2};
auto exp = WIDEN("[nonexistent") + String(both) + WIDEN("]");
verify( l1, StringView(exp) );
const local_info l2{local_info::ambiguous, s1, s2};
exp = WIDEN("[ambiguous") + String(both) + WIDEN("]");
verify( l2, StringView(exp) );
const local_info l3{local_info::unique, s1, s1};
exp = WIDEN("[") + String(single) + WIDEN("]");
verify( l3, StringView(exp) );
String res;
StringView sv;
sv = res = std::format(WIDEN("{:65}"), l3);
VERIFY( sv.ends_with(WIDEN(" ")) );
sv.remove_suffix(3);
VERIFY( sv == exp );
sv = res = std::format(WIDEN("{:=^67}"), l3);
VERIFY( sv.starts_with(WIDEN("==")) );
VERIFY( sv.ends_with(WIDEN("===")) );
sv.remove_prefix(2);
sv.remove_suffix(3);
VERIFY( sv == exp );
}
template<typename CharT>
void
test_infos()
{
test_sys_info<CharT>();
test_local_info<CharT>();
}
#endif
template<typename CharT>
void
test_all()
{
test_padding<CharT>();
test_durations<CharT>();
test_calendar<CharT>();
test_time_points<CharT>();
#if _GLIBCXX_USE_CXX11_ABI || !_GLIBCXX_USE_DUAL_ABI
test_infos<CharT>();
#endif
}
int main()
{
test_all<char>();
#ifdef _GLIBCXX_USE_WCHAR_T
test_all<wchar_t>();
#endif // _GLIBCXX_USE_WCHAR_T
}