5151)
5252from  neo4j .time .arithmetic  import  (
5353    nano_add ,
54-     nano_sub ,
55-     nano_mul ,
5654    nano_div ,
57-     nano_mod ,
58-     nano_divmod ,
5955    symmetric_divmod ,
6056    round_half_to_even ,
6157)
@@ -334,18 +330,16 @@ class Duration(tuple):
334330    max  =  None 
335331
336332    def  __new__ (cls , years = 0 , months = 0 , weeks = 0 , days = 0 , hours = 0 , minutes = 0 ,
337-                 seconds = 0 , milliseconds = 0 , microseconds = 0 , nanoseconds = 0 ,
338-                 subseconds = 0 ):
333+                 seconds = 0 , subseconds = 0 , milliseconds = 0 , microseconds = 0 ,
334+                 nanoseconds = 0 ):
339335
340-         if  subseconds  and  nanoseconds :
341-             raise  ValueError ("Specify either subseconds or nanoseconds" )
342336        if  subseconds :
343-             deprecation_warn ("subseconds will be removed in 5.0." 
337+             deprecation_warn ("` subseconds`  will be removed in 5.0.  " 
344338                             "Use `nanoseconds` instead." )
345339            with  _decimal_context (prec = 9 , rounding = ROUND_HALF_EVEN ):
346340                nanoseconds  =  int (Decimal (subseconds ) *  NANO_SECONDS )
347341
348-         mo  =  round_half_to_even (12  *  years  +  months )
342+         mo  =  int (12  *  years  +  months )
349343        if  mo  <  MIN_INT64  or  mo  >  MAX_INT64 :
350344            raise  ValueError ("Months value out of range" )
351345        d  =  int (7  *  weeks  +  days )
@@ -360,26 +354,22 @@ def __new__(cls, years=0, months=0, weeks=0, days=0, hours=0, minutes=0,
360354            raise  ValueError ("Days value out of range" )
361355        if  s  <  MIN_INT64  or  s  >  MAX_INT64 :
362356            raise  ValueError ("Seconds value out of range" )
363-         if  ns  <  MIN_INT64  or  s  >  MAX_INT64 :
364-             raise  ValueError ("Nanoseconds  value out of range" )
357+         if  s  <  MIN_INT64  or  s  >  MAX_INT64 :
358+             raise  ValueError ("Seconds  value out of range" )
365359        return  tuple .__new__ (cls , (mo , d , s , ns ))
366360
367361    def  __bool__ (self ):
368362        return  any (map (bool , self ))
369363
370364    __nonzero__  =  __bool__ 
371365
372-     def  _check_composite (self ):
373-         if  sum ((self [0 ], self [1 ], self [2 ] or  self [3 ])) >  1 :
374-             deprecation_warn (
375-                 "Dividing composite durations will cause an error in 5.0" 
376-             )
377- 
378366    def  __add__ (self , other ):
379367        if  isinstance (other , Duration ):
380368            return  Duration (
381-                 months = self [0 ] +  other [0 ], days = self [1 ] +  other [1 ],
382-                 seconds = self [2 ] +  other [2 ], nanoseconds = self [3 ] +  other [3 ]
369+                 months = self [0 ] +  int (other .months ),
370+                 days = self [1 ] +  int (other .days ),
371+                 seconds = self [2 ] +  int (other .seconds ),
372+                 nanoseconds = self [3 ] +  int (other .nanoseconds )
383373            )
384374        if  isinstance (other , timedelta ):
385375            return  Duration (
@@ -392,30 +382,35 @@ def __add__(self, other):
392382    def  __sub__ (self , other ):
393383        if  isinstance (other , Duration ):
394384            return  Duration (
395-                 months = self [0 ] -  other [0 ], days = self [1 ] -  other [1 ],
396-                 seconds = self [2 ] -  other [2 ],
397-                 nanoseconds = self [3 ] -  other [3 ]
385+                 months = self [0 ] -  int (other .months ),
386+                 days = self [1 ] -  int (other .days ),
387+                 seconds = self [2 ] -  int (other .seconds ),
388+                 nanoseconds = self [3 ] -  int (other .nanoseconds )
398389            )
399390        if  isinstance (other , timedelta ):
400391            return  Duration (
401-                 months = self [0 ], days = self [1 ] -  other .days ,
392+                 months = self [0 ],
393+                 days = self [1 ] -  other .days ,
402394                seconds = self [2 ] -  other .seconds ,
403395                nanoseconds = self [3 ] -  other .microseconds  *  1000 
404396            )
405397        return  NotImplemented 
406398
407399    def  __mul__ (self , other ):
400+         if  isinstance (other , float ):
401+             deprecation_warn ("Multiplication with float will be deprecated in " 
402+                              "5.0." )
408403        if  isinstance (other , (int , float )):
409404            return  Duration (
410405                months = self [0 ] *  other , days = self [1 ] *  other ,
411406                seconds = self [2 ] *  other , nanoseconds = self [3 ] *  other 
412407            )
413408        return  NotImplemented 
414409
410+     @deprecated ("Will be removed in 5.0." ) 
415411    def  __floordiv__ (self , other ):
416-         self ._check_composite ()
417412        if  isinstance (other , int ):
418-             # TODO 5.0: new method (floor months, days, nanoseconds) 
413+             # TODO 5.0: new method (floor months, days, nanoseconds) or remove  
419414            # return Duration( 
420415            #     months=self[0] // other, days=self[1] // other, 
421416            #     nanoseconds=(self[2] * NANO_SECONDS + self[3]) // other 
@@ -426,10 +421,10 @@ def __floordiv__(self, other):
426421                            seconds = int (seconds  //  other ))
427422        return  NotImplemented 
428423
424+     @deprecated ("Will be removed in 5.0." ) 
429425    def  __mod__ (self , other ):
430-         self ._check_composite ()
431426        if  isinstance (other , int ):
432-             # TODO 5.0: new method (mod months, days, nanoseconds) 
427+             # TODO 5.0: new method (mod months, days, nanoseconds) or remove  
433428            # return Duration( 
434429            #     months=self[0] % other, days=self[1] % other, 
435430            #     nanoseconds=(self[2] * NANO_SECONDS + self[3]) % other 
@@ -441,13 +436,14 @@ def __mod__(self, other):
441436                            seconds = seconds , subseconds = subseconds )
442437        return  NotImplemented 
443438
439+     @deprecated ("Will be removed in 5.0." ) 
444440    def  __divmod__ (self , other ):
445441        if  isinstance (other , int ):
446442            return  self .__floordiv__ (other ), self .__mod__ (other )
447443        return  NotImplemented 
448444
445+     @deprecated ("Will be removed in 5.0." ) 
449446    def  __truediv__ (self , other ):
450-         self ._check_composite ()
451447        if  isinstance (other , (int , float )):
452448            return  Duration (
453449                months = round_half_to_even (self [0 ] /  other ),
@@ -1141,9 +1137,10 @@ def from_iso_format(cls, s):
11411137    @classmethod  
11421138    def  from_ticks (cls , ticks , tz = None ):
11431139        if  0  <=  ticks  <  86400 :
1144-             minute , second  =  nano_divmod (ticks , 60 )
1145-             hour , minute  =  divmod (minute , 60 )
1146-             return  cls .__new (ticks , hour , minute , second , tz )
1140+             ticks  =  Decimal (ticks ) *  NANO_SECONDS 
1141+             ticks  =  int (ticks .quantize (Decimal ("1." ), rounding = ROUND_HALF_EVEN ))
1142+             assert  0  <=  ticks  <  86400000000000 
1143+             return  cls .from_ticks_ns (ticks , tz = tz )
11471144        raise  ValueError ("Ticks out of range (0..86400)" )
11481145
11491146    @classmethod  
@@ -1249,7 +1246,7 @@ def ticks(self):
12491246    def  ticks_ns (self ):
12501247        """ Return the total number of seconds since midnight. 
12511248        """ 
1252-         # TODO 5.0: this will replace   self.__ticks  
1249+         # TODO 5.0: this will replace self.ticks  
12531250        return  self .__ticks 
12541251
12551252    @property  
@@ -1408,9 +1405,9 @@ def to_native(self):
14081405        """ Convert to a native Python `datetime.time` value. 
14091406        """ 
14101407        h , m , s , ns  =  self .hour_minute_second_nanoseconds 
1411-         mic_s  =  round_half_to_even (ns  /  1000 )
1408+         µs  =  round_half_to_even (ns  /  1000 )
14121409        tz  =  self .tzinfo 
1413-         return  time (h , m , s , mic_s , tz )
1410+         return  time (h , m , s , µs , tz )
14141411
14151412    def  iso_format (self ):
14161413        s  =  "%02d:%02d:%02d.%09d"  %  self .hour_minute_second_nanoseconds 
@@ -1568,8 +1565,8 @@ def from_clock_time(cls, clock_time, epoch):
15681565        else :
15691566            ordinal , seconds  =  divmod (seconds , 86400 )
15701567            ticks  =  epoch .time ().ticks_ns  +  seconds  *  NANO_SECONDS  +  nanoseconds 
1571-             ticks_overflow , ticks  =  divmod (ticks , 86400  *  NANO_SECONDS )
1572-             ordinal  +=  ticks_overflow 
1568+             days , ticks  =  divmod (ticks , 86400  *  NANO_SECONDS )
1569+             ordinal  +=  days 
15731570            date_  =  Date .from_ordinal (ordinal  +  epoch .date ().to_ordinal ())
15741571            time_  =  Time .from_ticks_ns (ticks )
15751572            return  cls .combine (date_ , time_ )
0 commit comments