[PATCH v2] libstdc++: Test for formatting with empty spec for time points.
Tomasz Kaminski
tkaminsk@redhat.com
Wed Jun 4 11:22:38 GMT 2025
On Wed, Jun 4, 2025 at 1:08 PM Tomasz Kamiński <tkaminsk@redhat.com> wrote:
> Adding a tests for behavior of the ostream operator and the formatting
> with empty chronio-spec for the chrono types. Current coverage is:
>
This should say "chron-spec", consider it to be fixed locally.
> * time point, zoned_time and local_time_format in this commit,
> * duration and hh_mm_ss in r16-1099-gac0a04b7a254fb,
> * calendar types in r16-1016-g28a17985dd34b7.
>
> libstdc++-v3/ChangeLog:
>
> * testsuite/std/time/format/empty_spec.cc: New tests.
> ---
> The only change is mention of the duration test in commit message,
> after the rebase. OK for trunk?
>
> .../testsuite/std/time/format/empty_spec.cc | 208 ++++++++++++++++--
> 1 file changed, 194 insertions(+), 14 deletions(-)
>
> diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
> b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
> index 46942dc30fc..1cb0066a608 100644
> --- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
> +++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
> @@ -12,6 +12,46 @@ 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()
> @@ -37,20 +77,6 @@ test_padding()
> VERIFY( res == WIDEN("==16 is not a valid month==") );
> }
>
> -template<typename T, typename _CharT>
> -void verify(const T& t, const _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 Ret = void>
> struct Rep
> {
> @@ -553,6 +579,159 @@ test_calendar()
> 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
> + 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") );
> +}
> +
> +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") );
> +}
> +
> +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>();
> + test_zoned_time<CharT>();
> + test_local_time_format<CharT>();
> +
> + test_no_empty_spec<CharT, sys_time<years>>();
> + test_no_empty_spec<CharT, sys_time<duration<float>>>();
> +}
> +
> template<typename CharT>
> void
> test_all()
> @@ -560,6 +739,7 @@ test_all()
> test_padding<CharT>();
> test_durations<CharT>();
> test_calendar<CharT>();
> + test_time_points<CharT>();
> }
>
> int main()
> --
> 2.49.0
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250604/6dd3e1d1/attachment-0001.htm>
More information about the Libstdc++
mailing list