66
77import  pathlib 
88import  datetime 
9+ import  zoneinfo 
910
1011import  pandas  as  pd 
1112import  pytz 
@@ -21,12 +22,15 @@ class Location:
2122    time zone, and altitude data associated with a particular geographic 
2223    location. You can also assign a name to a location object. 
2324
24-     Location objects have two time-zone attributes, either of which can be 
25-     individually changed after the Location object has been instantiated and 
26-     the other will stay in sync: 
25+     Location objects have two time-zone attributes: 
2726
28-         * ``tz`` is a IANA time-zone string. 
29-         * ``pytz`` is a pytz time-zone object. 
27+         * ``tz`` is an IANA time-zone string. 
28+         * ``pytz`` is a pytz-based time-zone object (read-only). 
29+         * ``zoneinfo`` is a zoneinfo.ZoneInfo time-zone object (read-only). 
30+ 
31+     As with Location-object initialization, use the ``tz`` attribute update 
32+     the Location's time zone after instantiation, and the read-only ``pytz`` 
33+     and ``zoneinfo`` attributes will stay in sync with any change in ``tz``. 
3034
3135    Location objects support the print method. 
3236
@@ -42,14 +46,16 @@ class Location:
4246
4347    tz : time zone as str, int, float, or datetime.tzinfo (inc. subclasses 
4448        from the pytz and zoneinfo packages), default 'UTC'. 
45-         See http://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a 
46-         list of valid name strings for IANA time zones. 
47-         ints and floats must be non-fractional N-hour offsets from UTC, which 
48-         are converted to the 'Etc/GMT-N' format (note limited range of N and 
49-         its conventional sign change). 
49+         This value is stored as a valid IANA time zone name string. See 
50+         http://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a 
51+         list of valid name strings, any of which may be passed directly here. 
52+         ints and floats must be whole-number hour offsets from UTC, which 
53+         are converted to the IANA-suppored 'Etc/GMT-N' format (note the 
54+         limited range of the offset N and its sign-change convention). 
5055        Raises TypeError for time zone conversion issues or 
51-         pytz.exceptions.UnknownTimeZoneError when (stringified) time zone is 
52-         not recognized by pytz.timezone. 
56+         zoneinfo.ZoneInfoNotFoundError when the (stringified) time zone is 
57+         not recognized as an IANA time zone by the zoneinfo.ZoneInfo 
58+         initializer used for internal time-zone representation. 
5359
5460    altitude : float, optional 
5561        Altitude from sea level in meters. 
@@ -87,33 +93,41 @@ def __repr__(self):
8793
8894    @property  
8995    def  tz (self ):
90-         # self.pytz holds the single source of time-zone truth. 
91-         return  self .pytz .zone 
96+         return  str (self ._zoneinfo )
9297
9398    @tz .setter  
9499    def  tz (self , tz_ ):
100+         # self._zoneinfo holds single source of time-zone truth as IANA name. 
95101        if  isinstance (tz_ , str ):
96-             self .pytz  =  pytz . timezone (tz_ )
102+             self ._zoneinfo  =  zoneinfo . ZoneInfo (tz_ )
97103        elif  isinstance (tz_ , int ):
98-             self .pytz  =  pytz . timezone (f"Etc/GMT{ - tz_ :+d}  " )
104+             self ._zoneinfo  =  zoneinfo . ZoneInfo (f"Etc/GMT{ - tz_ :+d}  " )
99105        elif  isinstance (tz_ , float ):
100106            if  tz_  %  1  !=  0 :
101107                raise  TypeError (
102-                     "floating  point tz does not have  zero fractional part: " 
103-                     f"{ tz_ }  " 
108+                     "Floating- point tz has non- zero fractional part: " 
109+                     f"{ tz_ } . Only whole-number offsets are supported. " 
104110                )
105111
106-             self .pytz  =  pytz . timezone (f"Etc/GMT{ - int (tz_ ):+d}  " )
112+             self ._zoneinfo  =  zoneinfo . ZoneInfo (f"Etc/GMT{ - int (tz_ ):+d}  " )
107113        elif  isinstance (tz_ , datetime .tzinfo ):
108114            # Includes time zones generated by pytz and zoneinfo packages. 
109-             self .pytz  =  pytz . timezone (str (tz_ ))
115+             self ._zoneinfo  =  zoneinfo . ZoneInfo (str (tz_ ))
110116        else :
111117            raise  TypeError (
112118                f"invalid tz specification: { tz_ }  , must be an IANA time zone " 
113-                 "string, a non-fractional  int/float UTC offset, or a " 
119+                 "string, a whole-number  int/float UTC offset, or a " 
114120                "datetime.tzinfo object (including subclasses)" 
115121            )
116122
123+     @property  
124+     def  pytz (self ):
125+         return  pytz .timezone (str (self ._zoneinfo ))
126+ 
127+     @property  
128+     def  zoneinfo (self ):
129+         return  self ._zoneinfo 
130+ 
117131    @classmethod  
118132    def  from_tmy (cls , tmy_metadata , tmy_data = None , ** kwargs ):
119133        """ 
0 commit comments