@@ -708,6 +708,39 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
708
708
std::__throw_runtime_error (" unknown time zone" );
709
709
}
710
710
#else // ifdef _WIN32
711
+
712
+ [[nodiscard]] static string __current_zone_environment () {
713
+ if (const char * __tz = std::getenv (" TZ" ))
714
+ return __tz;
715
+
716
+ return {};
717
+ }
718
+
719
+ [[nodiscard]] static string __current_zone_etc_localtime () {
720
+ filesystem::path __path = " /etc/localtime" ;
721
+ if (!filesystem::exists (__path) || !filesystem::is_symlink (__path))
722
+ return {};
723
+
724
+ filesystem::path __tz = filesystem::read_symlink (__path);
725
+ // The path may be a relative path, in that case convert it to an absolute
726
+ // path based on the proper initial directory.
727
+ if (__tz.is_relative ())
728
+ __tz = filesystem::canonical (" /etc" / __tz);
729
+
730
+ return filesystem::relative (__tz, " /usr/share/zoneinfo/" );
731
+ }
732
+
733
+ [[nodiscard]] static string __current_zone_etc_timezone () {
734
+ filesystem::path __path = " /etc/timezone" ;
735
+ if (!filesystem::exists (__path))
736
+ return {};
737
+
738
+ ifstream __f (__path);
739
+ string __name;
740
+ std::getline (__f, __name);
741
+ return __name;
742
+ }
743
+
711
744
[[nodiscard]] static const time_zone* __current_zone_posix (const tzdb& tzdb) {
712
745
// On POSIX systems there are several ways to configure the time zone.
713
746
// In order of priority they are:
@@ -726,30 +759,28 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
726
759
//
727
760
// - The time zone name is the target of the symlink /etc/localtime
728
761
// relative to /usr/share/zoneinfo/
762
+ //
763
+ // - The file /etc/timezone. This text file contains the name of the time
764
+ // zone.
765
+ //
766
+ // On Linux systems it seems /etc/timezone is deprecated and being phased
767
+ // out. This file is used when /etc/localtime does not exist, or when it exists but is not a symlink. For more information and links see
768
+ // https://github.com/llvm/llvm-project/issues/105634
729
769
730
- // The algorithm is like this:
731
- // - If the environment variable TZ is set and points to a valid
732
- // record use this value.
733
- // - Else use the name based on the `/etc/localtime` symlink.
770
+ string __name = chrono::__current_zone_environment ();
734
771
735
- if (const char * __tz = getenv (" TZ" ))
736
- if (const time_zone* __result = tzdb.__locate_zone (__tz))
772
+ // Ignore invalid names in the environment.
773
+ if (!__name.empty ())
774
+ if (const time_zone* __result = tzdb.__locate_zone (__name))
737
775
return __result;
738
776
739
- filesystem::path __path = " /etc/localtime" ;
740
- if (!filesystem::exists (__path))
741
- std::__throw_runtime_error (" tzdb: the symlink '/etc/localtime' does not exist" );
742
-
743
- if (!filesystem::is_symlink (__path))
744
- std::__throw_runtime_error (" tzdb: the path '/etc/localtime' is not a symlink" );
777
+ __name = chrono::__current_zone_etc_localtime ();
778
+ if (__name.empty ())
779
+ __name = chrono::__current_zone_etc_timezone ();
745
780
746
- filesystem::path __tz = filesystem::read_symlink (__path);
747
- // The path may be a relative path, in that case convert it to an absolute
748
- // path based on the proper initial directory.
749
- if (__tz.is_relative ())
750
- __tz = filesystem::canonical (" /etc" / __tz);
781
+ if (__name.empty ())
782
+ std::__throw_runtime_error (" tzdb: unable to determine the name of the current time zone" );
751
783
752
- string __name = filesystem::relative (__tz, " /usr/share/zoneinfo/" );
753
784
if (const time_zone* __result = tzdb.__locate_zone (__name))
754
785
return __result;
755
786
0 commit comments