[Python-ideas] Pythonic Dates, Times, and Deltas

14 views
Skip to first unread message

Daniel G. Taylor

unread,
Oct 13, 2010, 4:04:28 PM10/13/10
to python...@python.org
Hey,

I've recently been doing a lot of work with dates related to payment and
statistics processing at work and have run into several annoyances with
the built-in datetime, date, time, timedelta, etc classes, even when
adding in relativedelta. They are awkward, non-intuitive and not at all
Pythonic to me. Over the past year I've written up a library for making
my life a bit easier and figured I would post some information here to
see what others think, and to gauge whether or not such a library might
be PEP-worthy.

My original post about it was here:

http://programmer-art.org/articles/programming/pythonic-date

The github project page is here:

http://github.com/danielgtaylor/paodate

This is code that is and has been running in production environments for
months but may still contain bugs. I have tried to include unit tests
and ample documentation. I'd love to get some feedback and people's
thoughts.

I would also love to hear what others find is difficult or missing from
the built-in date and time handling.

Take care,

--
Daniel G. Taylor
http://programmer-art.org/

_______________________________________________
Python-ideas mailing list
Python...@python.org
http://mail.python.org/mailman/listinfo/python-ideas

Oleg Broytman

unread,
Oct 13, 2010, 4:30:08 PM10/13/10
to python...@python.org
On Wed, Oct 13, 2010 at 04:04:28PM -0400, Daniel G. Taylor wrote:
> http://programmer-art.org/articles/programming/pythonic-date

Have you ever tried mxDateTime. Do you consider it unpythonic?

Oleg.
--
Oleg Broytman http://phd.pp.ru/ p...@phd.pp.ru
Programmers don't die, they just GOSUB without RETURN.

M.-A. Lemburg

unread,
Oct 13, 2010, 4:42:27 PM10/13/10
to Daniel G. Taylor, python...@python.org
Daniel G. Taylor wrote:
> Hey,
>
> I've recently been doing a lot of work with dates related to payment and
> statistics processing at work and have run into several annoyances with
> the built-in datetime, date, time, timedelta, etc classes, even when
> adding in relativedelta. They are awkward, non-intuitive and not at all
> Pythonic to me. Over the past year I've written up a library for making
> my life a bit easier and figured I would post some information here to
> see what others think, and to gauge whether or not such a library might
> be PEP-worthy.
>
> My original post about it was here:
>
> http://programmer-art.org/articles/programming/pythonic-date
>
> The github project page is here:
>
> http://github.com/danielgtaylor/paodate
>
> This is code that is and has been running in production environments for
> months but may still contain bugs. I have tried to include unit tests
> and ample documentation. I'd love to get some feedback and people's
> thoughts.
>
> I would also love to hear what others find is difficult or missing from
> the built-in date and time handling.

mxDateTime implements most of these ideas:

http://www.egenix.com/products/python/mxBase/mxDateTime/

It's been in production use for more than 13 years now and
has proven to be very versatile in practice; YMMV, of course.

