diff options
author | Mark de Wever <koraq@xs4all.nl> | 2023-07-10 07:59:58 +0200 |
---|---|---|
committer | Mark de Wever <koraq@xs4all.nl> | 2023-07-18 21:17:11 +0200 |
commit | b9f3d241f46c1d2cae42b01e72ef34a18d84c319 (patch) | |
tree | 7ba7d04f412fc0b5c2c0a1ab303b9cbed95a3833 /libcxx | |
parent | 1be4db73642fa0658d3b1e1dad7ec95259d1d261 (diff) | |
download | llvm-b9f3d241f46c1d2cae42b01e72ef34a18d84c319.zip llvm-b9f3d241f46c1d2cae42b01e72ef34a18d84c319.tar.gz llvm-b9f3d241f46c1d2cae42b01e72ef34a18d84c319.tar.bz2 |
[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
Diffstat (limited to 'libcxx')
4 files changed, 62 insertions, 1 deletions
diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h index cc97bfd..1301cd6 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 <class _Tm, class _Duration> _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const chrono::sys_time<_Duration> __tp) { - chrono::sys_days __days = chrono::time_point_cast<chrono::days>(__tp); + chrono::sys_days __days = chrono::floor<chrono::days>(__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 577ac35..7853f2f 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<signed integer type of at least 64 bits, nano>; + // using microseconds = duration<signed integer type of at least 55 bits, micro>; + // using milliseconds = duration<signed integer type of at least 45 bits, milli>; + // using seconds = duration<signed integer type of at least 35 bits>; + // using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>; + // using hours = duration<signed integer type of at least 23 bits, ratio<3600>>; + 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<std::chrono::milliseconds>(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 692f41e4..4535a19 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<signed integer type of at least 64 bits, nano>; + // using microseconds = duration<signed integer type of at least 55 bits, micro>; + // using milliseconds = duration<signed integer type of at least 45 bits, milli>; + // using seconds = duration<signed integer type of at least 35 bits>; + // using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>; + // using hours = duration<signed integer type of at least 23 bits, ratio<3600>>; + 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<std::chrono::milliseconds>(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 1c58fe7..1f1cdcc 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<signed integer type of at least 64 bits, nano>; + // using microseconds = duration<signed integer type of at least 55 bits, micro>; + // using milliseconds = duration<signed integer type of at least 45 bits, milli>; + // using seconds = duration<signed integer type of at least 35 bits>; + // using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>; + // using hours = duration<signed integer type of at least 23 bits, ratio<3600>>; + 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<std::chrono::milliseconds>(946'688'523'123ms)); std::locale::global(std::locale::classic()); |