Skip to content

Commit 50da5f2

Browse files
committed
[libc++][TZDB] Implements zoned_traits.
Implements parts of: - P0355 Extending chrono to Calendars and Time Zones
1 parent da03175 commit 50da5f2

File tree

9 files changed

+182
-2
lines changed

9 files changed

+182
-2
lines changed

libcxx/include/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ set(files
277277
__chrono/year_month.h
278278
__chrono/year_month_day.h
279279
__chrono/year_month_weekday.h
280+
__chrono/zoned_time.h
280281
__compare/common_comparison_category.h
281282
__compare/compare_partial_order_fallback.h
282283
__compare/compare_strong_order_fallback.h

libcxx/include/__chrono/zoned_time.h

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
11+
12+
#ifndef _LIBCPP___CHRONO_ZONED_TIME_H
13+
#define _LIBCPP___CHRONO_ZONED_TIME_H
14+
15+
#include <version>
16+
// Enable the contents of the header only when libc++ was built with experimental features enabled.
17+
#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)
18+
19+
# include <__chrono/time_zone.h>
20+
# include <__chrono/tzdb_list.h>
21+
# include <__config>
22+
# include <__fwd/string_view.h>
23+
24+
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25+
# pragma GCC system_header
26+
# endif
27+
28+
_LIBCPP_BEGIN_NAMESPACE_STD
29+
30+
# if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) && \
31+
!defined(_LIBCPP_HAS_NO_LOCALIZATION)
32+
33+
namespace chrono {
34+
35+
template <class>
36+
struct zoned_traits {};
37+
38+
template <>
39+
struct zoned_traits<const time_zone*> {
40+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static const time_zone* default_zone() { return chrono::locate_zone("UTC"); }
41+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static const time_zone* locate_zone(string_view __name) {
42+
return chrono::locate_zone(__name);
43+
}
44+
};
45+
46+
} // namespace chrono
47+
48+
# endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM)
49+
// && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
50+
51+
_LIBCPP_END_NAMESPACE_STD
52+
53+
#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)
54+
55+
#endif // _LIBCPP___CHRONO_ZONED_TIME_H

libcxx/include/chrono

+4
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,9 @@ class time_zone {
786786
bool operator==(const time_zone& x, const time_zone& y) noexcept; // C++20
787787
strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; // C++20
788788
789+
// [time.zone.zonedtraits], class template zoned_traits
790+
template<class T> struct zoned_traits; // C++20
791+
789792
// [time.zone.leap], leap second support
790793
class leap_second { // C++20
791794
public:
@@ -959,6 +962,7 @@ constexpr chrono::year operator ""y(unsigned lo
959962
# include <__chrono/time_zone_link.h>
960963
# include <__chrono/tzdb.h>
961964
# include <__chrono/tzdb_list.h>
965+
# include <__chrono/zoned_time.h>
962966
# endif
963967

964968
#endif

libcxx/include/module.modulemap

+1
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,7 @@ module std_private_chrono_year [system] { header "__chrono/yea
11591159
module std_private_chrono_year_month [system] { header "__chrono/year_month.h" }
11601160
module std_private_chrono_year_month_day [system] { header "__chrono/year_month_day.h" }
11611161
module std_private_chrono_year_month_weekday [system] { header "__chrono/year_month_weekday.h" }
1162+
module std_private_chrono_zoned_time [system] { header "__chrono/zoned_time.h" }
11621163

11631164
module std_private_compare_common_comparison_category [system] { header "__compare/common_comparison_category.h" }
11641165
module std_private_compare_compare_partial_order_fallback [system] { header "__compare/compare_partial_order_fallback.h" }

libcxx/modules/std/chrono.inc

+1-2
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,10 @@ export namespace std {
227227
using std::chrono::choose;
228228
using std::chrono::time_zone;
229229

230-
# if 0
231-
232230
// [time.zone.zonedtraits], class template zoned_traits
233231
using std::chrono::zoned_traits;
234232

233+
# if 0
235234
// [time.zone.zonedtime], class template zoned_time
236235
using std::chrono::zoned_time;
237236

libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,10 @@ void test() {
7272
leap.date(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
7373
leap.value(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
7474
}
75+
76+
{
77+
using t = std::chrono::zoned_traits<const std::chrono::time_zone*>;
78+
t::default_zone(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
79+
t::locate_zone(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
80+
}
7581
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
11+
12+
// XFAIL: libcpp-has-no-experimental-tzdb
13+
// XFAIL: availability-tzdb-missing
14+
15+
// <chrono>
16+
17+
// template<> struct zoned_traits<const time_zone*>;
18+
19+
// static const time_zone* default_zone();
20+
21+
#include <chrono>
22+
#include <cassert>
23+
24+
int main(int, char**) {
25+
std::same_as<const std::chrono::time_zone*> decltype(auto) tz =
26+
std::chrono::zoned_traits<const std::chrono::time_zone*>::default_zone();
27+
assert(tz);
28+
29+
// The time zone "UTC" can be a link, this means tz->name() can be something
30+
// differently. For example, "Etc/UTC". Instead validate whether same time
31+
// zone is returned by comparing the addresses.
32+
const std::chrono::time_zone* expected = std::chrono::locate_zone("UTC");
33+
assert(tz == expected);
34+
35+
return 0;
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
11+
12+
// XFAIL: libcpp-has-no-experimental-tzdb
13+
// XFAIL: availability-tzdb-missing
14+
15+
// <chrono>
16+
17+
// template<> struct zoned_traits<const time_zone*>;
18+
19+
// static const time_zone* locate_zone(string_view name);
20+
21+
#include <chrono>
22+
#include <cassert>
23+
#include <concepts>
24+
25+
#include "assert_macros.h"
26+
27+
static void test(std::string_view name) {
28+
std::same_as<const std::chrono::time_zone*> decltype(auto) tz =
29+
std::chrono::zoned_traits<const std::chrono::time_zone*>::locate_zone(name);
30+
31+
const std::chrono::time_zone* expected = std::chrono::locate_zone(name);
32+
assert(tz == expected);
33+
}
34+
35+
int main(int, char**) {
36+
test("UTC");
37+
test("Europe/Berlin");
38+
test("Asia/Hong_Kong");
39+
40+
TEST_THROWS_TYPE(std::runtime_error,
41+
TEST_IGNORE_NODISCARD std::chrono::zoned_traits<const std::chrono::time_zone*>::locate_zone(
42+
"there_is_no_time_zone_with_this_name"));
43+
44+
return 0;
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
11+
12+
// XFAIL: libcpp-has-no-experimental-tzdb
13+
// XFAIL: availability-tzdb-missing
14+
15+
// <chrono>
16+
17+
// template<class T> struct zoned_traits {};
18+
//
19+
// A specialization for const time_zone* is provided by the implementation:
20+
// template<> struct zoned_traits<const time_zone*> { ... }
21+
22+
#include <chrono>
23+
#include <type_traits>
24+
25+
// This test test whether non-specialized versions exhibit the expected
26+
// behavior. (Note these specializations are not really useful.)
27+
static_assert(std::is_trivial_v<std::chrono::zoned_traits<int>>);
28+
static_assert(std::is_trivial_v<std::chrono::zoned_traits<float>>);
29+
static_assert(std::is_trivial_v<std::chrono::zoned_traits<void*>>);
30+
31+
struct foo {};
32+
static_assert(std::is_empty_v<std::chrono::zoned_traits<foo>>);
33+
static_assert(std::is_trivial_v<std::chrono::zoned_traits<foo>>);

0 commit comments

Comments
 (0)