Skip to content

Commit 1fda177

Browse files
authored
[libc++][chrono] Adds the sys_info class. (#85619)
Adds the sys_info class and time_zone::get_info(). The code still has a few quirks and has not been optimized for performance yet. The returned sys_info is compared against the output of the zdump tool in the test giving confidence the implementation is correct. Implements parts of: - P0355 Extending <chrono> to Calendars and Time Zones Implements: - LWGXXXX The sys_info range should be affected by save
1 parent ee284d2 commit 1fda177

File tree

22 files changed

+2916
-6
lines changed

22 files changed

+2916
-6
lines changed

libcxx/docs/Status/Cxx2cIssues.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@
6363
"`4054 <https://wg21.link/LWG4054>`__","Repeating a ``repeat_view`` should repeat the view","Tokyo March 2024","","","|ranges|"
6464
"","","","","",""
6565
"`3343 <https://wg21.link/LWG3343>`__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Yet Adopted","|Complete|","16.0",""
66+
"XXXX","","The sys_info range should be affected by save","Not Yet Adopted","|Complete|","19.0"
6667
"","","","","",""

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ set(files
291291
__chrono/parser_std_format_spec.h
292292
__chrono/statically_widen.h
293293
__chrono/steady_clock.h
294+
__chrono/sys_info.h
294295
__chrono/system_clock.h
295296
__chrono/time_point.h
296297
__chrono/time_zone.h

libcxx/include/__chrono/sys_info.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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_SYS_INFO_H
13+
#define _LIBCPP___CHRONO_SYS_INFO_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_INCOMPLETE_TZDB)
18+
19+
# include <__chrono/duration.h>
20+
# include <__chrono/system_clock.h>
21+
# include <__chrono/time_point.h>
22+
# include <__config>
23+
# include <string>
24+
25+
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26+
# pragma GCC system_header
27+
# endif
28+
29+
_LIBCPP_BEGIN_NAMESPACE_STD
30+
31+
# if _LIBCPP_STD_VER >= 20
32+
33+
namespace chrono {
34+
35+
struct sys_info {
36+
sys_seconds begin;
37+
sys_seconds end;
38+
seconds offset;
39+
minutes save;
40+
string abbrev;
41+
};
42+
43+
} // namespace chrono
44+
45+
# endif //_LIBCPP_STD_VER >= 20
46+
47+
_LIBCPP_END_NAMESPACE_STD
48+
49+
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
50+
51+
#endif // _LIBCPP___CHRONO_SYS_INFO_H

libcxx/include/__chrono/time_zone.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
// Enable the contents of the header only when libc++ was built with experimental features enabled.
1717
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
1818

19+
# include <__chrono/duration.h>
20+
# include <__chrono/sys_info.h>
21+
# include <__chrono/system_clock.h>
1922
# include <__compare/strong_order.h>
2023
# include <__config>
2124
# include <__memory/unique_ptr.h>
@@ -55,10 +58,18 @@ class _LIBCPP_AVAILABILITY_TZDB time_zone {
5558

5659
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name(); }
5760

61+
template <class _Duration>
62+
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI sys_info get_info(const sys_time<_Duration>& __time) const {
63+
return __get_info(chrono::time_point_cast<seconds>(__time));
64+
}
65+
5866
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI const __impl& __implementation() const noexcept { return *__impl_; }
5967

6068
private:
6169
[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI string_view __name() const noexcept;
70+
71+
[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI sys_info __get_info(sys_seconds __time) const;
72+
6273
unique_ptr<__impl> __impl_;
6374
};
6475

libcxx/include/chrono

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,15 @@ const time_zone* current_zone()
724724
const tzdb& reload_tzdb(); // C++20
725725
string remote_version(); // C++20
726726
727+
// [time.zone.info], information classes
728+
struct sys_info { // C++20
729+
sys_seconds begin;
730+
sys_seconds end;
731+
seconds offset;
732+
minutes save;
733+
string abbrev;
734+
};
735+
727736
// 25.10.5, class time_zone // C++20
728737
enum class choose {earliest, latest};
729738
class time_zone {
@@ -733,6 +742,9 @@ class time_zone {
733742
// unspecified additional constructors
734743
735744
string_view name() const noexcept;
745+
746+
template<class Duration>
747+
sys_info get_info(const sys_time<Duration>& st) const;
736748
};
737749
bool operator==(const time_zone& x, const time_zone& y) noexcept; // C++20
738750
strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; // C++20
@@ -881,6 +893,7 @@ constexpr chrono::year operator ""y(unsigned lo
881893
#include <__chrono/month_weekday.h>
882894
#include <__chrono/monthday.h>
883895
#include <__chrono/steady_clock.h>
896+
#include <__chrono/sys_info.h>
884897
#include <__chrono/system_clock.h>
885898
#include <__chrono/time_point.h>
886899
#include <__chrono/weekday.h>

libcxx/include/libcxx.imp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@
288288
{ include: [ "<__chrono/parser_std_format_spec.h>", "private", "<chrono>", "public" ] },
289289
{ include: [ "<__chrono/statically_widen.h>", "private", "<chrono>", "public" ] },
290290
{ include: [ "<__chrono/steady_clock.h>", "private", "<chrono>", "public" ] },
291+
{ include: [ "<__chrono/sys_info.h>", "private", "<chrono>", "public" ] },
291292
{ include: [ "<__chrono/system_clock.h>", "private", "<chrono>", "public" ] },
292293
{ include: [ "<__chrono/time_point.h>", "private", "<chrono>", "public" ] },
293294
{ include: [ "<__chrono/time_zone.h>", "private", "<chrono>", "public" ] },

libcxx/include/module.modulemap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,9 @@ module std_private_chrono_time_zone [system] {
11671167
module std_private_chrono_time_zone_link [system] {
11681168
header "__chrono/time_zone_link.h"
11691169
}
1170+
module std_private_chrono_sys_info [system] {
1171+
header "__chrono/sys_info.h"
1172+
}
11701173
module std_private_chrono_system_clock [system] {
11711174
header "__chrono/system_clock.h"
11721175
export std_private_chrono_time_point

libcxx/modules/std/chrono.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,12 @@ export namespace std {
212212
// [time.zone.exception], exception classes
213213
using std::chrono::ambiguous_local_time;
214214
using std::chrono::nonexistent_local_time;
215+
# endif // if 0
215216

216217
// [time.zone.info], information classes
217218
using std::chrono::sys_info;
218219

220+
# if 0
219221
// [time.zone.timezone], class time_zone
220222
using std::chrono::choose;
221223
# endif // if 0

libcxx/src/include/tzdb/time_zone_private.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ namespace chrono {
2424

2525
class time_zone::__impl {
2626
public:
27-
explicit _LIBCPP_HIDE_FROM_ABI __impl(string&& __name) : __name_(std::move(__name)) {}
27+
explicit _LIBCPP_HIDE_FROM_ABI __impl(string&& __name, const __tz::__rules_storage_type& __rules_db)
28+
: __name_(std::move(__name)), __rules_db_(__rules_db) {}
2829

2930
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view __name() const noexcept { return __name_; }
3031

@@ -33,12 +34,20 @@ class time_zone::__impl {
3334
return __continuations_;
3435
}
3536

37+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI const __tz::__rules_storage_type& __rules_db() const { return __rules_db_; }
38+
3639
private:
3740
string __name_;
3841
// Note the first line has a name + __continuation, the other lines
3942
// are just __continuations. So there is always at least one item in
4043
// the vector.
4144
vector<__tz::__continuation> __continuations_;
45+
46+
// Continuations often depend on a set of rules. The rules are stored in
47+
// parallel data structurs in tzdb_list. From the time_zone it's not possible
48+
// to find its associated tzdb entry and thus not possible to find its
49+
// associated rules. Therefore a link to the rules in stored in this class.
50+
const __tz::__rules_storage_type& __rules_db_;
4251
};
4352

4453
} // namespace chrono

libcxx/src/include/tzdb/types_private.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,17 @@ namespace chrono::__tz {
3333
// Sun>=8 first Sunday on or after the eighth
3434
// Sun<=25 last Sunday on or before the 25th
3535
struct __constrained_weekday {
36-
/* year_month_day operator()(year __year, month __month);*/ // needed but not implemented
36+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI year_month_day operator()(year __year, month __month) const {
37+
auto __result = static_cast<sys_days>(year_month_day{__year, __month, __day});
38+
weekday __wd{static_cast<sys_days>(__result)};
39+
40+
if (__comparison == __le)
41+
__result -= __wd - __weekday;
42+
else
43+
__result += __weekday - __wd;
44+
45+
return __result;
46+
}
3747

3848
weekday __weekday;
3949
enum __comparison_t { __le, __ge } __comparison;
@@ -85,7 +95,8 @@ struct __continuation {
8595
// used.
8696
// If this field contains - then standard time always
8797
// applies. This is indicated by the monostate.
88-
using __rules_t = variant<monostate, __tz::__save, string, size_t>;
98+
// TODO TZDB Investigate implantation the size_t based caching.
99+
using __rules_t = variant<monostate, __tz::__save, string /*, size_t*/>;
89100

90101
__rules_t __rules;
91102

0 commit comments

Comments
 (0)