[libcxx-commits] [libcxx] [libc++][chrono] Adds the sys_info class. (PR #85619)

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sun Apr 7 02:52:06 PDT 2024


================
@@ -27,6 +722,169 @@ _LIBCPP_EXPORTED_FROM_ABI time_zone::~time_zone() = default;
 
 [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI string_view time_zone::__name() const noexcept { return __impl_->__name(); }
 
+[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI sys_info
+time_zone::__get_info(sys_seconds __time) const {
+  optional<sys_info> __result;
+  bool __valid_result = false; // true iff __result.has_value() is true and
+                               // result.begin <= __time < __result.end is true.
+  bool __can_merge                 = false;
+  sys_seconds __continuation_begin = sys_seconds::min();
+  // Iterates over the Zone entry and its continuations. Internally the Zone
+  // entry is split in a Zone information and the first continuation. The last
+  // continuation has no UNTIL field. This means the loop should always find a
+  // continuation.
+  //
+  // For more information on background of zone information please consult the
+  // following information
+  //   [zic manual](https://www.man7.org/linux/man-pages/man8/zic.8.html)
+  //   [tz source info](https://data.iana.org/time-zones/tz-how-to.html)
+  //   On POSIX systems the zdump tool can be useful:
+  //     zdump -v Asia/Hong_Kong
+  //   Gives all transitions in the Hong Kong time zone.
+  //
+  // During iteration the result for the current continuation is returned. If
+  // no continuation is applicable it will return the end time as "error". When
+  // two continuations are contiguous and contain the "same" information these
+  // ranges are merged as one range.
+  // The merging requires to keep results occur before __time, likewise when a
+  // valid result is found the algorithm needs test the next continuation to see
+  // when it can be merged. For example, Africa/Ceuta
+  // Continuations
+  //  0 s WE%sT 1929                   (C1)
+  //  0 - WET 1967                     (C2)
+  //  0 Sp WE%sT 1984 Mar 16           (C3)
+  //
+  // Rules
+  //  R s 1926 1929 - O Sa>=1 24s 0 -  (R1)
+  //
+  //  R Sp 1967 o - Jun 3 12 1 S       (R2)
+  //
+  // The rule R1 is the last rule used in C1. The rule R2 is the first rule in
+  // C3. Since R2 is the first rule this means when a continuation uses this
+  // rule its value prior to R2 will be SAVE 0 LETTERS of the first entry with a
+  // SAVE of 0, in this case WET.
+  // This gives the following changes in the information.
+  //   1928-10-07 00:00:00 C1 R1 becomes active: offset 0 save 0 abbrev WET
+  //   1929-01-01 00:00:00 C2    becomes active: offset 0 save 0 abbrev WET
+  //   1967-01-01 00:00:00 C3    becomes active: offset 0 save 0 abbrev WET
+  //   1967-06-03 12:00:00 C3 R2 becomes active: offset 0 save 1 abbrev WEST
+  //
+  // The first 3 entries are contiguous and contain the same information, this
+  // means the period [1928-10-07 00:00:00, 1967-06-03 12:00:00) should be
+  // returned in one sys_info object.
+
+  const auto& __continuations = __impl_->__continuations();
+  for (auto __it = __continuations.begin(); __it != __continuations.end(); ++__it) {
+    const auto& __continuation   = *__it;
+    __sys_info_result __sys_info = chrono::__get_sys_info(__time, __continuation_begin, __continuation);
----------------
mordante wrote:

This is quite hard to do and actually not needed. The `time_zone` keeps track of its continuations. This class is not really aware of the `tzdb` entry it originates from. This origin information is only needed to extract to rules, which would be a cumbersome to do. (It involves iterating the members under a reader lock to find the offset the `tzdb` in the `tzdb_list`, then return the rules at the same offset in its list.) Instead I changed to code directly keep track of the rules; this is trivial to do. I added a test for this.

https://github.com/llvm/llvm-project/pull/85619


More information about the libcxx-commits mailing list