mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 22:06:36 +00:00
[libc++][chrono] Completes the tzdb class. (#82157)
It adds the missing member functions of the tzdb class and adds the free functions that use these member functions. Implements parts of: - P0355 Extending <chrono> to Calendars and Time Zones
This commit is contained in:
parent
338ecfbac3
commit
4167fec407
@ -16,6 +16,7 @@
|
||||
// Enable the contents of the header only when libc++ was built with experimental features enabled.
|
||||
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
|
||||
|
||||
# include <__algorithm/ranges_lower_bound.h>
|
||||
# include <__chrono/leap_second.h>
|
||||
# include <__chrono/time_zone.h>
|
||||
# include <__chrono/time_zone_link.h>
|
||||
@ -43,6 +44,40 @@ struct tzdb {
|
||||
vector<time_zone_link> links;
|
||||
|
||||
vector<leap_second> leap_seconds;
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI const time_zone* __locate_zone(string_view __name) const {
|
||||
if (const time_zone* __result = __find_in_zone(__name))
|
||||
return __result;
|
||||
|
||||
if (auto __it = ranges::lower_bound(links, __name, {}, &time_zone_link::name);
|
||||
__it != links.end() && __it->name() == __name)
|
||||
if (const time_zone* __result = __find_in_zone(__it->target()))
|
||||
return __result;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const time_zone* locate_zone(string_view __name) const {
|
||||
if (const time_zone* __result = __locate_zone(__name))
|
||||
return __result;
|
||||
|
||||
std::__throw_runtime_error("tzdb: requested time zone not found");
|
||||
}
|
||||
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI const time_zone* current_zone() const {
|
||||
return __current_zone();
|
||||
}
|
||||
|
||||
private:
|
||||
_LIBCPP_HIDE_FROM_ABI const time_zone* __find_in_zone(string_view __name) const noexcept {
|
||||
if (auto __it = ranges::lower_bound(zones, __name, {}, &time_zone::name);
|
||||
__it != zones.end() && __it->name() == __name)
|
||||
return std::addressof(*__it);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const time_zone* __current_zone() const;
|
||||
};
|
||||
|
||||
} // namespace chrono
|
||||
|
@ -17,6 +17,7 @@
|
||||
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
|
||||
|
||||
# include <__availability>
|
||||
# include <__chrono/time_zone.h>
|
||||
# include <__chrono/tzdb.h>
|
||||
# include <__config>
|
||||
# include <__fwd/string.h>
|
||||
@ -84,6 +85,15 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline con
|
||||
return get_tzdb_list().front();
|
||||
}
|
||||
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone*
|
||||
locate_zone(string_view __name) {
|
||||
return get_tzdb().locate_zone(__name);
|
||||
}
|
||||
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* current_zone() {
|
||||
return get_tzdb().current_zone();
|
||||
}
|
||||
|
||||
_LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const tzdb& reload_tzdb();
|
||||
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string remote_version();
|
||||
|
@ -689,6 +689,9 @@ struct tzdb {
|
||||
vector<time_zone> zones;
|
||||
vector<time_zone_link> links;
|
||||
vector<leap_second> leap_seconds;
|
||||
|
||||
const time_zone* locate_zone(string_view tz_name) const;
|
||||
const time_zone* current_zone() const;
|
||||
};
|
||||
|
||||
class tzdb_list { // C++20
|
||||
@ -714,6 +717,8 @@ public:
|
||||
// [time.zone.db.access], time zone database access
|
||||
const tzdb& get_tzdb(); // C++20
|
||||
tzdb_list& get_tzdb_list(); // C++20
|
||||
const time_zone* locate_zone(string_view tz_name); // C++20
|
||||
const time_zone* current_zone() // C++20
|
||||
|
||||
// [time.zone.db.remote], remote time zone database support
|
||||
const tzdb& reload_tzdb(); // C++20
|
||||
|
@ -199,10 +199,10 @@ export namespace std {
|
||||
using std::chrono::tzdb_list;
|
||||
|
||||
// [time.zone.db.access], time zone database access
|
||||
// using std::chrono::current_zone;
|
||||
using std::chrono::current_zone;
|
||||
using std::chrono::get_tzdb;
|
||||
using std::chrono::get_tzdb_list;
|
||||
// using std::chrono::locate_zone;
|
||||
using std::chrono::locate_zone;
|
||||
|
||||
// [time.zone.db.remote], remote time zone database support
|
||||
using std::chrono::reload_tzdb;
|
||||
|
@ -675,6 +675,57 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
|
||||
std::ranges::sort(__tzdb.leap_seconds);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
[[nodiscard]] static const time_zone* __current_zone_windows(const tzdb& tzdb) {
|
||||
// TODO TZDB Implement this on Windows.
|
||||
std::__throw_runtime_error("unknown time zone");
|
||||
}
|
||||
#else // ifdef _WIN32
|
||||
[[nodiscard]] static const time_zone* __current_zone_posix(const tzdb& tzdb) {
|
||||
// On POSIX systems there are several ways to configure the time zone.
|
||||
// In order of priority they are:
|
||||
// - TZ environment variable
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08
|
||||
// The documentation is unclear whether or not it's allowed to
|
||||
// change time zone information. For example the TZ string
|
||||
// MST7MDT
|
||||
// this is an entry in tzdata.zi. The value
|
||||
// MST
|
||||
// is also an entry. Is it allowed to use the following?
|
||||
// MST-3
|
||||
// Even when this is valid there is no time_zone record in the
|
||||
// database. Since the library would need to return a valid pointer,
|
||||
// this means the library needs to allocate and leak a pointer.
|
||||
//
|
||||
// - The time zone name is the target of the symlink /etc/localtime
|
||||
// relative to /usr/share/zoneinfo/
|
||||
|
||||
// The algorithm is like this:
|
||||
// - If the environment variable TZ is set and points to a valid
|
||||
// record use this value.
|
||||
// - Else use the name based on the `/etc/localtime` symlink.
|
||||
|
||||
if (const char* __tz = getenv("TZ"))
|
||||
if (const time_zone* __result = tzdb.__locate_zone(__tz))
|
||||
return __result;
|
||||
|
||||
filesystem::path __path = "/etc/localtime";
|
||||
if (!std::filesystem::exists(__path))
|
||||
std::__throw_runtime_error("tzdb: the symlink '/etc/localtime' does not exist");
|
||||
|
||||
if (!std::filesystem::is_symlink(__path))
|
||||
std::__throw_runtime_error("tzdb: the path '/etc/localtime' is not a symlink");
|
||||
|
||||
filesystem::path __tz = filesystem::read_symlink(__path);
|
||||
string __name = filesystem::relative(__tz, "/usr/share/zoneinfo/");
|
||||
|
||||
if (const time_zone* __result = tzdb.__locate_zone(__name))
|
||||
return __result;
|
||||
|
||||
std::__throw_runtime_error(("tzdb: the time zone '" + __name + "' is not found in the database").c_str());
|
||||
}
|
||||
#endif // ifdef _WIN32
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Public API
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -684,6 +735,14 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_l
|
||||
return __result;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const time_zone* tzdb::__current_zone() const {
|
||||
#ifdef _WIN32
|
||||
return chrono::__current_zone_windows(*this);
|
||||
#else
|
||||
return chrono::__current_zone_posix(*this);
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const tzdb& reload_tzdb() {
|
||||
if (chrono::remote_version() == chrono::get_tzdb().version)
|
||||
return chrono::get_tzdb();
|
||||
|
@ -38,8 +38,16 @@ void test() {
|
||||
|
||||
std::chrono::get_tzdb_list();
|
||||
std::chrono::get_tzdb();
|
||||
std::chrono::locate_zone("name");
|
||||
std::chrono::current_zone();
|
||||
std::chrono::remote_version();
|
||||
|
||||
{
|
||||
const std::chrono::tzdb& t = list.front();
|
||||
t.locate_zone("name");
|
||||
t.current_zone();
|
||||
}
|
||||
|
||||
{
|
||||
tz.name();
|
||||
operator==(tz, tz);
|
||||
|
@ -33,9 +33,17 @@ void test() {
|
||||
list.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
list.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
|
||||
{
|
||||
const std::chrono::tzdb& t = list.front();
|
||||
t.locate_zone("name"); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
t.current_zone(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
}
|
||||
|
||||
namespace crno = std::chrono;
|
||||
crno::get_tzdb_list(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
crno::get_tzdb(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
crno::locate_zone("n"); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
crno::current_zone(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
crno::remote_version(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
|
||||
{
|
||||
|
@ -0,0 +1,84 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// struct tzdb
|
||||
|
||||
// const time_zone* locate_zone(string_view tz_name) const;
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <string_view>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "assert_macros.h"
|
||||
#include "concat_macros.h"
|
||||
#include "filesystem_test_helper.h"
|
||||
#include "test_tzdb.h"
|
||||
|
||||
scoped_test_env env;
|
||||
[[maybe_unused]] const std::filesystem::path dir = env.create_dir("zoneinfo");
|
||||
const std::filesystem::path file = env.create_file("zoneinfo/tzdata.zi");
|
||||
|
||||
std::string_view std::chrono::__libcpp_tzdb_directory() {
|
||||
static std::string result = dir.string();
|
||||
return result;
|
||||
}
|
||||
|
||||
void write(std::string_view input) {
|
||||
static int version = 0;
|
||||
|
||||
std::ofstream f{file};
|
||||
f << "# version " << version++ << '\n';
|
||||
f.write(input.data(), input.size());
|
||||
}
|
||||
|
||||
static const std::chrono::tzdb& parse(std::string_view input) {
|
||||
write(input);
|
||||
return std::chrono::reload_tzdb();
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
const std::chrono::tzdb& tzdb = parse(
|
||||
R"(
|
||||
Z zone 0 r f
|
||||
L zone link
|
||||
L link link_to_link
|
||||
)");
|
||||
|
||||
{
|
||||
const std::chrono::time_zone* tz = tzdb.locate_zone("zone");
|
||||
assert(tz);
|
||||
assert(tz->name() == "zone");
|
||||
}
|
||||
{
|
||||
const std::chrono::time_zone* tz = tzdb.locate_zone("link");
|
||||
assert(tz);
|
||||
assert(tz->name() == "zone");
|
||||
}
|
||||
|
||||
TEST_VALIDATE_EXCEPTION(
|
||||
std::runtime_error,
|
||||
[&]([[maybe_unused]] const std::runtime_error& e) {
|
||||
std::string_view what{"tzdb: requested time zone not found"};
|
||||
TEST_LIBCPP_REQUIRE(
|
||||
e.what() == what,
|
||||
TEST_WRITE_CONCATENATED("\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));
|
||||
},
|
||||
TEST_IGNORE_NODISCARD tzdb.locate_zone("link_to_link"));
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// const time_zone* current_zone();
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <string_view>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "assert_macros.h"
|
||||
#include "concat_macros.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
static void set_tz(std::string zone) {
|
||||
// Note Windows does not have setenv, only putenv
|
||||
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/putenv-s-wputenv-s?view=msvc-170
|
||||
// Unlike POSIX it does not mention the string of putenv becomes part
|
||||
// of the environment.
|
||||
|
||||
int status = _putenv_s("TZ", zone.c_str(), 1);
|
||||
assert(status == 0);
|
||||
}
|
||||
|
||||
#else
|
||||
static void set_tz(const std::string& zone) {
|
||||
int status = setenv("TZ", zone.c_str(), 1);
|
||||
assert(status == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void test_zone(const std::string& zone) {
|
||||
set_tz(zone);
|
||||
const std::chrono::time_zone* tz = std::chrono::current_zone();
|
||||
assert(tz);
|
||||
assert(tz->name() == zone);
|
||||
}
|
||||
|
||||
static void test_link(const std::string& link, std::string_view zone) {
|
||||
set_tz(link);
|
||||
const std::chrono::time_zone* tz = std::chrono::current_zone();
|
||||
assert(tz);
|
||||
assert(tz->name() == zone);
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
const std::chrono::time_zone* tz = std::chrono::current_zone();
|
||||
// Returns a valid time zone, the value depends on the OS settings.
|
||||
assert(tz);
|
||||
// setting the environment to an invalid value returns the value of
|
||||
// the OS setting.
|
||||
set_tz("This is not a time zone");
|
||||
assert(tz == std::chrono::current_zone());
|
||||
|
||||
const std::chrono::tzdb& db = std::chrono::get_tzdb();
|
||||
for (const auto& zone : db.zones)
|
||||
test_zone(std::string{zone.name()});
|
||||
|
||||
for (const auto& link : db.links)
|
||||
test_link(std::string{link.name()}, link.target());
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// const time_zone* locate_zone(string_view tz_name);
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <string_view>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "assert_macros.h"
|
||||
#include "concat_macros.h"
|
||||
|
||||
static void test_zone(std::string_view zone) {
|
||||
const std::chrono::time_zone* tz = std::chrono::locate_zone(zone);
|
||||
assert(tz);
|
||||
assert(tz->name() == zone);
|
||||
}
|
||||
|
||||
static void test_link(std::string_view link, std::string_view zone) {
|
||||
const std::chrono::time_zone* tz = std::chrono::locate_zone(link);
|
||||
assert(tz);
|
||||
assert(tz->name() == zone);
|
||||
}
|
||||
|
||||
static void test_exception([[maybe_unused]] std::string_view zone) {
|
||||
TEST_VALIDATE_EXCEPTION(
|
||||
std::runtime_error,
|
||||
[&]([[maybe_unused]] const std::runtime_error& e) {
|
||||
std::string_view what{"tzdb: requested time zone not found"};
|
||||
TEST_LIBCPP_REQUIRE(
|
||||
e.what() == what,
|
||||
TEST_WRITE_CONCATENATED("\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));
|
||||
},
|
||||
TEST_IGNORE_NODISCARD std::chrono::locate_zone(zone));
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
const std::chrono::tzdb& db = std::chrono::get_tzdb();
|
||||
for (const auto& zone : db.zones)
|
||||
test_zone(zone.name());
|
||||
|
||||
for (const auto& link : db.links)
|
||||
test_link(link.name(), link.target());
|
||||
|
||||
test_exception("This is not a time zone");
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// struct tzdb
|
||||
|
||||
// const time_zone* current_zone() const;
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <string_view>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "assert_macros.h"
|
||||
#include "concat_macros.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
static void set_tz(std::string zone) {
|
||||
// Note Windows does not have setenv, only putenv
|
||||
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/putenv-s-wputenv-s?view=msvc-170
|
||||
// Unlike POSIX it does not mention the string of putenv becomes part
|
||||
// of the environment.
|
||||
|
||||
int status = _putenv_s("TZ", zone.c_str(), 1);
|
||||
assert(status == 0);
|
||||
}
|
||||
|
||||
#else
|
||||
static void set_tz(const std::string& zone) {
|
||||
int status = setenv("TZ", zone.c_str(), 1);
|
||||
assert(status == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void test_zone(const std::string& zone) {
|
||||
set_tz(zone);
|
||||
const std::chrono::time_zone* tz = std::chrono::get_tzdb().current_zone();
|
||||
assert(tz);
|
||||
assert(tz->name() == zone);
|
||||
}
|
||||
|
||||
static void test_link(const std::string& link, std::string_view zone) {
|
||||
set_tz(link);
|
||||
const std::chrono::time_zone* tz = std::chrono::get_tzdb().current_zone();
|
||||
assert(tz);
|
||||
assert(tz->name() == zone);
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
const std::chrono::time_zone* tz = std::chrono::get_tzdb().current_zone();
|
||||
// Returns a valid time zone, the value depends on the OS settings.
|
||||
assert(tz);
|
||||
// setting the environment to an invalid value returns the value of
|
||||
// the OS setting.
|
||||
set_tz("This is not a time zone");
|
||||
assert(tz == std::chrono::get_tzdb().current_zone());
|
||||
|
||||
const std::chrono::tzdb& db = std::chrono::get_tzdb();
|
||||
for (const auto& zone : db.zones)
|
||||
test_zone(std::string{zone.name()});
|
||||
|
||||
for (const auto& link : db.links)
|
||||
test_link(std::string{link.name()}, link.target());
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// struct tzdb
|
||||
|
||||
// const time_zone* locate_zone(string_view tz_name) const;
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <string_view>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "assert_macros.h"
|
||||
#include "concat_macros.h"
|
||||
|
||||
static void test_zone(std::string_view zone) {
|
||||
const std::chrono::time_zone* tz = std::chrono::get_tzdb().locate_zone(zone);
|
||||
assert(tz);
|
||||
assert(tz->name() == zone);
|
||||
}
|
||||
|
||||
static void test_link(std::string_view link, std::string_view zone) {
|
||||
const std::chrono::time_zone* tz = std::chrono::get_tzdb().locate_zone(link);
|
||||
assert(tz);
|
||||
assert(tz->name() == zone);
|
||||
}
|
||||
|
||||
static void test_exception([[maybe_unused]] std::string_view zone) {
|
||||
TEST_VALIDATE_EXCEPTION(
|
||||
std::runtime_error,
|
||||
[&]([[maybe_unused]] const std::runtime_error& e) {
|
||||
std::string_view what{"tzdb: requested time zone not found"};
|
||||
TEST_LIBCPP_REQUIRE(
|
||||
e.what() == what,
|
||||
TEST_WRITE_CONCATENATED("\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));
|
||||
},
|
||||
TEST_IGNORE_NODISCARD std::chrono::get_tzdb().locate_zone(zone));
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
const std::chrono::tzdb& db = std::chrono::get_tzdb();
|
||||
for (const auto& zone : db.zones)
|
||||
test_zone(zone.name());
|
||||
|
||||
for (const auto& link : db.links)
|
||||
test_link(link.name(), link.target());
|
||||
|
||||
test_exception("This is not a time zone");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user