classification
Title: timedelta multiply and divide by floating point
Type: Stage:
Components: Library (Lib) Versions: Python 2.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: agthorr, haypo, mcherm, rhettinger, skip.montanaro, tim_one (6)
Priority: normal Keywords

Created on 2005-09-12 21:41 by agthorr, last changed 2008-12-22 14:25 by haypo.

Files
File name Uploaded Description Edit Remove
dt.diff skip.montanaro, 2007-09-02 01:54
Messages (9)
msg26263 - (view) Author: Daniel Stutzbach (agthorr) Date: 2005-09-12 21:41
In python 2.4.1, the datetime.timedelta type allows for
the multiplication and division by integers.  However,
it raises a TypeError for multiplication or division by
floating point numbers.  This is a counterintutive
restriction and I can't think of any good reason for it.

For example:

>>> import datetime
>>> datetime.timedelta(minutes=5)/2
datetime.timedelta(0, 150)
>>> datetime.timedelta(minutes=5)*0.5
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for *:
'datetime.timedelta' and 'float'
msg26264 - (view) Author: Raymond Hettinger (rhettinger) Date: 2005-09-13 04:11
Logged In: YES 
user_id=80475

Tim, do you prefer the current behavior?
msg26265 - (view) Author: Michael Chermside (mcherm) Date: 2005-09-15 16:03
Logged In: YES 
user_id=99874

I, too, would like to know what Tim thinks, but for what it's 
worth (not much) I find Daniel's point fairly convincing... 
multiplication by floats is an operation that makes sense, has 
only one possible obvious meaning, and is not particularly 
likely to cause errors (the way multiplying Decimal's with 
floats does). So IF it's easy to implement, I say go for it.
msg26266 - (view) Author: Tim Peters (tim_one) Date: 2005-09-15 21:04
Logged In: YES 
user_id=31435

timedelta arithmetic is 100% portable now, and wholly 
explainable in terms of universally understood integer 
arithmetic.  Throw floats into it, and that's lost.

That said, I don't have a strong objection to complicating the 
implementation if there _are_ strong use cases.  The OP's 
example isn't "a use case":  it's not worth anything to let 
someone multiply a timedelta by 0.5 instead of dividing by 2.  
I don't have a use case to offer in its place (never felt a need 
here).

If someone wants to work on it, note that a timedelta can 
contain more than 53 bits of information, so, e.g., trying to 
represent a timedelta as an IEEE double-precision number of 
microseconds can lose information.  This makes a high-
qualty "computed as if to infinite precision with one rounding 
at the end" implementation of mixed datetime/float arithmetic 
tricky to do right.
msg26267 - (view) Author: Daniel Stutzbach (agthorr) Date: 2005-09-15 22:00
Logged In: YES 
user_id=6324

Let me elaborate on the use-case where I originally ran into
this.

I'm conducting a series of observation experiments where I
measure the duration of an event.  I then want to do various
statistical analysis such as computing the mean, median,
etc.  Originally, I tried using standard functions such as
lmean from the stats.py package.  However, these sorts of
functions divide by a float at the end, causing them to fail
on timedelta objects.  Thus, I have to either write my own
special functions, or convert the timedelta objects to
integers first (then convert them back afterwards).

Basically, I want timedelta objects to look and act like
fixed-point arithmetic objects so that I can reuse other
functions on them that were originally developed to operate
on floats.  More importantly, I'd rather not have to
maintain two different versions of the functions to deal
with different types.

For implementation, why not multiply the float times .day,
.seconds, and .microseconds separately, then propagate and
fraction parts into the next smallest group (e.g., 0.5 days
becomes 24*60*60*0.5 seconds).

I agree it'd be possible to lose information with the wrong
sequence of operations, but that's always the case when
using floating point numbers.  In other words, that, too, is
what I would expect from the timedelta implementation.
msg26268 - (view) Author: Skip Montanaro (skip.montanaro) Date: 2005-09-17 01:48
Logged In: YES 
user_id=44345

>> Thus, I have to either write my own special functions, or convert
>> the timedelta objects to integers first (then convert them back
>> afterwards).

How about adding tolong() that returns the number of microseconds
in the timedelta and fromlong() that accepts a long representing
microseconds and returns a timedelta object?  That way the timedelta
object does a reasonably simple thing and the user is still responsible
for overflow the normal arithmetic stuff.  You can do any sort of
arithmetic operations on the long (including converting to other
numeric types) with all the attendant caveats, then convert back to
a timedelta object at the end.
msg55569 - (view) Author: Skip Montanaro (skip.montanaro) Date: 2007-09-02 01:54
Attached is a diff to the datetime module that
implements floating point division.  Comments?
Is it worthwhile to pursue?  If so, I'll
implement the other floating point arithmetic
operations.
msg55570 - (view) Author: Skip Montanaro (skip.montanaro) Date: 2007-09-02 02:59
Ummm... make that: "I'll implement multiplication."
msg78185 - (view) Author: STINNER Victor (haypo) Date: 2008-12-22 14:25
I like this idea, it's the opposite of the issue #2706.
History
Date User Action Args
2008-12-22 14:25:54hayposetnosy: + haypo
messages: + msg78185
2007-09-02 02:59:53skip.montanarosetmessages: + msg55570
2007-09-02 01:54:54skip.montanarosetfiles: + dt.diff
messages: + msg55569
versions: + Python 2.6
2005-09-12 21:41:10agthorrcreate