Skip to content

Commit

Permalink
[libc++][chrono] Adds the sys_info class. (llvm#85619)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mordante committed Apr 10, 2024
1 parent ee284d2 commit 1fda177
Show file tree
Hide file tree
Showing 22 changed files with 2,916 additions and 6 deletions.
1 change: 1 addition & 0 deletions libcxx/docs/Status/Cxx2cIssues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,5 @@
"`4054 <https://wg21.link/LWG4054>`__","Repeating a ``repeat_view`` should repeat the view","Tokyo March 2024","","","|ranges|"
"","","","","",""
"`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",""
"XXXX","","The sys_info range should be affected by save","Not Yet Adopted","|Complete|","19.0"
"","","","","",""
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ set(files
__chrono/parser_std_format_spec.h
__chrono/statically_widen.h
__chrono/steady_clock.h
__chrono/sys_info.h
__chrono/system_clock.h
__chrono/time_point.h
__chrono/time_zone.h
Expand Down
51 changes: 51 additions & 0 deletions libcxx/include/__chrono/sys_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html

#ifndef _LIBCPP___CHRONO_SYS_INFO_H
#define _LIBCPP___CHRONO_SYS_INFO_H

#include <version>
// Enable the contents of the header only when libc++ was built with experimental features enabled.
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)

# include <__chrono/duration.h>
# include <__chrono/system_clock.h>
# include <__chrono/time_point.h>
# include <__config>
# include <string>

# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
# endif

_LIBCPP_BEGIN_NAMESPACE_STD

# if _LIBCPP_STD_VER >= 20

namespace chrono {

struct sys_info {
sys_seconds begin;
sys_seconds end;
seconds offset;
minutes save;
string abbrev;
};

} // namespace chrono

# endif //_LIBCPP_STD_VER >= 20

_LIBCPP_END_NAMESPACE_STD

#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)

#endif // _LIBCPP___CHRONO_SYS_INFO_H
11 changes: 11 additions & 0 deletions libcxx/include/__chrono/time_zone.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
// Enable the contents of the header only when libc++ was built with experimental features enabled.
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)

# include <__chrono/duration.h>
# include <__chrono/sys_info.h>
# include <__chrono/system_clock.h>
# include <__compare/strong_order.h>
# include <__config>
# include <__memory/unique_ptr.h>
Expand Down Expand Up @@ -55,10 +58,18 @@ class _LIBCPP_AVAILABILITY_TZDB time_zone {

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

template <class _Duration>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI sys_info get_info(const sys_time<_Duration>& __time) const {
return __get_info(chrono::time_point_cast<seconds>(__time));
}

[[nodiscard]] _LIBCPP_HIDE_FROM_ABI const __impl& __implementation() const noexcept { return *__impl_; }

private:
[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI string_view __name() const noexcept;

[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI sys_info __get_info(sys_seconds __time) const;

unique_ptr<__impl> __impl_;
};

Expand Down
13 changes: 13 additions & 0 deletions libcxx/include/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,15 @@ const time_zone* current_zone()
const tzdb& reload_tzdb(); // C++20
string remote_version(); // C++20
// [time.zone.info], information classes
struct sys_info { // C++20
sys_seconds begin;
sys_seconds end;
seconds offset;
minutes save;
string abbrev;
};
// 25.10.5, class time_zone // C++20
enum class choose {earliest, latest};
class time_zone {
Expand All @@ -733,6 +742,9 @@ class time_zone {
// unspecified additional constructors
string_view name() const noexcept;
template<class Duration>
sys_info get_info(const sys_time<Duration>& st) const;
};
bool operator==(const time_zone& x, const time_zone& y) noexcept; // C++20
strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; // C++20
Expand Down Expand Up @@ -881,6 +893,7 @@ constexpr chrono::year operator ""y(unsigned lo
#include <__chrono/month_weekday.h>
#include <__chrono/monthday.h>
#include <__chrono/steady_clock.h>
#include <__chrono/sys_info.h>
#include <__chrono/system_clock.h>
#include <__chrono/time_point.h>
#include <__chrono/weekday.h>
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/libcxx.imp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@
{ include: [ "<__chrono/parser_std_format_spec.h>", "private", "<chrono>", "public" ] },
{ include: [ "<__chrono/statically_widen.h>", "private", "<chrono>", "public" ] },
{ include: [ "<__chrono/steady_clock.h>", "private", "<chrono>", "public" ] },
{ include: [ "<__chrono/sys_info.h>", "private", "<chrono>", "public" ] },
{ include: [ "<__chrono/system_clock.h>", "private", "<chrono>", "public" ] },
{ include: [ "<__chrono/time_point.h>", "private", "<chrono>", "public" ] },
{ include: [ "<__chrono/time_zone.h>", "private", "<chrono>", "public" ] },
Expand Down
3 changes: 3 additions & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,9 @@ module std_private_chrono_time_zone [system] {
module std_private_chrono_time_zone_link [system] {
header "__chrono/time_zone_link.h"
}
module std_private_chrono_sys_info [system] {
header "__chrono/sys_info.h"
}
module std_private_chrono_system_clock [system] {
header "__chrono/system_clock.h"
export std_private_chrono_time_point
Expand Down
2 changes: 2 additions & 0 deletions libcxx/modules/std/chrono.inc
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,12 @@ export namespace std {
// [time.zone.exception], exception classes
using std::chrono::ambiguous_local_time;
using std::chrono::nonexistent_local_time;
# endif // if 0

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

# if 0
// [time.zone.timezone], class time_zone
using std::chrono::choose;
# endif // if 0
Expand Down
11 changes: 10 additions & 1 deletion libcxx/src/include/tzdb/time_zone_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ namespace chrono {

class time_zone::__impl {
public:
explicit _LIBCPP_HIDE_FROM_ABI __impl(string&& __name) : __name_(std::move(__name)) {}
explicit _LIBCPP_HIDE_FROM_ABI __impl(string&& __name, const __tz::__rules_storage_type& __rules_db)
: __name_(std::move(__name)), __rules_db_(__rules_db) {}

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

Expand All @@ -33,12 +34,20 @@ class time_zone::__impl {
return __continuations_;
}

[[nodiscard]] _LIBCPP_HIDE_FROM_ABI const __tz::__rules_storage_type& __rules_db() const { return __rules_db_; }

private:
string __name_;
// Note the first line has a name + __continuation, the other lines
// are just __continuations. So there is always at least one item in
// the vector.
vector<__tz::__continuation> __continuations_;

// Continuations often depend on a set of rules. The rules are stored in
// parallel data structurs in tzdb_list. From the time_zone it's not possible
// to find its associated tzdb entry and thus not possible to find its
// associated rules. Therefore a link to the rules in stored in this class.
const __tz::__rules_storage_type& __rules_db_;
};

} // namespace chrono
Expand Down
15 changes: 13 additions & 2 deletions libcxx/src/include/tzdb/types_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,17 @@ namespace chrono::__tz {
// Sun>=8 first Sunday on or after the eighth
// Sun<=25 last Sunday on or before the 25th
struct __constrained_weekday {
/* year_month_day operator()(year __year, month __month);*/ // needed but not implemented
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI year_month_day operator()(year __year, month __month) const {
auto __result = static_cast<sys_days>(year_month_day{__year, __month, __day});
weekday __wd{static_cast<sys_days>(__result)};

if (__comparison == __le)
__result -= __wd - __weekday;
else
__result += __weekday - __wd;

return __result;
}

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

__rules_t __rules;

Expand Down
Loading

0 comments on commit 1fda177

Please sign in to comment.