@@ -1657,73 +1657,81 @@ def tzinfo(self):
16571657
16581658    # OPERATIONS # 
16591659
1660+     def  _get_both_normalized_ticks (self , other , strict = True ):
1661+         if  (isinstance (other , (time , Time ))
1662+                 and  ((self .utc_offset () is  None )
1663+                      ^  (other .utcoffset () is  None ))):
1664+             if  strict :
1665+                 raise  TypeError ("can't compare offset-naive and offset-aware " 
1666+                                 "times" )
1667+             else :
1668+                 return  None , None 
1669+         if  isinstance (other , Time ):
1670+             other_ticks  =  other .__ticks 
1671+         elif  isinstance (other , time ):
1672+             other_ticks  =  int (3600000000000  *  other .hour 
1673+                               +  60000000000  *  other .minute 
1674+                               +  NANO_SECONDS  *  other .second 
1675+                               +  1000  *  other .microsecond )
1676+         else :
1677+             return  None , None 
1678+         utc_offset  =  other .utcoffset ()
1679+         if  utc_offset  is  not   None :
1680+             other_ticks  -=  utc_offset .total_seconds () *  NANO_SECONDS 
1681+         self_ticks  =  self .__ticks 
1682+         utc_offset  =  self .utc_offset ()
1683+         if  utc_offset  is  not   None :
1684+             self_ticks  -=  utc_offset .total_seconds () *  NANO_SECONDS 
1685+         return  self_ticks , other_ticks 
1686+ 
16601687    def  __hash__ (self ):
16611688        """""" 
1662-         return  hash (self .__ticks ) ^  hash (self .tzinfo )
1689+         if  self .__nanosecond  %  1000  ==  0 :
1690+             return  hash (self .to_native ())
1691+         self_ticks  =  self .__ticks 
1692+         if  self .utc_offset () is  not   None :
1693+             self_ticks  -=  self .utc_offset ().total_seconds () *  NANO_SECONDS 
1694+         return  hash (self_ticks )
16631695
16641696    def  __eq__ (self , other ):
16651697        """`==` comparison with :class:`.Time` or :class:`datetime.time`.""" 
1666-         if  isinstance (other , Time ):
1667-             return  self .__ticks  ==  other .__ticks  and  self .tzinfo  ==  other .tzinfo 
1668-         if  isinstance (other , time ):
1669-             other_ticks  =  (3600000000000  *  other .hour 
1670-                            +  60000000000  *  other .minute 
1671-                            +  NANO_SECONDS  *  other .second 
1672-                            +  1000  *  other .microsecond )
1673-             return  self .ticks  ==  other_ticks  and  self .tzinfo  ==  other .tzinfo 
1674-         return  False 
1698+         self_ticks , other_ticks  =  self ._get_both_normalized_ticks (other ,
1699+                                                                   strict = False )
1700+         if  self_ticks  is  None :
1701+             return  False 
1702+         return  self_ticks  ==  other_ticks 
16751703
16761704    def  __ne__ (self , other ):
16771705        """`!=` comparison with :class:`.Time` or :class:`datetime.time`.""" 
16781706        return  not  self .__eq__ (other )
16791707
16801708    def  __lt__ (self , other ):
16811709        """`<` comparison with :class:`.Time` or :class:`datetime.time`.""" 
1682-         if  isinstance (other , Time ):
1683-             return  (self .tzinfo  ==  other .tzinfo 
1684-                     and  self .ticks  <  other .ticks )
1685-         if  isinstance (other , time ):
1686-             if  self .tzinfo  !=  other .tzinfo :
1687-                 return  False 
1688-             other_ticks  =  3600  *  other .hour  +  60  *  other .minute  +  other .second  +  (other .microsecond  /  1000000 )
1689-             return  self .ticks  <  other_ticks 
1690-         return  NotImplemented 
1710+         self_ticks , other_ticks  =  self ._get_both_normalized_ticks (other )
1711+         if  self_ticks  is  None :
1712+             return  NotImplemented 
1713+         return  self_ticks  <  other_ticks 
16911714
16921715    def  __le__ (self , other ):
16931716        """`<=` comparison with :class:`.Time` or :class:`datetime.time`.""" 
1694-         if  isinstance (other , Time ):
1695-             return  (self .tzinfo  ==  other .tzinfo 
1696-                     and  self .ticks  <=  other .ticks )
1697-         if  isinstance (other , time ):
1698-             if  self .tzinfo  !=  other .tzinfo :
1699-                 return  False 
1700-             other_ticks  =  3600  *  other .hour  +  60  *  other .minute  +  other .second  +  (other .microsecond  /  1000000 )
1701-             return  self .ticks  <=  other_ticks 
1702-         return  NotImplemented 
1717+         self_ticks , other_ticks  =  self ._get_both_normalized_ticks (other )
1718+         if  self_ticks  is  None :
1719+             return  NotImplemented 
1720+         return  self_ticks  <=  other_ticks 
17031721
17041722    def  __ge__ (self , other ):
17051723        """`>=` comparison with :class:`.Time` or :class:`datetime.time`.""" 
1706-         if  isinstance (other , Time ):
1707-             return  (self .tzinfo  ==  other .tzinfo 
1708-                     and  self .ticks  >=  other .ticks )
1709-         if  isinstance (other , time ):
1710-             if  self .tzinfo  !=  other .tzinfo :
1711-                 return  False 
1712-             other_ticks  =  3600  *  other .hour  +  60  *  other .minute  +  other .second  +  (other .microsecond  /  1000000 )
1713-             return  self .ticks  >=  other_ticks 
1714-         return  NotImplemented 
1724+         self_ticks , other_ticks  =  self ._get_both_normalized_ticks (other )
1725+         if  self_ticks  is  None :
1726+             return  NotImplemented 
1727+         return  self_ticks  >=  other_ticks 
17151728
17161729    def  __gt__ (self , other ):
17171730        """`>` comparison with :class:`.Time` or :class:`datetime.time`.""" 
1718-         if  isinstance (other , Time ):
1719-             return  (self .tzinfo  ==  other .tzinfo 
1720-                     and  self .ticks  >=  other .ticks )
1721-         if  isinstance (other , time ):
1722-             if  self .tzinfo  !=  other .tzinfo :
1723-                 return  False 
1724-             other_ticks  =  3600  *  other .hour  +  60  *  other .minute  +  other .second  +  (other .microsecond  /  1000000 )
1725-             return  self .ticks  >=  other_ticks 
1726-         return  NotImplemented 
1731+         self_ticks , other_ticks  =  self ._get_both_normalized_ticks (other )
1732+         if  self_ticks  is  None :
1733+             return  NotImplemented 
1734+         return  self_ticks  >  other_ticks 
17271735
17281736    def  __copy__ (self ):
17291737        return  self .__new (self .__ticks , self .__hour , self .__minute ,
@@ -1757,6 +1765,21 @@ def replace(self, **kwargs):
17571765                    nanosecond = kwargs .get ("nanosecond" , self .__nanosecond ),
17581766                    tzinfo = kwargs .get ("tzinfo" , self .__tzinfo ))
17591767
1768+     def  _utc_offset (self , dt = None ):
1769+         if  self .tzinfo  is  None :
1770+             return  None 
1771+         value  =  self .tzinfo .utcoffset (dt )
1772+         if  value  is  None :
1773+             return  None 
1774+         if  isinstance (value , timedelta ):
1775+             s  =  value .total_seconds ()
1776+             if  not  (- 86400  <  s  <  86400 ):
1777+                 raise  ValueError ("utcoffset must be less than a day" )
1778+             if  s  %  60  !=  0  or  value .microseconds  !=  0 :
1779+                 raise  ValueError ("utcoffset must be a whole number of minutes" )
1780+             return  value 
1781+         raise  TypeError ("utcoffset must be a timedelta" )
1782+ 
17601783    def  utc_offset (self ):
17611784        """Return the UTC offset of this time. 
17621785
@@ -1770,19 +1793,7 @@ def utc_offset(self):
17701793        :raises TypeError: if `self.tzinfo.utcoffset(self)` does return anything but 
17711794            None or a :class:`datetime.timedelta`. 
17721795        """ 
1773-         if  self .tzinfo  is  None :
1774-             return  None 
1775-         value  =  self .tzinfo .utcoffset (self )
1776-         if  value  is  None :
1777-             return  None 
1778-         if  isinstance (value , timedelta ):
1779-             s  =  value .total_seconds ()
1780-             if  not  (- 86400  <  s  <  86400 ):
1781-                 raise  ValueError ("utcoffset must be less than a day" )
1782-             if  s  %  60  !=  0  or  value .microseconds  !=  0 :
1783-                 raise  ValueError ("utcoffset must be a whole number of minutes" )
1784-             return  value 
1785-         raise  TypeError ("utcoffset must be a timedelta" )
1796+         return  self ._utc_offset ()
17861797
17871798    def  dst (self ):
17881799        """Get the daylight saving time adjustment (DST). 
@@ -2194,17 +2205,52 @@ def hour_minute_second_nanosecond(self):
21942205
21952206    # OPERATIONS # 
21962207
2208+     def  _get_both_normalized (self , other , strict = True ):
2209+         if  (isinstance (other , (datetime , DateTime ))
2210+                 and  ((self .utc_offset () is  None )
2211+                      ^  (other .utcoffset () is  None ))):
2212+             if  strict :
2213+                 raise  TypeError ("can't compare offset-naive and offset-aware " 
2214+                                 "datetimes" )
2215+             else :
2216+                 return  None , None 
2217+         self_norm  =  self 
2218+         utc_offset  =  self .utc_offset ()
2219+         if  utc_offset  is  not   None :
2220+             self_norm  -=  utc_offset 
2221+         self_norm  =  self_norm .replace (tzinfo = None )
2222+         other_norm  =  other 
2223+         if  isinstance (other , (datetime , DateTime )):
2224+             utc_offset  =  other .utcoffset ()
2225+             if  utc_offset  is  not   None :
2226+                 other_norm  -=  utc_offset 
2227+             other_norm  =  other_norm .replace (tzinfo = None )
2228+         else :
2229+             return  None , None 
2230+         return  self_norm , other_norm 
2231+ 
21972232    def  __hash__ (self ):
21982233        """""" 
2199-         return  hash (self .date ()) ^  hash (self .time ())
2234+         if  self .nanosecond  %  1000  ==  0 :
2235+             return  hash (self .to_native ())
2236+         self_norm  =  self 
2237+         utc_offset  =  self .utc_offset ()
2238+         if  utc_offset  is  not   None :
2239+             self_norm  -=  utc_offset 
2240+         return  hash (self_norm .date ()) ^  hash (self_norm .time ())
22002241
22012242    def  __eq__ (self , other ):
22022243        """ 
22032244        `==` comparison with :class:`.DateTime` or :class:`datetime.datetime`. 
22042245        """ 
2205-         if  isinstance (other , (DateTime , datetime )):
2246+         if  not  isinstance (other , (datetime , DateTime )):
2247+             return  NotImplemented 
2248+         if  self .utc_offset () ==  other .utcoffset ():
22062249            return  self .date () ==  other .date () and  self .time () ==  other .time ()
2207-         return  False 
2250+         self_norm , other_norm  =  self ._get_both_normalized (other , strict = False )
2251+         if  self_norm  is  None :
2252+             return  False 
2253+         return  self_norm  ==  other_norm 
22082254
22092255    def  __ne__ (self , other ):
22102256        """ 
@@ -2216,45 +2262,55 @@ def __lt__(self, other):
22162262        """ 
22172263        `<` comparison with :class:`.DateTime` or :class:`datetime.datetime`. 
22182264        """ 
2219-         if  isinstance (other , (DateTime , datetime )):
2265+         if  not  isinstance (other , (datetime , DateTime )):
2266+             return  NotImplemented 
2267+         if  self .utc_offset () ==  other .utcoffset ():
22202268            if  self .date () ==  other .date ():
22212269                return  self .time () <  other .time ()
2222-             else :
2223-                 return  self .date () <  other .date ()
2224-         return  NotImplemented 
2270+             return  self .date () <  other .date ()
2271+         self_norm , other_norm  =  self ._get_both_normalized (other )
2272+         return  (self_norm .date () <  other_norm .date ()
2273+                 or  self_norm .time () <  other_norm .time ())
22252274
22262275    def  __le__ (self , other ):
22272276        """ 
22282277        `<=` comparison with :class:`.DateTime` or :class:`datetime.datetime`. 
22292278        """ 
2230-         if  isinstance (other , (DateTime , datetime )):
2279+         if  not  isinstance (other , (datetime , DateTime )):
2280+             return  NotImplemented 
2281+         if  self .utc_offset () ==  other .utcoffset ():
22312282            if  self .date () ==  other .date ():
22322283                return  self .time () <=  other .time ()
2233-             else : 
2234-                  return   self .date ()  <   other . date ( )
2235-         return  NotImplemented 
2284+             return   self . date ()  <=   other . date () 
2285+         self_norm ,  other_norm   =   self ._get_both_normalized ( other )
2286+         return  self_norm   <=   other_norm 
22362287
22372288    def  __ge__ (self , other ):
22382289        """ 
22392290        `>=` comparison with :class:`.DateTime` or :class:`datetime.datetime`. 
22402291        """ 
2241-         if  isinstance (other , (DateTime , datetime )):
2292+         if  not  isinstance (other , (datetime , DateTime )):
2293+             return  NotImplemented 
2294+         if  self .utc_offset () ==  other .utcoffset ():
22422295            if  self .date () ==  other .date ():
22432296                return  self .time () >=  other .time ()
2244-             else : 
2245-                  return   self .date ()  >   other . date ( )
2246-         return  NotImplemented 
2297+             return   self . date ()  >=   other . date () 
2298+         self_norm ,  other_norm   =   self ._get_both_normalized ( other )
2299+         return  self_norm   >=   other_norm 
22472300
22482301    def  __gt__ (self , other ):
22492302        """ 
22502303        `>` comparison with :class:`.DateTime` or :class:`datetime.datetime`. 
22512304        """ 
2252-         if  isinstance (other , (DateTime , datetime )):
2305+         if  not  isinstance (other , (datetime , DateTime )):
2306+             return  NotImplemented 
2307+         if  self .utc_offset () ==  other .utcoffset ():
22532308            if  self .date () ==  other .date ():
22542309                return  self .time () >  other .time ()
2255-             else :
2256-                 return  self .date () >  other .date ()
2257-         return  NotImplemented 
2310+             return  self .date () >  other .date ()
2311+         self_norm , other_norm  =  self ._get_both_normalized (other )
2312+         return  (self_norm .date () >  other_norm .date ()
2313+                 or  self_norm .time () >  other_norm .time ())
22582314
22592315    def  __add__ (self , other ):
22602316        """Add a :class:`datetime.timedelta`. 
@@ -2358,7 +2414,7 @@ def as_timezone(self, tz):
23582414        """ 
23592415        if  self .tzinfo  is  None :
23602416            return  self 
2361-         utc  =  (self  -  self .utcoffset ()).replace (tzinfo = tz )
2417+         utc  =  (self  -  self .utc_offset ()).replace (tzinfo = tz )
23622418        return  tz .fromutc (utc )
23632419
23642420    def  utc_offset (self ):
@@ -2367,7 +2423,7 @@ def utc_offset(self):
23672423        See :meth:`.Time.utc_offset`. 
23682424        """ 
23692425
2370-         return  self .__time .utc_offset ( )
2426+         return  self .__time ._utc_offset ( self )
23712427
23722428    def  dst (self ):
23732429        """Get the daylight saving time adjustment (DST). 
0 commit comments