
There's a furious discussion going on at the python-list mailing list, about negative timedelta strings: py> str(timedelta(0, -1)) '-1 day, 23:59:59' This is documented. It's even documented as being "somewhat unusual". I found a tracker item for it, back in July 2010: http://bugs.python.org/issue9430 and that refers back to a discussion on #python-dev, but (as far as I know) that's not archived anywhere. I had a look on the python-dev mailing list around that time, and couldn't find anything. Does anyone remember the rationale for this behaviour? Is it open to debate or is it now cast in stone? (Personally, I'm not looking to reopen the debate, and if I did, it would be on python-ideas.) Any links to the earlier discussion would be helpful. Thanks, -- Steve

On Fri, Mar 28, 2014 at 7:03 AM, Steven D'Aprano <steve@pearwood.info> wrote:
py> str(timedelta(0, -1)) '-1 day, 23:59:59' .. Does anyone remember the rationale for this behaviour?
I don't recall any better rationale than what I wrote in the docs: "String representations of timedelta objects are normalized similarly to their internal representation."
Is it open to debate or is it now cast in stone?
I think the barrier for changing str() is lower than that for changing repr(), but I would be against any changes in this area. (I may have had a different view if ISO 8601 syntax for timedeltas was not so ugly. :-)

On Fri, Mar 28, 2014 at 11:07 AM, Alexander Belopolsky <alexander.belopolsky@gmail.com> wrote:
Is it open to debate or is it now cast in stone?
I think the barrier for changing str() is lower than that for changing repr(), but I would be against any changes in this area. (I may have had a different view if ISO 8601 syntax for timedeltas was not so ugly. :-)
I think str() should be left alone. It's clear there is no one best str representation for timedelta objects. I think it might be worthwhile to add a method which allows the programmer to format timedelta objects in whatever way s/he sees fit. That would support the ISO 8601 syntax (*), and anything else the programmer things is better than the status quo. Skip (*) As an aside (that is, this belongs in a separate thread if you want to discuss it), in my opinion, attempting to support ISO 8601 formatting is pointless without the presence of an anchor datetime. Otherwise how would you know how far back "five months" or "seven years" was? If that's the case, then you might as well add the timedelta to your anchor datetime and just use datetime.strftime().

On Fri, 28 Mar 2014 11:19:52 -0500 Skip Montanaro <skip@pobox.com> wrote:
On Fri, Mar 28, 2014 at 11:07 AM, Alexander Belopolsky <alexander.belopolsky@gmail.com> wrote:
Is it open to debate or is it now cast in stone?
I think the barrier for changing str() is lower than that for changing repr(), but I would be against any changes in this area. (I may have had a different view if ISO 8601 syntax for timedeltas was not so ugly. :-)
I think str() should be left alone. It's clear there is no one best str representation for timedelta objects.
But at least we could have one that isn't terribly confusing :-) Regards Antoine.

On Fri, Mar 28, 2014 at 12:19 PM, Skip Montanaro <skip@pobox.com> wrote:
(*) As an aside (that is, this belongs in a separate thread if you want to discuss it), in my opinion, attempting to support ISO 8601 formatting is pointless without the presence of an anchor datetime.
I meant ISO 8601 syntax for "durations" [1]. """ For example, "P3Y6M4DT12H30M5S" represents a duration of "three years, six months, four days, twelve hours, thirty minutes, and five seconds". """ And if you have to ask - no I don't want to see this anywhere near Python stdlib. :-) [1] http://en.wikipedia.org/wiki/ISO_8601#Durations

On Fri, Mar 28, 2014 at 5:19 PM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
ISO 8601 doesn't seem to define a representation for negative durations, though, so it wouldn't solve the original problem.
Aside from the horribleness of the ISO 8601 notation for a duration, it's best not to confuse the notions of duration and delta. Notionally, a delta contains more information than a duration. -Fred -- Fred L. Drake, Jr. <fred at fdrake.net> "A storm broke loose in my mind." --Albert Einstein

