From b9f3d241f46c1d2cae42b01e72ef34a18d84c319 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Mon, 10 Jul 2023 07:59:58 +0200 Subject: [PATCH] [libc++][format] Fixes times before epoch. The number of days should be rounded down, for both positive and negative times since epoch. The original code truncated, which is correct for positive values, but wrong for negative values. Depends on D138826 Reviewed By: #libc, ldionne Differential Revision: https://reviews.llvm.org/D154865 --- libcxx/include/__chrono/convert_to_tm.h | 2 +- .../time.syn/formatter.file_time.pass.cpp | 20 ++++++++++++++++++ .../time.syn/formatter.local_time.pass.cpp | 21 +++++++++++++++++++ .../time/time.syn/formatter.sys_time.pass.cpp | 20 ++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h index cc97bfd005a1b..1301cd6f1f1ad 100644 --- a/libcxx/include/__chrono/convert_to_tm.h +++ b/libcxx/include/__chrono/convert_to_tm.h @@ -78,7 +78,7 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _Date& __date, chrono::weekday _ template _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const chrono::sys_time<_Duration> __tp) { - chrono::sys_days __days = chrono::time_point_cast(__tp); + chrono::sys_days __days = chrono::floor(__tp); chrono::year_month_day __ymd{__days}; _Tm __result = std::__convert_to_tm<_Tm>(chrono::year_month_day{__ymd}, chrono::weekday{__days}); diff --git a/libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp b/libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp index 577ac35ac5259..7853f2f3d5ac2 100644 --- a/libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp @@ -49,10 +49,30 @@ static void test_no_chrono_specs() { std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); // Non localized output + + // [time.syn] + // using nanoseconds = duration; + // using microseconds = duration; + // using milliseconds = duration; + // using seconds = duration; + // using minutes = duration>; + // using hours = duration>; + check(SV("1425-08-04 22:06:56"), SV("{}"), file_seconds(-17'179'869'184s)); // Minimum value for 35 bits. + check(SV("1901-12-13 20:45:52"), SV("{}"), file_seconds(-2'147'483'648s)); + + check(SV("1969-12-31 00:00:00"), SV("{}"), file_seconds(-24h)); + check(SV("1969-12-31 06:00:00"), SV("{}"), file_seconds(-18h)); + check(SV("1969-12-31 12:00:00"), SV("{}"), file_seconds(-12h)); + check(SV("1969-12-31 18:00:00"), SV("{}"), file_seconds(-6h)); + check(SV("1969-12-31 23:59:59"), SV("{}"), file_seconds(-1s)); + check(SV("1970-01-01 00:00:00"), SV("{}"), file_seconds(0s)); check(SV("2000-01-01 00:00:00"), SV("{}"), file_seconds(946'684'800s)); check(SV("2000-01-01 01:02:03"), SV("{}"), file_seconds(946'688'523s)); + check(SV("2038-01-19 03:14:07"), SV("{}"), file_seconds(2'147'483'647s)); + check(SV("2514-05-30 01:53:03"), SV("{}"), file_seconds(17'179'869'183s)); // Maximum value for 35 bits. + check(SV("2000-01-01 01:02:03.123"), SV("{}"), file_time(946'688'523'123ms)); std::locale::global(std::locale::classic()); diff --git a/libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp b/libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp index 692f41e469984..4535a19778146 100644 --- a/libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp @@ -42,10 +42,31 @@ static void test_no_chrono_specs() { std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); // Non localized output + + // [time.syn] + // using nanoseconds = duration; + // using microseconds = duration; + // using milliseconds = duration; + // using seconds = duration; + // using minutes = duration>; + // using hours = duration>; + check( + SV("1425-08-04 22:06:56"), SV("{}"), std::chrono::local_seconds(-17'179'869'184s)); // Minimum value for 35 bits. + check(SV("1901-12-13 20:45:52"), SV("{}"), std::chrono::local_seconds(-2'147'483'648s)); + + check(SV("1969-12-31 00:00:00"), SV("{}"), std::chrono::local_seconds(-24h)); + check(SV("1969-12-31 06:00:00"), SV("{}"), std::chrono::local_seconds(-18h)); + check(SV("1969-12-31 12:00:00"), SV("{}"), std::chrono::local_seconds(-12h)); + check(SV("1969-12-31 18:00:00"), SV("{}"), std::chrono::local_seconds(-6h)); + check(SV("1969-12-31 23:59:59"), SV("{}"), std::chrono::local_seconds(-1s)); + check(SV("1970-01-01 00:00:00"), SV("{}"), std::chrono::local_seconds(0s)); check(SV("2000-01-01 00:00:00"), SV("{}"), std::chrono::local_seconds(946'684'800s)); check(SV("2000-01-01 01:02:03"), SV("{}"), std::chrono::local_seconds(946'688'523s)); + check(SV("2038-01-19 03:14:07"), SV("{}"), std::chrono::local_seconds(2'147'483'647s)); + check(SV("2514-05-30 01:53:03"), SV("{}"), std::chrono::local_seconds(17'179'869'183s)); // Maximum value for 35 bits. + check(SV("2000-01-01 01:02:03.123"), SV("{}"), std::chrono::local_time(946'688'523'123ms)); std::locale::global(std::locale::classic()); diff --git a/libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp b/libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp index 1c58fe7d0fcfe..1f1cdccc2a08a 100644 --- a/libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp @@ -42,10 +42,30 @@ static void test_no_chrono_specs() { std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); // Non localized output + + // [time.syn] + // using nanoseconds = duration; + // using microseconds = duration; + // using milliseconds = duration; + // using seconds = duration; + // using minutes = duration>; + // using hours = duration>; + check(SV("1425-08-04 22:06:56"), SV("{}"), std::chrono::sys_seconds(-17'179'869'184s)); // Minimum value for 35 bits. + check(SV("1901-12-13 20:45:52"), SV("{}"), std::chrono::sys_seconds(-2'147'483'648s)); + + check(SV("1969-12-31 00:00:00"), SV("{}"), std::chrono::sys_seconds(-24h)); + check(SV("1969-12-31 06:00:00"), SV("{}"), std::chrono::sys_seconds(-18h)); + check(SV("1969-12-31 12:00:00"), SV("{}"), std::chrono::sys_seconds(-12h)); + check(SV("1969-12-31 18:00:00"), SV("{}"), std::chrono::sys_seconds(-6h)); + check(SV("1969-12-31 23:59:59"), SV("{}"), std::chrono::sys_seconds(-1s)); + check(SV("1970-01-01 00:00:00"), SV("{}"), std::chrono::sys_seconds(0s)); check(SV("2000-01-01 00:00:00"), SV("{}"), std::chrono::sys_seconds(946'684'800s)); check(SV("2000-01-01 01:02:03"), SV("{}"), std::chrono::sys_seconds(946'688'523s)); + check(SV("2038-01-19 03:14:07"), SV("{}"), std::chrono::sys_seconds(2'147'483'647s)); + check(SV("2514-05-30 01:53:03"), SV("{}"), std::chrono::sys_seconds(17'179'869'183s)); // Maximum value for 35 bits. + check(SV("2000-01-01 01:02:03.123"), SV("{}"), std::chrono::sys_time(946'688'523'123ms)); std::locale::global(std::locale::classic());