[libcxx-commits] [libcxx] [libc++][TZDB] Fixes reverse time lookups. (PR #89502)
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Apr 23 10:45:12 PDT 2024
https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/89502
>From 4f37c08bf11ab272d24dd3c339e4ca11b1273647 Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Wed, 17 Apr 2024 21:00:22 +0200
Subject: [PATCH] [libc++][TZDB] Fixes reverse time lookups.
Testing with the get_info() returning a local_info revealed some issues in
the reverse lookup. This needed an additional quirck. Also the skipping
when not in the current continuation optimization was wrong. It prevented
merging two sys_info objects.
---
libcxx/src/time_zone.cpp | 19 ++++-
.../get_info.sys_time.pass.cpp | 76 +++++++++++++++++++
2 files changed, 91 insertions(+), 4 deletions(-)
diff --git a/libcxx/src/time_zone.cpp b/libcxx/src/time_zone.cpp
index aef6ac674a11e6..928f3d2855e456 100644
--- a/libcxx/src/time_zone.cpp
+++ b/libcxx/src/time_zone.cpp
@@ -567,11 +567,22 @@ __first_rule(seconds __stdoff, const vector<__tz::__rule>& __rules) {
false};
}
- __named_rule_until __continuation_end{__continuation};
- if (__time >= __continuation_end.__until() && !__continuation_end.__needs_adjustment())
- // note std::unexpected<sys_seconds>(__end); is ambiguous with std::unexpected() in <exception>,
- return __sys_info_result{std::unexpect, __continuation_end.__until()};
+ if (__rule->__save.__time != 0s) {
+ // another fix for America/Punta_Arenas when not at the start of the
+ // sys_info object.
+ seconds __save = __rule->__save.__time;
+ if (__continuation_begin >= __rule_begin - __save && __time < __next.first) {
+ return __sys_info{
+ sys_info{__continuation_begin,
+ __next.first,
+ __continuation.__stdoff + __save,
+ chrono::duration_cast<minutes>(__save),
+ chrono::__format(__continuation, __rule->__letters, __save)},
+ false};
+ }
+ }
+ __named_rule_until __continuation_end{__continuation};
while (__next.second != __rules.end()) {
#ifdef PRINT
std::print(
diff --git a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp
index 25d2ff11d09341..1a1705d5ae59a5 100644
--- a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp
+++ b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp
@@ -1299,6 +1299,78 @@ static void test_america_indiana_knox() {
tz->get_info(to_sys_seconds(2006y, std::chrono::October, 29d, 6h, 59min, 59s)));
}
+static void test_america_punta_arenas() {
+ // Z America/Punta_Arenas -4:43:40 - LMT 1890
+ // ...
+ // -4 - -04 1919 Jul
+ // -4:42:45 - SMT 1927 S
+ // -5 x -05/-04 1932 S
+ // ...
+ //
+ // R x 1927 1931 - S 1 0 1 -
+ // R x 1928 1932 - Ap 1 0 0 -
+ // ...
+
+ using namespace std::literals::chrono_literals;
+ const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Punta_Arenas");
+
+ assert_equal(
+ std::chrono::sys_info(
+ to_sys_seconds(1927y, std::chrono::September, 1d, 4h, 42min, 45s),
+ to_sys_seconds(1928y, std::chrono::April, 1d, 4h),
+ -4h,
+ 60min,
+ "-04"),
+ tz->get_info(to_sys_seconds(1927y, std::chrono::September, 1d, 4h, 42min, 45s)));
+
+ assert_equal(
+ std::chrono::sys_info(
+ to_sys_seconds(1927y, std::chrono::September, 1d, 4h, 42min, 45s),
+ to_sys_seconds(1928y, std::chrono::April, 1d, 4h),
+ -4h,
+ 60min,
+ "-04"),
+ tz->get_info(to_sys_seconds(1928y, std::chrono::April, 1d, 3h, 59min, 59s)));
+}
+
+static void test_europ_ljubljana() {
+ // Z Europe/Ljubljana 0:58:4 - LMT 1884
+ // 1 - CET 1941 Ap 18 23
+ // 1 c CE%sT 1945 May 8 2s
+ // 1 1 CEST 1945 S 16 2s
+ // 1 - CET 1982 N 27
+ // 1 E CE%sT
+ //
+ // ...
+ // R c 1943 o - O 4 2s 0 -
+ // R c 1944 1945 - Ap M>=1 2s 1 S
+ // R c 1944 o - O 2 2s 0 -
+ // R c 1945 o - S 16 2s 0 -
+ // R c 1977 1980 - Ap Su>=1 2s 1 S
+ // ...
+
+ using namespace std::literals::chrono_literals;
+ const std::chrono::time_zone* tz = std::chrono::locate_zone("Europe/Ljubljana");
+
+ assert_equal(
+ std::chrono::sys_info(
+ to_sys_seconds(1945y, std::chrono::April, 2d, 1h),
+ to_sys_seconds(1945y, std::chrono::September, 16d, 1h),
+ 2h,
+ 60min,
+ "CEST"),
+ tz->get_info(to_sys_seconds(1945y, std::chrono::April, 2d, 1h)));
+
+ assert_equal(
+ std::chrono::sys_info(
+ to_sys_seconds(1945y, std::chrono::April, 2d, 1h),
+ to_sys_seconds(1945y, std::chrono::September, 16d, 1h),
+ 2h,
+ 60min,
+ "CEST"),
+ tz->get_info(to_sys_seconds(1945y, std::chrono::September, 16d, 0h, 59min, 59s)));
+}
+
int main(int, const char**) {
// Basic tests
test_gmt();
@@ -1333,5 +1405,9 @@ int main(int, const char**) {
test_america_ciudad_juarez();
test_america_indiana_knox();
+ // Reverse search bugs
+ test_america_punta_arenas();
+ test_europ_ljubljana();
+
return 0;
}
More information about the libcxx-commits
mailing list