YADTR (Yet Another DateTime Rant)

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Mar 28 12:11:54 CET 2014

On Thu, 27 Mar 2014 20:29:17 -0400, Roy Smith wrote:

> In article <5334b747$0$29994$c3e8da3$5496439d at news.astraweb.com>,
>  Steven D'Aprano <steve+comp.lang.python at pearwood.info> wrote:
>> On Thu, 27 Mar 2014 08:52:24 -0400, Roy Smith wrote:
>> > In article <mailman.8613.1395917059.18130.python-list at python.org>,
>> >  Chris Angelico <rosuav at gmail.com> wrote:
>> >> It's not "equally braindead", it follows a simple and logical rule:
>> >> Only the day portion is negative.
>> > 
>> > Simple and logical, yes.  But also entirely braindead.
>> Do you think it is "braindead" for __str__ to return something which
>> follows the internal representation of the object?
> Yes.  The whole idea of OOD is to decouple internal representation from
> external behavior.

The *whole* idea? You don't think that encapsulation and inheritance 
might also be involved? *wink*

Besides, there's a difference between internal _representation_ and 
internal _implementation_. I don't always choose my words carefully, but 
this was one of those times :-)

A timedelta object *represents* a delta as (days + seconds + 
microseconds). That is part of the interface, not implementation. How it 
is actually implemented is irrelevant. (If I were to take a wild guess, 
I'd predict that timedeltas record the total number of seconds.)

>> > Give ma a real-life situation where you would want such behavior.
>> Easy -- I'm debugging timedelta routines, and I want to easily see that
>> the timedeltas calculated match what I expect them to be when I print
>> them. The quickest, easiest and simplest way is for str(timedelta) to
>> follow the internal representation.
> That's what __repr__() is for.

Actually, __repr__ should, if practical, match the constructor for the 

py> import datetime
py> t = datetime.timedelta(2, 3)
py> eval(repr(t)) == t

>> Oh look, that's exactly what the docs say:
>> "String representations of timedelta objects are normalized similarly
>> to their internal representation. This leads to somewhat unusual
>> results for negative timedeltas."
> Yes, I know that's what the docs say.  That's why it's not an
> implementation bug.  It's a design bug :-)

I don't think it is. Given a timedelta object with D days, S seconds and 
M microseconds, I think that it is a very useful property if the string 
also says it has D days, S seconds and M microseconds. Would you not 
agree? I think that this would be silly:

str(timedelta(1, 0, 0))
=> '0 day, 24:01:-5184000.0'

even though it would be correct. So we can dismiss the idea that the str 
of a timedelta should be free to arbitrarily vary from the internal 

I consider this to be a useful constraint on timedelta's internal 
representation (not implementation): the seconds and microseconds should 
be normalised to the half-open intervals, 0 to 86400 for seconds and 0 to 
1000000 for microseconds. Given that constraint, and the previous 
constraint that strings should show the same number of days etc., and we 
have the current behaviour.

Both constraints are reasonable. You have to weaken one, or the other, in 
order to get the result you want. That's not necessarily unreasonable, 
but neither is it a given. Python-Dev is not normally "braindead", so at 
least given them the benefit of the doubt that *maybe* there's some good 
reason we haven't thought of.

Steven D'Aprano

More information about the Python-list mailing list