[libcxx-commits] [libcxx] [libc++] Enable experimental tzdb on Apple platforms (PR #122010)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jan 8 07:17:19 PST 2025
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/122010
>From d335a22d9523c3a9ebed701dba4a1a9ad26d0096 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 7 Jan 2025 18:32:34 -0500
Subject: [PATCH 1/3] [libc++] Enable experimental tzdb on Apple platforms
This patch implements binary parsing of the leapseconds file provided
on Apple platforms and enables experimental tzdb support on Apple.
---
libcxx/CMakeLists.txt | 2 +-
libcxx/docs/ReleaseNotes/20.rst | 2 +
libcxx/src/experimental/tzdb.cpp | 134 +++++++++++++++++++++++++++----
3 files changed, 122 insertions(+), 16 deletions(-)
diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index abe12c2805a7cf..c957c12f081fa6 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -113,7 +113,7 @@ option(LIBCXX_ENABLE_MONOTONIC_CLOCK
#
# TODO TZDB make the default always ON when most platforms ship with the IANA
# database.
-if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|Darwin")
set(ENABLE_TIME_ZONE_DATABASE_DEFAULT ON)
else()
set(ENABLE_TIME_ZONE_DATABASE_DEFAULT OFF)
diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index c8a07fb8b73348..cc34127b5b2202 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -73,6 +73,8 @@ Improvements and New Features
optimized, resulting in a performance improvement of up to 2x for trivial element types (e.g., `std::vector<int>`),
and up to 3.4x for non-trivial element types (e.g., `std::vector<std::vector<int>>`).
+- Experimental support for ``std::chrono::tzdb`` has now been implemented on Apple platforms.
+
Deprecations and Removals
-------------------------
diff --git a/libcxx/src/experimental/tzdb.cpp b/libcxx/src/experimental/tzdb.cpp
index d22de21c998198..acc95960ade75f 100644
--- a/libcxx/src/experimental/tzdb.cpp
+++ b/libcxx/src/experimental/tzdb.cpp
@@ -50,6 +50,8 @@ namespace chrono {
_LIBCPP_WEAK string_view __libcpp_tzdb_directory() {
#if defined(__linux__)
return "/usr/share/zoneinfo/";
+#elif defined(__APPLE__)
+ return "/usr/share/zoneinfo/";
#else
# error "unknown path to the IANA Time Zone Database"
#endif
@@ -94,14 +96,23 @@ static void __skip(istream& __input, string_view __suffix) {
}
static void __matches(istream& __input, char __expected) {
- if (std::tolower(__input.get()) != __expected)
- std::__throw_runtime_error((string("corrupt tzdb: expected character '") + __expected + '\'').c_str());
+ _LIBCPP_ASSERT_INTERNAL(std::islower(__expected), "lowercase characters only here!");
+ char __c = __input.get();
+ if (std::tolower(__c) != __expected)
+ std::__throw_runtime_error(
+ (string("corrupt tzdb: expected character '") + __expected + "', got '" + __c + "'").c_str());
}
static void __matches(istream& __input, string_view __expected) {
- for (auto __c : __expected)
- if (std::tolower(__input.get()) != __c)
- std::__throw_runtime_error((string("corrupt tzdb: expected string '") + string(__expected) + '\'').c_str());
+ for (auto __c : __expected) {
+ _LIBCPP_ASSERT_INTERNAL(std::islower(__c), "lowercase strings only here!");
+ char __actual = __input.get();
+ if (std::tolower(__actual) != __c)
+ std::__throw_runtime_error(
+ (string("corrupt tzdb: expected character '") + __c + "' from string '" + string(__expected) + "', got '" +
+ __actual + "' instead")
+ .c_str());
+ }
}
[[nodiscard]] static string __parse_string(istream& __input) {
@@ -621,7 +632,96 @@ static void __parse_tzdata(tzdb& __db, __tz::__rules_storage_type& __rules, istr
}
}
-static void __parse_leap_seconds(vector<leap_second>& __leap_seconds, istream&& __input) {
+// This function parses the leap-seconds "binary file" compiled from the .list file
+// by the zic compiler. That format is what's provided on some platforms like Darwin.
+//
+// The format looks like:
+//
+// # Leap YEAR MON DAY 23:59:60 + S
+// Leap 1972 Jun 30 23:59:60 + S
+// Leap 1972 Dec 31 23:59:60 + S
+// Leap 1973 Dec 31 23:59:60 + S
+//
+inline vector<leap_second> __parse_leap_seconds_binary(istream&& __input) {
+ vector<leap_second> __result;
+ [&] {
+ while (true) {
+ switch (__input.peek()) {
+ case istream::traits_type::eof():
+ return;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ __input.get();
+ continue;
+
+ case '#':
+ chrono::__skip_line(__input);
+ continue;
+ }
+
+ chrono::__matches(__input, "leap");
+ chrono::__skip_mandatory_whitespace(__input);
+
+ year __year = chrono::__parse_year_value(__input);
+ chrono::__skip_mandatory_whitespace(__input);
+
+ month __month = chrono::__parse_month(__input);
+ chrono::__skip_mandatory_whitespace(__input);
+
+ day __day = chrono::__parse_day(__input);
+ chrono::__skip_mandatory_whitespace(__input);
+
+ hours __hour(chrono::__parse_integral(__input, /* leading zeros allowed */ true));
+ chrono::__matches(__input, ':');
+
+ minutes __minute(chrono::__parse_integral(__input, /* leading zeros allowed */ true));
+ chrono::__matches(__input, ':');
+
+ seconds __second(chrono::__parse_integral(__input, /* leading zeros allowed */ true));
+ chrono::__skip_mandatory_whitespace(__input);
+
+ // Now create a timestamp from everything we parsed
+ year_month_day __date = __year / __month / __day;
+ seconds __time = __hour + __minute + __second;
+ sys_seconds __timestamp = sys_seconds(sys_days(__date)) + __time;
+
+ // Finally, parse the value of the leap second (1s or -1s)
+ string __sign = __parse_string(__input);
+ seconds __value;
+ if (__sign == "+")
+ __value = seconds{1};
+ else if (__sign == "-")
+ __value = seconds{-1};
+ else
+ std::__throw_runtime_error(("corrupt tzdb: invalid leap second sign " + __sign).c_str());
+
+ chrono::__skip_line(__input);
+
+ __result.emplace_back(std::__private_constructor_tag{}, __timestamp, __value);
+ }
+ }();
+
+ // Ensure the leap seconds are sorted properly.
+ ranges::sort(__result, {}, &leap_second::date);
+
+ return __result;
+}
+
+// This function parses leap-seconds.list file as can be found at
+// https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list
+//
+// The format looks like
+//
+// #NTP Time DTAI Day Month Year
+// #
+// 2272060800 10 # 1 Jan 1972
+// 2287785600 11 # 1 Jul 1972
+// 2303683200 12 # 1 Jan 1973
+//
+// Where the timestamps are expressed as a number of seconds since 1 January 1900, 00:00:00.
+inline vector<leap_second> __parse_leap_seconds_list(istream&& __input) {
// The file stores dates since 1 January 1900, 00:00:00, we want
// seconds since 1 January 1970.
constexpr auto __offset = sys_days{1970y / January / 1} - sys_days{1900y / January / 1};
@@ -664,11 +764,21 @@ static void __parse_leap_seconds(vector<leap_second>& __leap_seconds, istream&&
// The database should contain the number of seconds inserted by a leap
// second (1 or -1). So the difference between the two elements is stored.
// std::ranges::views::adjacent has not been implemented yet.
+ vector<leap_second> __result;
(void)ranges::adjacent_find(__entries, [&](const __entry& __first, const __entry& __second) {
- __leap_seconds.emplace_back(
- std::__private_constructor_tag{}, __second.__timestamp, __second.__value - __first.__value);
+ __result.emplace_back(std::__private_constructor_tag{}, __second.__timestamp, __second.__value - __first.__value);
return false;
});
+ return __result;
+}
+
+// Parse leap seconds from the appropriate location based on the platform.
+static void __parse_leap_seconds(vector<leap_second>& __leap_seconds, filesystem::path const& __tzdb_directory) {
+#if defined(__APPLE__)
+ __leap_seconds.append_range(chrono::__parse_leap_seconds_binary(ifstream{__tzdb_directory / "leapseconds"}));
+#else
+ __leap_seconds.append_range(chrono::__parse_leap_seconds_list(ifstream{__tzdb_directory / "leap-seconds.list"}));
+#endif
}
void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
@@ -680,13 +790,7 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
ranges::sort(__tzdb.zones);
ranges::sort(__tzdb.links);
ranges::sort(__rules, {}, [](const auto& p) { return p.first; });
-
- // There are two files with the leap second information
- // - leapseconds as specified by zic
- // - leap-seconds.list the source data
- // The latter is much easier to parse, it seems Howard shares that
- // opinion.
- chrono::__parse_leap_seconds(__tzdb.leap_seconds, ifstream{__root / "leap-seconds.list"});
+ chrono::__parse_leap_seconds(__tzdb.leap_seconds, __root);
}
#ifdef _WIN32
>From ecef59431f66eb9844b590a67fdb4e0e9c3b4a24 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 8 Jan 2025 10:01:57 -0500
Subject: [PATCH 2/3] [WIP] Fix some tests for binary leap second parsing
---
libcxx/src/experimental/tzdb.cpp | 2 +-
.../time.zone.db/leap_seconds.pass.cpp | 46 +++++++++++++++----
.../time.zone/time.zone.db/rules.pass.cpp | 15 ++++--
.../time.zone/time.zone.db/version.pass.cpp | 5 +-
4 files changed, 52 insertions(+), 16 deletions(-)
diff --git a/libcxx/src/experimental/tzdb.cpp b/libcxx/src/experimental/tzdb.cpp
index acc95960ade75f..509b17e2ea15e4 100644
--- a/libcxx/src/experimental/tzdb.cpp
+++ b/libcxx/src/experimental/tzdb.cpp
@@ -100,7 +100,7 @@ static void __matches(istream& __input, char __expected) {
char __c = __input.get();
if (std::tolower(__c) != __expected)
std::__throw_runtime_error(
- (string("corrupt tzdb: expected character '") + __expected + "', got '" + __c + "'").c_str());
+ (string("corrupt tzdb: expected character '") + __expected + "', got '" + __c + "' instead").c_str());
}
static void __matches(istream& __input, string_view __expected) {
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp
index d7ae21926b4b26..e05279bfca4f6f 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp
@@ -28,10 +28,20 @@
#include "filesystem_test_helper.h"
#include "test_tzdb.h"
+#if defined(__APPLE__)
+# define TEST_USE_BINARY_LEAP_SECONDS
+#else
+# define TEST_USE_LIST_LEAP_SECONDS
+#endif
+
scoped_test_env env;
[[maybe_unused]] const std::filesystem::path dir = env.create_dir("zoneinfo");
const std::filesystem::path tzdata = env.create_file("zoneinfo/tzdata.zi");
-const std::filesystem::path leap_seconds = env.create_file("zoneinfo/leap-seconds.list");
+#ifdef TEST_USE_BINARY_LEAP_SECONDS
+const std::filesystem::path leap_seconds = env.create_file("zoneinfo/leapseconds");
+#else
+const std::filesystem::path leap_seconds = env.create_file("zoneinfo/leap-seconds.list");
+#endif
std::string_view std::chrono::__libcpp_tzdb_directory() {
static std::string result = dir.string();
@@ -65,21 +75,23 @@ static void test_exception(std::string_view input, [[maybe_unused]] std::string_
}
static void test_invalid() {
+#ifdef TEST_USE_BINARY_LEAP_SECONDS
+ test_exception("0", "corrupt tzdb: expected character 'l' from string 'leap', got '0' instead");
+ test_exception("Leap x", "corrupt tzdb: expected a digit");
+ test_exception("Leap 1970 J", "corrupt tzdb month: invalid name");
+ test_exception("Leap 1970 Jan 1 23:59:60 x", "corrupt tzdb: invalid leap second sign x");
+#else
test_exception("0", "corrupt tzdb: expected a non-zero digit");
-
test_exception("1", "corrupt tzdb: expected whitespace");
-
test_exception("1 ", "corrupt tzdb: expected a non-zero digit");
-
test_exception("5764607523034234880 2", "corrupt tzdb: integral too large");
+#endif
}
static void test_leap_seconds() {
using namespace std::chrono;
- // Test whether loading also sorts the entries in the proper order.
- const tzdb& result = parse(
- R"(
+ std::string list_format = R"(
2303683200 12 # 1 Jan 1973
2287785600 11 # 1 Jul 1972
2272060800 10 # 1 Jan 1972
@@ -91,7 +103,25 @@ static void test_leap_seconds() {
# largest accepted value by the parser
5764607523034234879 12
-)");
+)";
+
+ std::string binary_format = R"(
+Leap 1973 Jan 1 23:59:60 + S
+Leap 1972 Jul 1 23:59:60 + S
+Leap 1972 Jan 1 23:59:60 + S
+Leap 1900 Jan 2 23:59:60 + S # 2 Jan 1900 Dummy entry to test before 1970
+Leap 1900 Jan 2 00:00:01 + S # 2 Jan 1900 Dummy entry to test before 1970
+
+Leap 1973 Jan 2 23:59:60 - S # Fictional negative leap second
+Leap 32767 Jan 1 23:59:60 + S # Largest year accepted by the parser
+)";
+
+ // Test whether loading also sorts the entries in the proper order.
+#ifdef TEST_USE_BINARY_LEAP_SECONDS
+ const tzdb& result = parse(binary_format);
+#else
+ const tzdb& result = parse(list_format);
+#endif
assert(result.leap_seconds.size() == 6);
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp
index 7d9759320c535b..237a206b3a95bd 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp
@@ -20,9 +20,10 @@
// ADDITIONAL_COMPILE_FLAGS: -I %{libcxx-dir}/src/experimental/include
#include <chrono>
+#include <cstdio>
#include <fstream>
-#include <string>
#include <string_view>
+#include <string>
#include <variant>
#include "assert_macros.h"
@@ -96,7 +97,7 @@ static void test_invalid() {
test_exception("R r 0 mix", "corrupt tzdb: expected whitespace");
test_exception("R r 0 1", "corrupt tzdb: expected whitespace");
- test_exception("R r 0 1 X", "corrupt tzdb: expected character '-'");
+ test_exception("R r 0 1 X", "corrupt tzdb: expected character '-', got 'X' instead");
test_exception("R r 0 1 -", "corrupt tzdb: expected whitespace");
@@ -106,13 +107,17 @@ static void test_invalid() {
test_exception("R r 0 1 - Ja +", "corrupt tzdb weekday: invalid name");
test_exception("R r 0 1 - Ja 32", "corrupt tzdb day: value too large");
- test_exception("R r 0 1 - Ja l", "corrupt tzdb: expected string 'last'");
+ test_exception(
+ "R r 0 1 - Ja l",
+ std::string{"corrupt tzdb: expected character 'a' from string 'last', got '"} + (char)EOF + "' instead");
test_exception("R r 0 1 - Ja last", "corrupt tzdb weekday: invalid name");
test_exception("R r 0 1 - Ja lastS", "corrupt tzdb weekday: invalid name");
test_exception("R r 0 1 - Ja S", "corrupt tzdb weekday: invalid name");
test_exception("R r 0 1 - Ja Su", "corrupt tzdb on: expected '>=' or '<='");
- test_exception("R r 0 1 - Ja Su>", "corrupt tzdb: expected character '='");
- test_exception("R r 0 1 - Ja Su<", "corrupt tzdb: expected character '='");
+ test_exception(
+ "R r 0 1 - Ja Su>", std::string{"corrupt tzdb: expected character '=', got '"} + (char)EOF + "' instead");
+ test_exception(
+ "R r 0 1 - Ja Su<", std::string{"corrupt tzdb: expected character '=', got '"} + (char)EOF + "' instead");
test_exception("R r 0 1 - Ja Su>=+", "corrupt tzdb: expected a non-zero digit");
test_exception("R r 0 1 - Ja Su>=0", "corrupt tzdb: expected a non-zero digit");
test_exception("R r 0 1 - Ja Su>=32", "corrupt tzdb day: value too large");
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/version.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/version.pass.cpp
index b4f32a1b6fd785..ca3a890f1fa548 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.db/version.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/version.pass.cpp
@@ -18,9 +18,10 @@
// This is not part of the public tzdb interface.
#include <chrono>
+#include <cstdio>
#include <fstream>
-#include <string>
#include <string_view>
+#include <string>
#include "assert_macros.h"
#include "concat_macros.h"
@@ -60,7 +61,7 @@ static void test_exception(std::string_view input, [[maybe_unused]] std::string_
}
int main(int, const char**) {
- test_exception("", "corrupt tzdb: expected character '#'");
+ test_exception("", std::string{"corrupt tzdb: expected character '#', got '"} + (char)EOF + "' instead");
test_exception("#version", "corrupt tzdb: expected whitespace");
test("#version \t ABCD", "ABCD");
test("#Version \t ABCD", "ABCD");
>From 957fca1703af8a82e6143ce161ebe8bdec80211c Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 8 Jan 2025 10:17:06 -0500
Subject: [PATCH 3/3] WIP: Try using the binary tzdb unconditionally on all
platforms
---
libcxx/src/experimental/tzdb.cpp | 86 ++-----------------
.../time.zone.db/leap_seconds.pass.cpp | 45 +---------
2 files changed, 10 insertions(+), 121 deletions(-)
diff --git a/libcxx/src/experimental/tzdb.cpp b/libcxx/src/experimental/tzdb.cpp
index 509b17e2ea15e4..f9c3684f55bcb9 100644
--- a/libcxx/src/experimental/tzdb.cpp
+++ b/libcxx/src/experimental/tzdb.cpp
@@ -633,7 +633,8 @@ static void __parse_tzdata(tzdb& __db, __tz::__rules_storage_type& __rules, istr
}
// This function parses the leap-seconds "binary file" compiled from the .list file
-// by the zic compiler. That format is what's provided on some platforms like Darwin.
+// by the zic compiler. That format is widely available as it comes by default with
+// the IANA Time Zone Database.
//
// The format looks like:
//
@@ -642,8 +643,7 @@ static void __parse_tzdata(tzdb& __db, __tz::__rules_storage_type& __rules, istr
// Leap 1972 Dec 31 23:59:60 + S
// Leap 1973 Dec 31 23:59:60 + S
//
-inline vector<leap_second> __parse_leap_seconds_binary(istream&& __input) {
- vector<leap_second> __result;
+static void __parse_leap_seconds(vector<leap_second>& __leap_seconds, istream&& __input) {
[&] {
while (true) {
switch (__input.peek()) {
@@ -699,86 +699,12 @@ inline vector<leap_second> __parse_leap_seconds_binary(istream&& __input) {
chrono::__skip_line(__input);
- __result.emplace_back(std::__private_constructor_tag{}, __timestamp, __value);
+ __leap_seconds.emplace_back(std::__private_constructor_tag{}, __timestamp, __value);
}
}();
// Ensure the leap seconds are sorted properly.
- ranges::sort(__result, {}, &leap_second::date);
-
- return __result;
-}
-
-// This function parses leap-seconds.list file as can be found at
-// https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list
-//
-// The format looks like
-//
-// #NTP Time DTAI Day Month Year
-// #
-// 2272060800 10 # 1 Jan 1972
-// 2287785600 11 # 1 Jul 1972
-// 2303683200 12 # 1 Jan 1973
-//
-// Where the timestamps are expressed as a number of seconds since 1 January 1900, 00:00:00.
-inline vector<leap_second> __parse_leap_seconds_list(istream&& __input) {
- // The file stores dates since 1 January 1900, 00:00:00, we want
- // seconds since 1 January 1970.
- constexpr auto __offset = sys_days{1970y / January / 1} - sys_days{1900y / January / 1};
-
- struct __entry {
- sys_seconds __timestamp;
- seconds __value;
- };
- vector<__entry> __entries;
- [&] {
- while (true) {
- switch (__input.peek()) {
- case istream::traits_type::eof():
- return;
-
- case ' ':
- case '\t':
- case '\n':
- __input.get();
- continue;
-
- case '#':
- chrono::__skip_line(__input);
- continue;
- }
-
- sys_seconds __date = sys_seconds{seconds{chrono::__parse_integral(__input, false)}} - __offset;
- chrono::__skip_mandatory_whitespace(__input);
- seconds __value{chrono::__parse_integral(__input, false)};
- chrono::__skip_line(__input);
-
- __entries.emplace_back(__date, __value);
- }
- }();
- // The Standard requires the leap seconds to be sorted. The file
- // leap-seconds.list usually provides them in sorted order, but that is not
- // guaranteed so we ensure it here.
- ranges::sort(__entries, {}, &__entry::__timestamp);
-
- // The database should contain the number of seconds inserted by a leap
- // second (1 or -1). So the difference between the two elements is stored.
- // std::ranges::views::adjacent has not been implemented yet.
- vector<leap_second> __result;
- (void)ranges::adjacent_find(__entries, [&](const __entry& __first, const __entry& __second) {
- __result.emplace_back(std::__private_constructor_tag{}, __second.__timestamp, __second.__value - __first.__value);
- return false;
- });
- return __result;
-}
-
-// Parse leap seconds from the appropriate location based on the platform.
-static void __parse_leap_seconds(vector<leap_second>& __leap_seconds, filesystem::path const& __tzdb_directory) {
-#if defined(__APPLE__)
- __leap_seconds.append_range(chrono::__parse_leap_seconds_binary(ifstream{__tzdb_directory / "leapseconds"}));
-#else
- __leap_seconds.append_range(chrono::__parse_leap_seconds_list(ifstream{__tzdb_directory / "leap-seconds.list"}));
-#endif
+ ranges::sort(__leap_seconds, {}, &leap_second::date);
}
void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
@@ -790,7 +716,7 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
ranges::sort(__tzdb.zones);
ranges::sort(__tzdb.links);
ranges::sort(__rules, {}, [](const auto& p) { return p.first; });
- chrono::__parse_leap_seconds(__tzdb.leap_seconds, __root);
+ chrono::__parse_leap_seconds(__tzdb.leap_seconds, ifstream{__root / "leapseconds"});
}
#ifdef _WIN32
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp
index e05279bfca4f6f..7e8685d1f41069 100644
--- a/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp
@@ -28,20 +28,10 @@
#include "filesystem_test_helper.h"
#include "test_tzdb.h"
-#if defined(__APPLE__)
-# define TEST_USE_BINARY_LEAP_SECONDS
-#else
-# define TEST_USE_LIST_LEAP_SECONDS
-#endif
-
scoped_test_env env;
[[maybe_unused]] const std::filesystem::path dir = env.create_dir("zoneinfo");
const std::filesystem::path tzdata = env.create_file("zoneinfo/tzdata.zi");
-#ifdef TEST_USE_BINARY_LEAP_SECONDS
-const std::filesystem::path leap_seconds = env.create_file("zoneinfo/leapseconds");
-#else
-const std::filesystem::path leap_seconds = env.create_file("zoneinfo/leap-seconds.list");
-#endif
+const std::filesystem::path leap_seconds = env.create_file("zoneinfo/leapseconds");
std::string_view std::chrono::__libcpp_tzdb_directory() {
static std::string result = dir.string();
@@ -75,37 +65,17 @@ static void test_exception(std::string_view input, [[maybe_unused]] std::string_
}
static void test_invalid() {
-#ifdef TEST_USE_BINARY_LEAP_SECONDS
test_exception("0", "corrupt tzdb: expected character 'l' from string 'leap', got '0' instead");
test_exception("Leap x", "corrupt tzdb: expected a digit");
test_exception("Leap 1970 J", "corrupt tzdb month: invalid name");
test_exception("Leap 1970 Jan 1 23:59:60 x", "corrupt tzdb: invalid leap second sign x");
-#else
- test_exception("0", "corrupt tzdb: expected a non-zero digit");
- test_exception("1", "corrupt tzdb: expected whitespace");
- test_exception("1 ", "corrupt tzdb: expected a non-zero digit");
- test_exception("5764607523034234880 2", "corrupt tzdb: integral too large");
-#endif
}
static void test_leap_seconds() {
using namespace std::chrono;
- std::string list_format = R"(
-2303683200 12 # 1 Jan 1973
-2287785600 11 # 1 Jul 1972
-2272060800 10 # 1 Jan 1972
-86400 9 # 2 Jan 1900 Dummy entry to test before 1970
-1 8 # 2 Jan 1900 Dummy entry to test before 1970
-
-# Fictional negative leap second
-2303769600 11 # 2 Jan 1973
-
-# largest accepted value by the parser
-5764607523034234879 12
-)";
-
- std::string binary_format = R"(
+ // Test whether loading also sorts the entries in the proper order.
+ const tzdb& result = parse(R"(
Leap 1973 Jan 1 23:59:60 + S
Leap 1972 Jul 1 23:59:60 + S
Leap 1972 Jan 1 23:59:60 + S
@@ -114,14 +84,7 @@ Leap 1900 Jan 2 00:00:01 + S # 2 Jan 1900 Dummy entry to test before
Leap 1973 Jan 2 23:59:60 - S # Fictional negative leap second
Leap 32767 Jan 1 23:59:60 + S # Largest year accepted by the parser
-)";
-
- // Test whether loading also sorts the entries in the proper order.
-#ifdef TEST_USE_BINARY_LEAP_SECONDS
- const tzdb& result = parse(binary_format);
-#else
- const tzdb& result = parse(list_format);
-#endif
+)");
assert(result.leap_seconds.size() == 6);
More information about the libcxx-commits
mailing list