[libcxx-commits] [libcxx] [libc++][chrono] Adds the sys_info class. (PR #85619)
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Apr 5 10:19:17 PDT 2024
================
@@ -8,14 +8,709 @@
// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
+// TODO TZDB look at optimizations
+//
+// The current algorithm is correct but not efficient. For example, in a named
+// rule based continuation finding the next rule does quite a bit of work,
+// returns the next rule and "forgets" its state. This could be better.
+//
+// It would be possible to cache lookups. If a time for a zone is calculated its
+// sys_info could be kept and the next lookup could test whether the time is in
+// a "known" sys_info. The wording in the Standard hints at this slowness by
+// "suggesting" this could be implemented at the user's side.
+
+// TODO TZDB look at removing quirks
+//
+// The code has some special rules to adjust the timing at the continuation
+// switches. This works correctly, but some of the places feel odd. It would be
+// good to investigate this further and see whether all quirks are needed or
+// that there are better fixes.
+//
+// These quirks often use a 12h interval; this is the scan interval of zdump,
+// which implies there are no sys_info objects with a duration of less than 12h.
+
+#include <algorithm>
#include <chrono>
+#include <expected>
+#include <map>
+#include <ranges>
#include "include/tzdb/time_zone_private.h"
+#include "include/tzdb/tzdb_list_private.h"
+
+// TODO TZDB remove debug printing
+#ifdef PRINT
+# include <print>
+#endif
_LIBCPP_BEGIN_NAMESPACE_STD
+#ifdef PRINT
+template <>
+struct formatter<chrono::sys_info, char> {
+ template <class ParseContext>
+ constexpr typename ParseContext::iterator parse(ParseContext& ctx) {
+ return ctx.begin();
+ }
+
+ template <class FormatContext>
+ typename FormatContext::iterator format(const chrono::sys_info& info, FormatContext& ctx) const {
+ return std::format_to(
+ ctx.out(), "[{}, {}) {:%Q%q} {:%Q%q} {}", info.begin, info.end, info.offset, info.save, info.abbrev);
+ }
+};
+#endif
+
namespace chrono {
+//===----------------------------------------------------------------------===//
+// Details
+//===----------------------------------------------------------------------===//
+
+struct __sys_info {
+ sys_info __info;
+ bool __can_merge; // Can the returned sys_info object be merged with
+};
+
+// Return type for helper function to get a sys_info.
+// - The expected result returns the "best" sys_info object. This object can be
+// before the requested time. Sometimes sys_info objects from different
+// continuations share their offset, save, and abbrev and these objects are
+// merged to one sys_info object. The __can_merge flag determines whether the
+// current result can be merged with the next result.
+// - The unexpected result means no sys_info object was found and the time is
+// the time to be used for the next search iteration.
+using __sys_info_result = expected<__sys_info, sys_seconds>;
+
+template <ranges::forward_range _Range,
+ class _Type,
+ class _Proj = identity,
+ indirect_strict_weak_order<const _Type*, projected<ranges::iterator_t<_Range>, _Proj>> _Comp = ranges::less>
+[[nodiscard]] static ranges::borrowed_iterator_t<_Range>
+__binary_find(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) {
+ auto __end = ranges::end(__r);
+ auto __ret = ranges::lower_bound(ranges::begin(__r), __end, __value, __comp, __proj);
+ if (__ret == __end)
+ return __end;
+
+ // When the value does not match the predicate it's equal and a valid result
+ // was found.
+ return !std::invoke(__comp, __value, std::invoke(__proj, *__ret)) ? __ret : __end;
+}
+
+// Format based on https://data.iana.org/time-zones/tz-how-to.html
+//
+// 1 a time zone abbreviation that is a string of three or more characters that
+// are either ASCII alphanumerics, "+", or "-"
+// 2 the string "%z", in which case the "%z" will be replaced by a numeric time
+// zone abbreviation
+// 3 a pair of time zone abbreviations separated by a slash ('/'), in which
+// case the first string is the abbreviation for the standard time name and
+// the second string is the abbreviation for the daylight saving time name
+// 4 a string containing "%s", in which case the "%s" will be replaced by the
+// text in the appropriate Rule's LETTER column, and the resulting string
+// should be a time zone abbreviation
+//
+// Accepting invalid formats that can be processed in a sensible way would better
----------------
mordante wrote:
Actually I'll be less strict again... America/Barbados has a two letter abbreviation of AT. I'll validate the abbreviation is not empty instead.
https://github.com/llvm/llvm-project/pull/85619
More information about the libcxx-commits
mailing list