--
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source (#1, Oct 13 2010)
>>> Python/Zope Consulting and Support ... http://www.egenix.com/
>>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
________________________________________________________________________

::: Try our new 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/

Daniel G. Taylor

unread,
Oct 13, 2010, 4:59:38 PM10/13/10
to M.-A. Lemburg, python...@python.org
On 10/13/2010 04:42 PM, M.-A. Lemburg wrote:
> mxDateTime implements most of these ideas:
>
> http://www.egenix.com/products/python/mxBase/mxDateTime/
>
> It's been in production use for more than 13 years now and
> has proven to be very versatile in practice; YMMV, of course.

Hah, that is a very nice looking library. I wish I had looked into it
before writing my own. Looks like it still doesn't allow write access to
many properties in date or delta objects, but looks to have a lot of
really useful stuff in it. I'll be taking a closer look shortly.

Any idea why this hasn't made it into Python's standard library while
being around for 13 years? Seems like it would be extremely useful in
the standard distribution.

Take care,
--
Daniel G. Taylor
http://programmer-art.org/

Alexander Belopolsky

unread,
Oct 13, 2010, 5:17:36 PM10/13/10
to Daniel G. Taylor, python...@python.org
On Wed, Oct 13, 2010 at 4:04 PM, Daniel G. Taylor
<d...@programmer-art.org> wrote:
> ... and have run into several annoyances with the

> built-in datetime, date, time, timedelta, etc classes, even when adding in
> relativedelta. They are awkward, non-intuitive and not at all Pythonic to
> me.

There seems to be no shortage of blogosphere rants about how awkward
python datetime module is, but once patches are posted on the tracker
to improve it, nobody seems to be interested in reviewing them. I has
been suggested that C implementation presented a high barrier to entry
for people to get involved in datetime module development. This was
one of the reasons I pushed for including a pure python equivalent in
3.2. Unfortunately, getting datetime.py into SVN tree was not enough
to spark new interest in improving the module. Maybe this will change
with datetime.py making it into a released version.

..


> My original post about it was here:
>
> http://programmer-art.org/articles/programming/pythonic-date
>

This post is severely lacking in detail, so I cannot tell how your
library solves your announced problems, but most of them seem to be
easy with datetime:

* Make it easy to make a Date from anything - a timestamp, date,
datetime, tuple, etc.

>>> from datetime import *
>>> datetime.utcfromtimestamp(0)
datetime.datetime(1970, 1, 1, 0, 0)
>>> datetime.utcfromtimestamp(0).date()
datetime.date(1970, 1, 1)

* Make it easy to turn a Date into anything

datetime.timetuple() will convert datetime to a tuple. There is an
open ticket to simplify datetime to timestamp conversion

http://bugs.python.org/issue2736

but it is already easy enough:

>>> (datetime.now() - datetime(1970,1,1)).total_seconds()
1286989863.82536

* Make it easy and pythonic to add/subtract one or more days, weeks,
months, or years

monthdelta addition was discussed at http://bugs.python.org/issue5434,
but did not get enough interest. The rest seems to be easy enough
with timedetla.

* Make it easy to get a tuple of the start and end of the month

Why would you want this? Start of the month is easy: just date(year,
month, 1). End of the month is often unnecessary because it is more
pythonic to work with semi-open ranges and use first of the next month
instead.

Daniel G. Taylor

unread,
Oct 13, 2010, 5:45:33 PM10/13/10
to Alexander Belopolsky, python...@python.org
On 10/13/2010 05:17 PM, Alexander Belopolsky wrote:
> On Wed, Oct 13, 2010 at 4:04 PM, Daniel G. Taylor
> <d...@programmer-art.org> wrote:
>> ... and have run into several annoyances with the
>> built-in datetime, date, time, timedelta, etc classes, even when adding in
>> relativedelta. They are awkward, non-intuitive and not at all Pythonic to
>> me.
>
> There seems to be no shortage of blogosphere rants about how awkward
> python datetime module is, but once patches are posted on the tracker
> to improve it, nobody seems to be interested in reviewing them. I has
> been suggested that C implementation presented a high barrier to entry
> for people to get involved in datetime module development. This was
> one of the reasons I pushed for including a pure python equivalent in
> 3.2. Unfortunately, getting datetime.py into SVN tree was not enough
> to spark new interest in improving the module. Maybe this will change
> with datetime.py making it into a released version.

This at least sounds like some progress is being made, so that makes me
happy. I'd be glad to work on stuff if I knew it has the potential to
make a difference and be accepted upstream and if it doesn't require me
rewriting every little thing in the module. I'm not really sure where to
start as all I really want is a nice wrapper to make working with dates
seem intuitive and friendly.

> ..
>> My original post about it was here:
>>
>> http://programmer-art.org/articles/programming/pythonic-date
>>
>
> This post is severely lacking in detail, so I cannot tell how your
> library solves your announced problems, but most of them seem to be
> easy with datetime:

Yeah sorry it was mostly just a frustrated rant and then the start of my
wrapper implementation.

> * Make it easy to make a Date from anything - a timestamp, date,
> datetime, tuple, etc.
>
>>>> from datetime import *
>>>> datetime.utcfromtimestamp(0)
> datetime.datetime(1970, 1, 1, 0, 0)
>>>> datetime.utcfromtimestamp(0).date()
> datetime.date(1970, 1, 1)

Why does it not have this in the constructor? Where else in the standard
lib does anything behave like this? My solution was to just dump
whatever you want into the constructor and you get a Date object which
can be converted to anything else via simple properties.

> * Make it easy to turn a Date into anything
>
> datetime.timetuple() will convert datetime to a tuple. There is an
> open ticket to simplify datetime to timestamp conversion
>
> http://bugs.python.org/issue2736

I'll be happy when this is fixed :-)

> but it is already easy enough:
>
>>>> (datetime.now() - datetime(1970,1,1)).total_seconds()
> 1286989863.82536

This is new in Python 2.7 it seems, before you had to calculate it by
hand which was annoying to me. Now this seems okay.

> * Make it easy and pythonic to add/subtract one or more days, weeks,
> months, or years
>
> monthdelta addition was discussed at http://bugs.python.org/issue5434,
> but did not get enough interest. The rest seems to be easy enough
> with timedetla.

And that means yet another module I have to import with various
functions I have to use to manipulate an object rather than methods of
the object itself. This doesn't seem Pythonic to me...

> * Make it easy to get a tuple of the start and end of the month
>
> Why would you want this? Start of the month is easy: just date(year,
> month, 1). End of the month is often unnecessary because it is more
> pythonic to work with semi-open ranges and use first of the next month
> instead.

It's just for convenience really. For an example, I used it for querying
a database for invoices in certain date ranges and for managing e.g.
monthly recurring charges. It's just way more convenient and makes my
code very easy to read where it counts - within the complex logic
controlling when we charge credit cards. The less complex code there the
better, because typos and bugs cost real money.

Even if the tuples returned contained e.g. the first day of this and
next month instead of the last day of the month it's still useful to
have these properties that return the tuples (at least to me), as it
saves some manual work each time.

Take care,
--
Daniel G. Taylor
http://programmer-art.org/

Dag Odenhall

unread,
Oct 13, 2010, 6:16:32 PM10/13/10
to python...@python.org
On Wed, 2010-10-13 at 16:04 -0400, Daniel G. Taylor wrote:
> Hey,
>
> I've recently been doing a lot of work with dates related to payment and
> statistics processing at work and have run into several annoyances with
> the built-in datetime, date, time, timedelta, etc classes, even when
> adding in relativedelta. They are awkward, non-intuitive and not at all
> Pythonic to me. Over the past year I've written up a library for making
> my life a bit easier and figured I would post some information here to
> see what others think, and to gauge whether or not such a library might
> be PEP-worthy.
>
> My original post about it was here:
>
> http://programmer-art.org/articles/programming/pythonic-date
>
> The github project page is here:
>
> http://github.com/danielgtaylor/paodate
>
> This is code that is and has been running in production environments for
> months but may still contain bugs. I have tried to include unit tests
> and ample documentation. I'd love to get some feedback and people's
> thoughts.
>
> I would also love to hear what others find is difficult or missing from
> the built-in date and time handling.
>
> Take care,
>

Not convinced your library is very Pythonic. Why a tuple attribute
instead of having date objects be iterable so you can do tuple(Date())?

How does the fancy formats deal with locales?

Is there support for ISO 8601? Should probably be the __str__.

+1 on the general idea, though.

Alexander Belopolsky

unread,
Oct 13, 2010, 6:52:52 PM10/13/10
to Daniel G. Taylor, python...@python.org
On Wed, Oct 13, 2010 at 5:45 PM, Daniel G. Taylor
<d...@programmer-art.org> wrote:
..

>> * Make it easy to make a Date from anything - a timestamp, date,
>> datetime, tuple, etc.
>>
>>>>> from datetime import *
>>>>> datetime.utcfromtimestamp(0)
>>
>> datetime.datetime(1970, 1, 1, 0, 0)
>>>>>
>>>>> datetime.utcfromtimestamp(0).date()
>>
>> datetime.date(1970, 1, 1)
>
> Why does it not have this in the constructor?

Because "explicit is better than implicit."

> Where else in the standard lib does anything behave like this?

float.fromhex is one example.

This said, if I was starting from scratch, I would make date/datetime
constructors take a single positional argument that could be a string
(interpreted as ISO timestamp), tuple (broken down components), or
another date/datetime object. This would make date/datetime
constructors more similar to those of numeric types. I would not add
datetime(int) or datetime(float), however, because numeric timestamps
are too ambiguous and not necessary for purely calendaric
calculations.

Marco Mariani

unread,
Oct 14, 2010, 4:02:24 AM10/14/10
to python...@python.org
On 13 October 2010 23:17, Alexander Belopolsky <alexander....@gmail.com> wrote:


* Make it easy to get a tuple of the start and end of the month

Why would you want this?  Start of the month is easy: just date(year,
month, 1).  End of the month is often unnecessary because it is more
pythonic to work with semi-open ranges and use first of the next month
instead.

Except next month may well be in next year.. blah

And I don't care about pythonic ranges if I have to push the values through a BETWEEN query in SQL.

import calendar
import datetime

end = datetime.date(year, month, calendar.monthrange(year, month)[1])


Masklinn

unread,
Oct 14, 2010, 8:06:09 AM10/14/10
to Marco Mariani, python...@python.org

There's also dateutil, which exposes some ideas of mx.DateTime on top of the built-in datetime, including relativedelta.

As a result, you can get the last day of the current month by going backwards one day from the first day of next month:

>>> datetime.now().date() + relativedelta(months=+1, day=+1, days=-1)
datetime.date(2010, 10, 31)

Or (clearer order of operations):

>>> datetime.now().date() + relativedelta(months=+1, day=+1) + relativedelta(days=-1)
datetime.date(2010, 10, 31)

(note that in both cases the "+" sign is of course optional).

Parameters without an `s` postfix are absolute (day=1 sets the day of the current datetime to 1, similar to using .replace), parameters with an `s` are offsets (`days=+1` takes tomorrow).

Daniel G. Taylor

unread,
Oct 14, 2010, 2:51:05 PM10/14/10
to python...@python.org

FWIW my library does the same sort of stuff using relativedelta
internally, just sugar coats it heavily ;-)

