@@ -675,6 +675,57 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
675675 std::ranges::sort (__tzdb.leap_seconds );
676676}
677677
678+ #ifdef _WIN32
679+ [[nodiscard]] static const time_zone* __current_zone_windows (const tzdb& tzdb) {
680+ // TODO TZDB Implement this on Windows.
681+ std::__throw_runtime_error (" unknown time zone" );
682+ }
683+ #else // ifdef _WIN32
684+ [[nodiscard]] static const time_zone* __current_zone_posix (const tzdb& tzdb) {
685+ // On POSIX systems there are several ways to configure the time zone.
686+ // In order of priority they are:
687+ // - TZ environment variable
688+ // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08
689+ // The documentation is unclear whether or not it's allowed to
690+ // change time zone information. For example the TZ string
691+ // MST7MDT
692+ // this is an entry in tzdata.zi. The value
693+ // MST
694+ // is also an entry. Is it allowed to use the following?
695+ // MST-3
696+ // Even when this is valid there is no time_zone record in the
697+ // database. Since the library would need to return a valid pointer,
698+ // this means the library needs to allocate and leak a pointer.
699+ //
700+ // - The time zone name is the target of the symlink /etc/localtime
701+ // relative to /usr/share/zoneinfo/
702+
703+ // The algorithm is like this:
704+ // - If the environment variable TZ is set and points to a valid
705+ // record use this value.
706+ // - Else use the name based on the `/etc/localtime` symlink.
707+
708+ if (const char * __tz = getenv (" TZ" ))
709+ if (const time_zone* __result = tzdb.__locate_zone (__tz))
710+ return __result;
711+
712+ filesystem::path __path = " /etc/localtime" ;
713+ if (!std::filesystem::exists (__path))
714+ std::__throw_runtime_error (" tzdb: the symlink '/etc/localtime' does not exist" );
715+
716+ if (!std::filesystem::is_symlink (__path))
717+ std::__throw_runtime_error (" tzdb: the path '/etc/localtime' is not a symlink" );
718+
719+ filesystem::path __tz = filesystem::read_symlink (__path);
720+ string __name = filesystem::relative (__tz, " /usr/share/zoneinfo/" );
721+
722+ if (const time_zone* __result = tzdb.__locate_zone (__name))
723+ return __result;
724+
725+ std::__throw_runtime_error ((" tzdb: the time zone '" + __name + " ' is not found in the database" ).c_str ());
726+ }
727+ #endif // ifdef _WIN32
728+
678729// ===----------------------------------------------------------------------===//
679730// Public API
680731// ===----------------------------------------------------------------------===//
@@ -684,6 +735,14 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_l
684735 return __result;
685736}
686737
738+ [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const time_zone* tzdb::__current_zone () const {
739+ #ifdef _WIN32
740+ return chrono::__current_zone_windows (*this );
741+ #else
742+ return chrono::__current_zone_posix (*this );
743+ #endif
744+ }
745+
687746_LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const tzdb& reload_tzdb () {
688747 if (chrono::remote_version () == chrono::get_tzdb ().version )
689748 return chrono::get_tzdb ();
0 commit comments