[libcxx-commits] [libcxx] b9f3d24 - [libc++][format] Fixes times before epoch.
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jul 18 12:17:17 PDT 2023
Author: Mark de Wever
Date: 2023-07-18T21:17:11+02:00
New Revision: b9f3d241f46c1d2cae42b01e72ef34a18d84c319
URL: https://github.com/llvm/llvm-project/commit/b9f3d241f46c1d2cae42b01e72ef34a18d84c319
DIFF: https://github.com/llvm/llvm-project/commit/b9f3d241f46c1d2cae42b01e72ef34a18d84c319.diff
LOG: [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
Added:
Modified:
libcxx/include/__chrono/convert_to_tm.h
libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp
libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp
libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h
index cc97bfd005a1b6..1301cd6f1f1ada 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 577ac35ac5259a..7853f2f3d5ac2d 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 692f41e4699848..4535a197781463 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 1c58fe7d0fcfe2..1f1cdccc2a08a3 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());
More information about the libcxx-commits
mailing list