On Fri, Mar 28, 2014 at 2:52 PM, Fred Drake <fred@fdrake.net> wrote:
On Fri, Mar 28, 2014 at 5:19 PM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
ISO 8601 doesn't seem to define a representation for negative durations, though, so it wouldn't solve the original problem.
Aside from the horribleness of the ISO 8601 notation for a duration, it's best not to confuse the notions of duration and delta. Notionally, a delta contains more information than a duration.
and less -- really it's different. A duration would be really useful actually, for things like "next month", etc,. IIRC, mxDateTime has something for this, but it's NOT the same as a timedelta. timedelta appears to be analogous to ISO 8601's " time interval", which requires 1. Start and end, such as "2007-03-01T13:00:00Z/2008-05-11T15:30:00Z" 2. Start and duration, such as "2007-03-01T13:00:00Z/P1Y2M10DT2H30M" 3. Duration and end, such as "P1Y2M10DT2H30M/2008-05-11T15:30:00Z" 4. Duration only, such as "P1Y2M10DT2H30M", with additional context information http://en.wikipedia.org/wiki/ISO_8601#Time_intervals I don't think there is or should be a any direct mapping from timedelta to ISO duration. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

n 31.03.2014 21:09, Chris Barker wrote:
On Fri, Mar 28, 2014 at 2:52 PM, Fred Drake <fred@fdrake.net> wrote:
On Fri, Mar 28, 2014 at 5:19 PM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
ISO 8601 doesn't seem to define a representation for negative durations, though, so it wouldn't solve the original problem.
Aside from the horribleness of the ISO 8601 notation for a duration, it's best not to confuse the notions of duration and delta. Notionally, a delta contains more information than a duration.
and less -- really it's different.
A duration would be really useful actually, for things like "next month", etc,. IIRC, mxDateTime has something for this, but it's NOT the same as a timedelta.
mxDateTime has DateTimeDelta objects which represent a time delta (in the mathematical sense) between two points in DateTime and RelativeDateTime objects which allow defining deltas in terms of qualifiers which are applied to the left hand side of an operation. With RelativeDateTime you can do things like e.g. first_of_next_month = now() + RelativeDateTime(months=+1, day=1) There are some other concepts you can emulate with these, like e.g. a specific time frame (DateTime + one of the above deltas), a reoccurring time (start_time + one of the deltas + number occurrences + exceptions), an age concept (difference between two DateTime values expressed in RelativeDateTime terms), etc. Some examples:
from mx.DateTime import *
print RelativeDateTime(months=+1, day=1) YYYY-(+01)-01 HH:MM:SS
print now() + RelativeDateTime(months=+1, day=1) 2014-05-01 14:49:05.83
print Age(now(), Date(1969,4,6)) (+0044)-(+11)-(+27) (+14):(+49):(+02)
-- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Apr 02 2014)
Python Projects, Consulting and Support ... http://www.egenix.com/ mxODBC.Zope/Plone.Database.Adapter ... http://zope.egenix.com/ mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
2014-04-09: PyCon 2014, Montreal, Canada ... 7 days to go 2014-04-29: Python Meeting Duesseldorf ... 27 days to go ::::: Try our mxODBC.Connect Python Database Interface for free ! :::::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/

On Wed, Apr 2, 2014 at 7:52 AM, M.-A. Lemburg <mal@egenix.com> wrote:
print now() + RelativeDateTime(months=+1, day=1) 2014-05-01 14:49:05.83
I find this sort date arithmetic unintuitive, though I'm at a loss to come up with better logic than you have:
d = Date(2014, 2, 28) d + RelativeDateTime(months=+1) <mx.DateTime.DateTime object for '2014-03-28 00:00:00.00' at 1eda8c8> d = Date(2014, 1, 31) d + RelativeDateTime(months=+1) <mx.DateTime.DateTime object for '2014-03-03 00:00:00.00' at 1eda870>
I guess the assumption is that one month is the length in days of the current month, though, you wind up with situations where shorter months can be skipped altogether. Is there a way to talk in terms of "months" but not have short months get skipped? Thx, Skip