Take care,
--
Daniel G. Taylor
http://programmer-art.org/

Daniel G. Taylor

unread,
Oct 14, 2010, 2:54:30 PM10/14/10
to python...@python.org
On 10/13/2010 06:16 PM, Dag Odenhall wrote:
> Not convinced your library is very Pythonic. Why a tuple attribute
> instead of having date objects be iterable so you can do tuple(Date())?

How do you envision this working for days, weeks, months, years? E.g.
getting the min/max Date objects for today, for next week, for this
current month, etc.

I'm very open to ideas here; I just implemented what made sense to me at
the time.

> How does the fancy formats deal with locales?

It internally uses datetime.strftime, so will behave however that
behaves with regard to locales.

> Is there support for ISO 8601? Should probably be the __str__.

Not built-in other than supporting a strftime method. This is a good
idea and I will probably add it.

> +1 on the general idea, though.

Thanks :-)

Take care,
--
Daniel G. Taylor
http://programmer-art.org/

Nathan Schneider

unread,
Oct 14, 2010, 6:01:42 PM10/14/10
to Daniel G. Taylor, python...@python.org
I'm glad to see there's interest in solving this (seems I'm not alone
in seeing date/time support as the ugly stepchild of the Python
standard library).

For what it's worth, not too long ago I ended up writing a bunch of
convenience functions to instantiate and convert between existing
date/time representations (datetime objects, time tuples, timestamps,
and string representations). The result is here, in case anyone's
interested:

http://www.cs.cmu.edu/~nschneid/docs/temporal.py

Cheers,
Nathan

Ben Finney

unread,
Oct 14, 2010, 8:51:43 PM10/14/10
to python...@python.org
"Daniel G. Taylor"
<d...@programmer-art.org> writes:

> Any idea why this hasn't made it into Python's standard library while
> being around for 13 years? Seems like it would be extremely useful in
> the standard distribution.

One barrier is that its license terms
<URL:http://www.egenix.com/products/python/mxBase/eGenix.com-Public-License-1.1.0.pdf>
are incompatible with redistribution under the terms of the Python
license.

I'd love to see the mx code released under compatible license terms, but
am not optimistic.

--
\ “He that would make his own liberty secure must guard even his |
`\ enemy from oppression.” —Thomas Paine |
_o__) |
Ben Finney

Reply all
Reply to author
Forward
0 new messages