On 2014-04-02, at 15:04 , Skip Montanaro <skip@pobox.com> wrote:
On Wed, Apr 2, 2014 at 7:52 AM, M.-A. Lemburg <mal@egenix.com> wrote:
print now() + RelativeDateTime(months=+1, day=1) 2014-05-01 14:49:05.83
I find this sort date arithmetic unintuitive, though I'm at a loss to come up with better logic than you have:
d = Date(2014, 2, 28) d + RelativeDateTime(months=+1) <mx.DateTime.DateTime object for '2014-03-28 00:00:00.00' at 1eda8c8> d = Date(2014, 1, 31) d + RelativeDateTime(months=+1) <mx.DateTime.DateTime object for '2014-03-03 00:00:00.00' at 1eda870>
I guess the assumption is that one month is the length in days of the current month, though, you wind up with situations where shorter months can be skipped altogether. Is there a way to talk in terms of "months" but not have short months get skipped?
FWIW dateutil has a slightly different logic there:
date(2014, 2, 28) + relativedelta(months=+1) datetime.date(2014, 3, 28) date(2014, 1, 31) + relativedelta(months=+1) datetime.date(2014, 2, 28)

On 02.04.2014 15:04, Skip Montanaro wrote:
On Wed, Apr 2, 2014 at 7:52 AM, M.-A. Lemburg <mal@egenix.com> wrote:
print now() + RelativeDateTime(months=+1, day=1) 2014-05-01 14:49:05.83
I find this sort date arithmetic unintuitive, though I'm at a loss to come up with better logic than you have:
d = Date(2014, 2, 28) d + RelativeDateTime(months=+1) <mx.DateTime.DateTime object for '2014-03-28 00:00:00.00' at 1eda8c8> d = Date(2014, 1, 31) d + RelativeDateTime(months=+1) <mx.DateTime.DateTime object for '2014-03-03 00:00:00.00' at 1eda870>
I guess the assumption is that one month is the length in days of the current month, though, you wind up with situations where shorter months can be skipped altogether. Is there a way to talk in terms of "months" but not have short months get skipped?
I'm not really satisfied with this solution either. The problem is that the qualifier "+ 1 month" is not defined for dates with don't have a corresponding day in the following month. This should probably either raise an exception or use some parameter to "solve" the problem, by e.g. choosing the last day of the month or using the current scheme: mxDateTime skips to the first of the next month and then advances the number of days defined in the left hand DateTime value, i.e. Date(2014, 2, 1) + 30 * oneDay. -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Apr 02 2014)
Python Projects, Consulting and Support ... http://www.egenix.com/ mxODBC.Zope/Plone.Database.Adapter ... http://zope.egenix.com/ mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
2014-04-09: PyCon 2014, Montreal, Canada ... 7 days to go 2014-04-29: Python Meeting Duesseldorf ... 27 days to go ::::: Try our mxODBC.Connect Python Database Interface for free ! :::::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/

Greg Ewing <greg.ewing@canterbury.ac.nz>:
ISO 8601 doesn't seem to define a representation for negative durations, though, so it wouldn't solve the original problem.
XSD uses ISO 8601 durations and allows a sign before the initial "P". It would appear PT1M means 60 or 61 seconds. P1D means 23, 24 or 25 hours. P1M means 28..31 days etc. Timedelta would have no option but to stick to seconds: P29389453.2345S but then, why not simply use a number: 29389453.2345 Marko

On 2014-03-28, at 17:19 , Skip Montanaro <skip@pobox.com> wrote:
(*) As an aside (that is, this belongs in a separate thread if you want to discuss it), in my opinion, attempting to support ISO 8601 formatting is pointless without the presence of an anchor datetime. Otherwise how would you know how far back "five months" or "seven years" was?
dateutil's relativedelta keeps the notion "abstract" until it's combined with an anchor datetime, at which point it's reified to a real duration[0].
If that's the case, then you might as well add the timedelta to your anchor datetime and just use datetime.strftime().
You can't even express "next month" with timedelta, since the duration of a month is not a fixed number of seconds. [0] well not exactly, a relativedelta really defines a processing pipeline on its anchor date, which allows for fun stuff like "saturday the third week of next month".
participants (10)
-
Alexander Belopolsky
-
Antoine Pitrou
-
Chris Barker
-
Fred Drake
-
Greg Ewing
-
M.-A. Lemburg
-
Marko Rauhamaa
-
Skip Montanaro
-
Steven D'Aprano
-
Xavier Morel