[Python-ideas] datetime: Support infinity

64 views
Skip to first unread message

Thomas Güttler

unread,
Jan 26, 2015, 8:31:22 AM1/26/15
to Python-Ideas
Hi,

postgreSQL supports infinity for datetime:

http://www.postgresql.org/docs/current/static/datatype-datetime.html#AEN6027

{{{
infinity date, timestamp later than all other time stamps
-infinity date, timestamp earlier than all other time stamps
}}}


Mapping this to python is not possible at the moment.

See:

http://initd.org/psycopg/docs/usage.html#infinite-dates-handling

{{{
PostgreSQL can store the representation of an “infinite” date, timestamp, or interval. Infinite dates are not available
to Python, so these objects are mapped to date.max, datetime.max, interval.max. Unfortunately the mapping cannot be
bidirectional so these dates will be stored back into the database with their values, such as 9999-12-31.
}}}

I don't know the internals of the datetime module. I guess it is not possible to support infinity.

What do you think?

Thomas Güttler
_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

M.-A. Lemburg

unread,
Jan 26, 2015, 8:37:34 AM1/26/15
to Thomas Güttler, Python-Ideas
On 26.01.2015 09:24, Thomas Güttler wrote:
> Hi,
>
> postgreSQL supports infinity for datetime:
>
> http://www.postgresql.org/docs/current/static/datatype-datetime.html#AEN6027
>
> {{{
> infinity date, timestamp later than all other time stamps
> -infinity date, timestamp earlier than all other time stamps
> }}}
>
>
> Mapping this to python is not possible at the moment.
>
> See:
>
> http://initd.org/psycopg/docs/usage.html#infinite-dates-handling
>
> {{{
> PostgreSQL can store the representation of an “infinite” date, timestamp, or interval. Infinite
> dates are not available to Python, so these objects are mapped to date.max, datetime.max,
> interval.max. Unfortunately the mapping cannot be bidirectional so these dates will be stored back
> into the database with their values, such as 9999-12-31.
> }}}
>
> I don't know the internals of the datetime module. I guess it is not possible to support infinity.
>
> What do you think?

Leaving aside the question of how useful such date/time values
would be, you can use the PG work-around for supporting these
in Python as well.

In mxDateTime, we have special values which can be used for this:

>>> mx.DateTime.MaxDateTime
<mx.DateTime.DateTime object for '25200470046051299-12-31 00:00:00.00' at 7fd7c4b3b2b8>
>>> mx.DateTime.MinDateTime
<mx.DateTime.DateTime object for '-25200470046051299-01-01 00:00:00.00' at 7fd7c4b3b390>

--
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source (#1, Jan 26 2015)
>>> Python Projects, Coaching and Consulting ... http://www.egenix.com/
>>> mxODBC Plone/Zope Database Adapter ... http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
________________________________________________________________________

::::: 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/

Antoine Pitrou

unread,
Jan 26, 2015, 9:15:12 AM1/26/15
to python...@python.org
On Mon, 26 Jan 2015 09:24:07 +0100
Thomas Güttler

<guet...@thomas-guettler.de> wrote:
> Hi,
>
> postgreSQL supports infinity for datetime:
>
> http://www.postgresql.org/docs/current/static/datatype-datetime.html#AEN6027
>
> {{{
> infinity date, timestamp later than all other time stamps
> -infinity date, timestamp earlier than all other time stamps
> }}}
>
>
> Mapping this to python is not possible at the moment.
>
> See:
>
> http://initd.org/psycopg/docs/usage.html#infinite-dates-handling
>
> {{{
> PostgreSQL can store the representation of an “infinite” date, timestamp, or interval. Infinite dates are not available
> to Python, so these objects are mapped to date.max, datetime.max, interval.max. Unfortunately the mapping cannot be
> bidirectional so these dates will be stored back into the database with their values, such as 9999-12-31.
> }}}

Unless someone has a real-world use for the values of date.max,
datetime.max, interval.max, I find it rather counter-productive to not
store them back as infinities.

Adding infinities to the datetime module would probably be possible but
someone has to figure out the arithmetic rules. Do we need "not a time"
when adding infinity to -infinity?

Regards

Antoine.

Steven D'Aprano

unread,
Jan 26, 2015, 11:45:22 AM1/26/15
to python...@python.org
On Mon, Jan 26, 2015 at 10:14:23AM +0100, Antoine Pitrou wrote:
> On Mon, 26 Jan 2015 09:24:07 +0100
> Thomas Güttler <guet...@thomas-guettler.de> wrote:

> > PostgreSQL can store the representation of an “infinite” date, timestamp, or interval. Infinite dates are not available
> > to Python, so these objects are mapped to date.max, datetime.max, interval.max. Unfortunately the mapping cannot be
> > bidirectional so these dates will be stored back into the database with their values, such as 9999-12-31.

> Unless someone has a real-world use for the values of date.max,
> datetime.max, interval.max, I find it rather counter-productive to not
> store them back as infinities.

That would make them de-facto infinities that weirdly don't look like
infinities:

py> datetime.date.max
datetime.date(9999, 12, 31)


If I'm reading this page correctly, PostgreSQL supports a lot of dates
that Python doesn't, up to 5874897AD:

http://www.postgresql.org/docs/9.4/static/datatype-datetime.html

so it might not matter if 9999-12-31 gets turned into infinity rather
than treated as a normal date.


> Adding infinities to the datetime module would probably be possible but
> someone has to figure out the arithmetic rules. Do we need "not a time"
> when adding infinity to -infinity?

I shouldn't think so. The purpose of NANs in IEEE-754 maths is to allow
the programmer to delay dealing with the failed operation until the end
of the calculation. I don't think that date calculations tend to be
anywhere as complicated as mathematical ones, so it would be acceptable
to just raise an exception.

Besides, Postgresql doesn't have a "NotATime" value, so if we're trying
to match what they do, we don't need one either.


--
Steven

Antoine Pitrou

unread,
Jan 26, 2015, 12:09:56 PM1/26/15
to python...@python.org
On Mon, 26 Jan 2015 22:44:40 +1100
Steven D'Aprano <st...@pearwood.info> wrote:
> On Mon, Jan 26, 2015 at 10:14:23AM +0100, Antoine Pitrou wrote:
> > On Mon, 26 Jan 2015 09:24:07 +0100
> > Thomas Güttler <guet...@thomas-guettler.de> wrote:
>
> > > PostgreSQL can store the representation of an “infinite” date, timestamp, or interval. Infinite dates are not available
> > > to Python, so these objects are mapped to date.max, datetime.max, interval.max. Unfortunately the mapping cannot be
> > > bidirectional so these dates will be stored back into the database with their values, such as 9999-12-31.
>
> > Unless someone has a real-world use for the values of date.max,
> > datetime.max, interval.max, I find it rather counter-productive to not
> > store them back as infinities.
>
> That would make them de-facto infinities that weirdly don't look like
> infinities:

That would only make them infinities in PostgreSQL. That sounds like a
reasonable compromise for a probably little-used feature, and uncommon
values.

> > Adding infinities to the datetime module would probably be possible but
> > someone has to figure out the arithmetic rules. Do we need "not a time"
> > when adding infinity to -infinity?
>
> I shouldn't think so. The purpose of NANs in IEEE-754 maths is to allow
> the programmer to delay dealing with the failed operation until the end
> of the calculation. I don't think that date calculations tend to be
> anywhere as complicated as mathematical ones, so it would be acceptable
> to just raise an exception.

Note Numpy datetimes and timedeltas do have a concept of "NotATime".
But, yes, it's an unexpected feature.

Regards

Antoine.

Chris Barker - NOAA Federal

unread,
Jan 26, 2015, 4:32:36 PM1/26/15
to Thomas Güttler, Python-Ideas
Postgres asside, a infinity and minus infinity datetime would be
generally useful,

Useful enough that I wrote them for my code base. And early the
postgress folks think it's a useful construct.

So +1 on adding this -- and not just hacked into the postgress adapter.

My use case is thus:

We have a model that does a computation through time. Various objects
can be active for a given time period. We use datetimes to store the
active_start and active_stop. For objects that are always active up to
a particular stop time, or become active at a particular time, and
then stay active forever, we needed a way to express -infTime and
infTime.

It probably would have mostly worked to use the min and max datetime
values, but then we lose information to pass back to the user. We also
convert to-from numpy datetimes, which have a different range.

I have a sample implementation if anyone wants to look amateur it,
though I don't think it does reflected comparisons correctly. it's
really only just good enough for our use case.

-Chris

rand...@fastmail.us

unread,
Jan 26, 2015, 11:37:17 PM1/26/15
to python...@python.org
On Mon, Jan 26, 2015, at 06:44, Steven D'Aprano wrote:
> If I'm reading this page correctly, PostgreSQL supports a lot of dates
> that Python doesn't, up to 5874897AD:

Why doesn't Python support these?

You know, as long as we're talking about expanding the range of
datetime.

Alexander Belopolsky

unread,
Jan 26, 2015, 11:50:08 PM1/26/15
to rand...@fastmail.us, python-ideas

On Mon, Jan 26, 2015 at 6:36 PM, <rand...@fastmail.us> wrote:
On Mon, Jan 26, 2015, at 06:44, Steven D'Aprano wrote:
> If I'm reading this page correctly, PostgreSQL supports a lot of dates
> that Python doesn't, up to 5874897AD:

Why doesn't Python support these?

YAGNI.  4-digit year is enough for all practical purposes.

Yawar Amin

unread,
Jan 27, 2015, 3:00:46 AM1/27/15
to python...@python.org
Hi Thomas,

On 2015-01-26 03:24, Thomas Güttler wrote:
> [...]
> I don't know the internals of the datetime module. I guess it is not
> possible to support infinity.
>
> What do you think?

I think it's a great idea to support infinity dates in Python (in fact,
in any modern date handling library). If I read you right, the problem
with mapping back to Postgres is that infinity dates are being
represented in-band in Python, so they get mapped to non-infinite dates
in Postgres.

The solution is to represent infinity dates as out-of-band values. My
take on this is to represent them as subtypes of datetime and handle
those subtypes appropriately. A rough (but working) sketch of the idea:

import datetime as dt

class datetime_ext(dt.datetime):
def __new__(cls, *args, **kwargs):
return dt.datetime.__new__(cls, *args, **kwargs)

# Getting the infinity dates.
@staticmethod
def pos_inf(): return datetime_inf(1)
@staticmethod
def neg_inf(): return datetime_inf(-1)

# More fun names.
@staticmethod
def big_bang(): return datetime_ext.neg_inf()
@staticmethod
def big_crunch(): return datetime_ext.pos_inf()

# Now the fun part.
def _are_we_inf(self, other):
return (
isinstance(self, datetime_inf),
isinstance(other, datetime_inf)
)

def __lt__(self, other):
awi = self._are_we_inf(other)

if awi == (True, True): return self.sign < other.sign
elif awi == (False, True): return other.sign > 0
elif awi == (True, False): return self.sign < 0
else: return self < other

def __gt__(self, other):
awi = self._are_we_inf(other)

if awi == (True, True): return self.sign > other.sign
elif awi == (False, True): return other.sign < 0
elif awi == (True, False): return self.sign > 0
else: return self > other

def __eq__(self, other):
awi = self._are_we_inf(other)

if awi == (True, True): return self.sign == other.sign
elif awi == (False, False): return self == other
else: return False

def __ne__(self, other): return not (self == other)
def __le__(self, other): return (self < other) or (self == other)
def __ge__(self, other): return (self > other) or (self == other)

class datetime_inf(datetime_ext):
def __new__(cls, sign):
# The numbers passed in to the constructor are meaningless; they
# should never be used.
retval = datetime_ext.__new__(cls, 1, 1, 1)
retval.sign = sign

return retval

def _raise_err(self): raise TypeError("Infinity date")
def date(self): return datetime_inf(self.sign)
def time(self): _raise_err()
def timetz(self): _raise_err()
def replace(self): _raise_err()
def astimezone(self): _raise_err()
# ... all the others ...

# All True:
print(datetime_ext.big_bang() == datetime_ext.big_bang())
print(datetime_ext.big_crunch() == datetime_ext.big_crunch())
print(datetime_ext.big_bang() < datetime_ext.big_crunch())
print(datetime_ext.big_crunch() > datetime_ext.big_bang())
print(datetime_ext.big_bang() < dt.datetime.today())
print(datetime_ext.big_crunch() > dt.datetime.today())

# Added bonuses (boni?):
print(dt.datetime.max < datetime_ext.big_crunch())
print(dt.datetime.min > datetime_ext.big_bang())

So the basic idea here is to override the comparison methods to treat
the datetime_inf type specially. The implementation of datetime_inf
isn't particularly elegant, but I think it works for its intended
purpose.

Now with these, I'm pretty sure you can write an InfDateWrapper class
that checks for datetime_ext.big_bang() and datetime_ext.big_crunch()
and returns the corresponding Postgres '-infinity::date' and
'infinity::date'; and that the mapping will be fully bidirectional.

And as I said, I believe something like this should be added to the
Python stdlib. If no one has a better implementation I'll start working
on a proposal.

Regards,

Yawar


signature.asc

Thomas Güttler

unread,
Jan 27, 2015, 10:43:43 AM1/27/15
to python...@python.org
...

>
> And as I said, I believe something like this should be added to the
> Python stdlib. If no one has a better implementation I'll start working
> on a proposal.

Great! At the moment I have no better implementation. We have a dirty work around
in our code base, and a solution in Python stdlib would be very good.

Up to now we must use Python 2.7, so a backport (like subprocess32) would be needed.
Is this possible?

Please CC your proposal to me.

Regards,

Ben Finney

unread,
Jan 27, 2015, 10:42:49 PM1/27/15
to python...@python.org
Antoine Pitrou <soli...@pitrou.net>
writes:

> Unless someone has a real-world use for the values of date.max,
> datetime.max, interval.max, I find it rather counter-productive to not
> store them back as infinities.

The values are useful to know exactly how far in the future one can
store date values in Python. It is important that this be discoverable
programmatically because the maximum values might change in future
versions of the ‘datetime’ library.

Because it remains true (and presumably will continue to be true) that
the maximum value is *not* infinity, it is important that the following
real-world cases are distinct:

* Query the ‘datetime’ library for the largest (furthest-in-the-future)
value that it can handle.

* Store a value explicitly meaning “infinitely far in the future” or
“infinitely far in the past” compared to any actual date or datetime
value.

I have needed both, sometimes in the same program.

An example is to be able to represent the timestamp field of a journal
entry that is still being composed and has not yet gained a timestamp.
‘None’ is not sufficient, because it must be “in the future” compared to
any actual point in time, even greater than ‘datetime.date.max’.

To use the same value attempting to represent both “maximum” and
“infinite” is a fragile, and needlessly confusing, hack. Having distinct
“infinitely far in the future” and “infinitely far in the past” values,
that are *not* themselves particular points on the timeline, would be a
valuable addition for this reason.

> Adding infinities to the datetime module would probably be possible but
> someone has to figure out the arithmetic rules. Do we need "not a time"
> when adding infinity to -infinity?

Adding dates (or datetimes) is not a valid operation today, so I don't
see why we would need to change behaviour there.

--
\ “This world in arms is not spending money alone. It is spending |
`\ the sweat of its laborers, the genius of its scientists, the |
_o__) hopes of its children.” —Dwight Eisenhower, 1953-04-16 |
Ben Finney

Antoine Pitrou

unread,
Jan 27, 2015, 10:48:00 PM1/27/15
to python...@python.org
On Wed, 28 Jan 2015 09:42:16 +1100
Ben Finney <ben+p...@benfinney.id.au> wrote:
> Antoine Pitrou <soli...@pitrou.net>
> writes:
>
> > Unless someone has a real-world use for the values of date.max,
> > datetime.max, interval.max, I find it rather counter-productive to not
> > store them back as infinities.
>
> The values are useful to know exactly how far in the future one can
> store date values in Python. It is important that this be discoverable
> programmatically because the maximum values might change in future
> versions of the ‘datetime’ library.

So what? Again, the values wouldn't change in Python. It would only be
the PostgreSQL mapping that would change.

> > Adding infinities to the datetime module would probably be possible but
> > someone has to figure out the arithmetic rules. Do we need "not a time"
> > when adding infinity to -infinity?
>
> Adding dates (or datetimes) is not a valid operation today, so I don't
> see why we would need to change behaviour there.

We're talking about both datetimes and timestamps here. Please follow.

Regards

Antoine.

Alexander Belopolsky

unread,
Jan 27, 2015, 10:59:55 PM1/27/15
to Antoine Pitrou, python-ideas

On Tue, Jan 27, 2015 at 5:47 PM, Antoine Pitrou <soli...@pitrou.net> wrote:
> Adding dates (or datetimes) is not a valid operation today, so I don't
> see why we would need to change behaviour there.

We're talking about both datetimes and timestamps here. Please follow.

I think Antoine meant "timedeltas".  Having a date infinity necessitates an infinite timedelta to represent a difference between a finite and an infinite date.

While we cannot add dates, it is still a valid question what the result of subtracting an infinite date from itself should be.  If we make it timedelta(0) then date.inf is not that different from date.max.

Antoine Pitrou

unread,
Jan 27, 2015, 11:03:51 PM1/27/15
to python...@python.org
On Tue, 27 Jan 2015 17:59:13 -0500
Alexander Belopolsky
<alexander....@gmail.com> wrote:
> On Tue, Jan 27, 2015 at 5:47 PM, Antoine Pitrou <soli...@pitrou.net> wrote:
>
> > > Adding dates (or datetimes) is not a valid operation today, so I don't
> > > see why we would need to change behaviour there.
> >
> > We're talking about both datetimes and timestamps here. Please follow.
>
>
> I think Antoine meant "timedeltas".

Yup, indeed. My bad.
And for the record:

>>> import numpy as np
>>> np.timedelta64(0) / np.timedelta64(0)
__main__:1: RuntimeWarning: invalid value encountered in true_divide
nan
>>> np.timedelta64(0) / np.timedelta64(0) == np.timedelta64('nat')
True
>>> type(np.timedelta64('nat'))
<class 'numpy.timedelta64'>

Ben Finney

unread,
Jan 27, 2015, 11:04:39 PM1/27/15
to python...@python.org
Antoine Pitrou <soli...@pitrou.net>
writes:

> On Wed, 28 Jan 2015 09:42:16 +1100
> Ben Finney <ben+p...@benfinney.id.au> wrote:

> > The [minimum and maximum] values are useful to know exactly how far
> > in the future [and past] one can store date values in Python. It is


> > important that this be discoverable programmatically because the

> > maximum [or minimum] values might change in future versions of the


> > ‘datetime’ library.
>
> So what? Again, the values wouldn't change in Python. It would only be
> the PostgreSQL mapping that would change.

That's the point, though. We should at least allow for “datetime.date.max”
and “datetime.date.infinitely_far_in_the_future” to be distinct, and
allow for the former to change value in a backward-compatible way.

So the maxima and minima should map to their specific points in time in
both directions between PostgreSQL and Python.

“Maximum” does not mean “infinite”, and conflating them robs us not only
of the backward-compatible ability to change the maximum in future, but
also of the ability to later add a distinct value to represent infinity.

--
\ “You don't need a book of any description to help you have some |
`\ kind of moral awareness.” —Dr. Francesca Stavrakoloulou, bible |
_o__) scholar, 2011-05-08 |
Ben Finney

Chris Barker

unread,
Jan 27, 2015, 11:06:19 PM1/27/15
to Antoine Pitrou, Python-Ideas
On Tue, Jan 27, 2015 at 2:47 PM, Antoine Pitrou <soli...@pitrou.net> wrote:
On Wed, 28 Jan 2015 09:42:16 +1100
Ben Finney <ben+p...@benfinney.id.au> wrote:
 
So what? Again, the values wouldn't change in Python. It would only be
the PostgreSQL mapping that would change.

infinity times would be useful outside of the PostgreSQL mapping.

> > Adding infinities to the datetime module would probably be possible but
> > someone has to figure out the arithmetic rules. Do we need "not a time"
> > when adding infinity to -infinity?

not_a_timedelta, I suppose, or simply disallow it.

But if you do allow it -- then following the rules for floating point inf, -inf, and NaN would make sense.

-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....@noaa.gov

Steven D'Aprano

unread,
Jan 28, 2015, 12:47:37 AM1/28/15
to python...@python.org
The obvious question is "What does Postgresql do?"

Same for use-cases, which Antoine asked for. The primary use-case is to
improve compatibility with Postgresql while still treating the full
range of dates up to and including date.max as regular dates.

I'm not convinced that numpy is the right library to follow here. Unless
there are cases where you would perform calculations with Not-A-Time, an
exception would probably be better suited.

--
Steve

Antoine Pitrou

unread,
Jan 28, 2015, 1:26:03 AM1/28/15
to python...@python.org
On Wed, 28 Jan 2015 11:46:38 +1100
Steven D'Aprano <st...@pearwood.info> wrote:
>
> The obvious question is "What does Postgresql do?"
>
> Same for use-cases, which Antoine asked for. The primary use-case is to
> improve compatibility with Postgresql while still treating the full
> range of dates up to and including date.max as regular dates.
>
> I'm not convinced that numpy is the right library to follow here. Unless
> there are cases where you would perform calculations with Not-A-Time, an
> exception would probably be better suited.

I should add that I mentioned Numpy as a datapoint, but
knowledgeable people I talked to generally agreed that Numpy's
datetime64/timedelta64 design isn't very good (actually, it has an
even wonkier feature that's only exposed internally AFAIK). So
"Not-A-Time" need not necessarily be implemented in the stdlib ;)

Regards

Antoine.

Yawar Amin

unread,
Jan 28, 2015, 3:24:58 AM1/28/15
to python...@python.org
Hi,

On 2015-01-27 18:04, Chris Barker wrote:
> On Tue, Jan 27, 2015 at 2:47 PM, Antoine Pitrou <soli...@pitrou.net> wrote:
> [...]

> > > Adding infinities to the datetime module would probably be
> > > possible but
> > > someone has to figure out the arithmetic rules. Do we need
> > > "not a time"
> > > when adding infinity to -infinity?

> not_a_timedelta, I suppose, or simply disallow it.
>
> But if you do allow it -- then following the rules for floating point
> inf, -inf, and NaN would make sense.

Adding datetime.neg_inf() and datetime.pos_inf() should return
datetime.now().

Regards,

Yawar


signature.asc

Yawar Amin

unread,
Jan 28, 2015, 3:29:54 AM1/28/15
to python...@python.org
Hi Chris,

On 2015-01-26 11:31, Chris Barker - NOAA Federal wrote:
> [...]
> I have a sample implementation if anyone wants to look amateur it,
> though I don't think it does reflected comparisons correctly. it's
> really only just good enough for our use case.

I'd like to take a look. Can you send it to me, or post it somewhere?

Regards,

Yawar

Alexander Belopolsky

unread,
Jan 28, 2015, 4:01:07 AM1/28/15
to Yawar Amin, python-ideas

On Tue, Jan 27, 2015 at 10:24 PM, Yawar Amin <yawar...@gmail.com> wrote:
Adding datetime.neg_inf() and datetime.pos_inf() should return
datetime.now().

Nah, it should return datetime.utcfromtimestamp(random.randint(-2**32, 2**32)).  Anything else would be a heresy!

Chris Barker

unread,
Jan 28, 2015, 5:18:44 AM1/28/15
to Yawar Amin, Python-Ideas
On Tue, Jan 27, 2015 at 7:29 PM, Yawar Amin <yawar...@gmail.com> wrote:
On 2015-01-26 11:31, Chris Barker - NOAA Federal wrote:
> I have a sample implementation if anyone wants to look at it,

> though I don't think it does reflected comparisons correctly. it's
> really only just good enough for our use case.

I'd like to take a look. Can you send it to me, or post it somewhere?

Yawar Amin

unread,
Jan 29, 2015, 2:56:52 AM1/29/15
to Chris Barker, Python-Ideas
On 2015-01-28 00:17, Chris Barker wrote:
> [...]
Cool, the comparison operator logic looks very similar to mine:

https://groups.google.com/d/msg/python-ideas/G3jeWoa6h14/ELpDLFu28QcJ

I believe the ideal design is the following type hierarchy:

datetime_base
datetime_neg_inf
datetime_pos_inf
datetime

But in the interests of pragmatism, I think this one can be made to
work:

datetime
datetime_neg_inf
datetime_pos_inf

So we'd keep using the existing datetime type, and whenever we need
infinity datetimes we'd just pass in the appropriate subtypes. The
advantage to this is that we don't have to switch everything over to
using a new derived type--just use the normal datetime for the majority
of cases where we don't need inifinity dates.

Regards,

Yawar


signature.asc

Chris Barker

unread,
Jan 29, 2015, 7:05:38 AM1/29/15
to Yawar Amin, Python-Ideas
On Wed, Jan 28, 2015 at 6:55 PM, Yawar Amin <yawar...@gmail.com> wrote:
Cool, the comparison operator logic looks very similar to mine:

https://groups.google.com/d/msg/python-ideas/G3jeWoa6h14/ELpDLFu28QcJ


Did you get it to work both ways? i.e.

datetime.neg_inf < datetime.now()

and

datetime.now() > datetime.neg_inf

I had trouble with that, because the regular datetime doesn't know how to compare itself to a neg_inf object.
 
I believe the ideal design is the following type hierarchy:

    datetime_base
      datetime_neg_inf
      datetime_pos_inf
      datetime

But in the interests of pragmatism, I think this one can be made to
work:

    datetime
      datetime_neg_inf
      datetime_pos_inf

yup -- should work.

and you could add class methods to the datetime object, so you could do:

datetime.neg_inf()
and
datetime.pos_inf()
 
The
advantage to this is that we don't have to switch everything over to
using a new derived type--just use the normal datetime for the majority
of cases where we don't need inifinity dates.

And it could be a third part package, too. -- particularly good for backward compatibility.

-Chris

rand...@fastmail.us

unread,
Jan 29, 2015, 6:11:19 PM1/29/15
to python...@python.org
On Thu, Jan 29, 2015, at 02:04, Chris Barker wrote:
> I had trouble with that, because the regular datetime doesn't know how to
> compare itself to a neg_inf object.

Works fine on python 3.3. Python 2 raises exception from __lt__, python
3 returns NotImplemented.

Chris Barker

unread,
Jan 29, 2015, 7:10:33 PM1/29/15
to rand...@fastmail.us, Python-Ideas
On Thu, Jan 29, 2015 at 10:10 AM, <rand...@fastmail.us> wrote:
Works fine on python 3.3.

Good.
 
Python 2 raises exception from __lt__,

yeah, that's what I got -- we're on 2 for now. You'd think there wold be a way to do it -- but I don't see a "reflected" versions of the comparison operators.

But for anything new, it'd be in 3.5+ anyway, so sounds like we're good.

Though it would be nice to have it as a recipe for older versions.

-Chris

Ethan Furman

unread,
Jan 29, 2015, 7:15:27 PM1/29/15
to python...@python.org
On 01/29/2015 11:09 AM, Chris Barker wrote:
> On Thu, Jan 29, 2015 at 10:10 AM, random832 wrote:
>>
>> Python 2 raises exception from __lt__,
>
> yeah, that's what I got -- we're on 2 for now. You'd think there wold
> be a way to do it -- but I don't see a "reflected" versions of the
> comparison operators.

Raising an exception was a bug. The comparison operators are their own reflection.

--
~Ethan~

signature.asc

Chris Barker

unread,
Jan 29, 2015, 7:20:10 PM1/29/15
to Ethan Furman, Python-Ideas
On Thu, Jan 29, 2015 at 11:14 AM, Ethan Furman <et...@stoneleaf.us> wrote:
>> Python 2 raises exception from __lt__,
>
> yeah, that's what I got -- we're on 2 for now. You'd think there wold
> be a way to do it -- but I don't see a "reflected" versions of the
> comparison operators.

Raising an exception was a bug.  The comparison operators are their own reflection.

So does that mean it could be fixed in 2.* ? (or already has been?) 

-Chris

Yawar Amin

unread,
Jan 29, 2015, 7:21:03 PM1/29/15
to Chris Barker, Python-Ideas
Hi Chris, sorry for the top-posting; replying from my phone.

My test implementation works for me on Python 2.7, see http://repl.it/9Wz

Notice especially the last few assertions, where normal datetime objects are on the LHS.

Regards,

Yawar

rand...@fastmail.us

unread,
Jan 29, 2015, 7:23:57 PM1/29/15
to python...@python.org
Or, more precisely, they are *each other's* reflection (__gt__ being the
reflection of __lt__).

This works fine in 2.7 for types that properly return NotImplemented.
This is just a bug in Python 2's datetime module.

Skip Montanaro

unread,
Jan 29, 2015, 7:30:25 PM1/29/15
to Chris Barker, Python-Ideas

On Thu, Jan 29, 2015 at 1:18 PM, Chris Barker <chris....@noaa.gov> wrote:
So does that mean it could be fixed in 2.* ? (or already has been?)

That it hasn't been fixed by now suggests that the core developers felt it would break more than it would repair. Might be worth scanning the relevant tracker issue(s) or searching the python-dev list archives.

Skip

rand...@fastmail.us

unread,
Jan 29, 2015, 7:30:27 PM1/29/15
to python...@python.org
On Thu, Jan 29, 2015, at 14:19, Yawar Amin wrote:
> Hi Chris, sorry for the top-posting; replying from my phone.
>
> My test implementation works for me on Python 2.7, see http://repl.it/9Wz
>
> Notice especially the last few assertions, where normal datetime objects
> are on the LHS.

How'd you do that? Does python always know to use the derived class's
operators when working with a base class and a derived class?

Ethan Furman

unread,
Jan 29, 2015, 7:33:08 PM1/29/15
to python...@python.org
On 01/29/2015 11:23 AM, rand...@fastmail.us wrote:
> On Thu, Jan 29, 2015, at 14:14, Ethan Furman wrote:
>> On 01/29/2015 11:09 AM, Chris Barker wrote:
>>> On Thu, Jan 29, 2015 at 10:10 AM, random832 wrote:
>>>>
>>>> Python 2 raises exception from __lt__,
>>>
>>> yeah, that's what I got -- we're on 2 for now. You'd think there wold
>>> be a way to do it -- but I don't see a "reflected" versions of the
>>> comparison operators.
>>
>> Raising an exception was a bug. The comparison operators are their own
>> reflection.
>
> Or, more precisely, they are *each other's* reflection (__gt__ being the
> reflection of __lt__).

Yes, much better phrasing, thank you.

--
~Ethan~

signature.asc

Chris Barker

unread,
Jan 29, 2015, 7:36:42 PM1/29/15
to Yawar Amin, Python-Ideas
On Thu, Jan 29, 2015 at 11:19 AM, Yawar Amin <yawar...@gmail.com> wrote:
My test implementation works for me on Python 2.7, see http://repl.it/9Wz

cool site! 

And yes, it does appear to work.

However the subclassing approach is really weird, as the infinite datetimes have a year, month, day, etc -- that strikes me as ripe for error. That's why I didn't subclass, but just had them e independent.

Another option would be to override just about everything...

-Chris

Ethan Furman

unread,
Jan 29, 2015, 7:37:09 PM1/29/15
to python...@python.org
On 01/29/2015 11:29 AM, rand...@fastmail.us wrote:
> On Thu, Jan 29, 2015, at 14:19, Yawar Amin wrote:
>> Hi Chris, sorry for the top-posting; replying from my phone.
>>
>> My test implementation works for me on Python 2.7, see http://repl.it/9Wz
>>
>> Notice especially the last few assertions, where normal datetime objects
>> are on the LHS.
>
> How'd you do that? Does python always know to use the derived class's
> operators when working with a base class and a derived class?

I can't find the reference, but yes.

So the broken datetime behavior would only be noticed by a non-datetime derived class.

--
~Ethan~

signature.asc

Chris Barker

unread,
Jan 29, 2015, 7:41:13 PM1/29/15
to Ethan Furman, Python-Ideas
On Thu, Jan 29, 2015 at 11:36 AM, Ethan Furman <et...@stoneleaf.us> wrote:
> How'd you do that? Does python always know to use the derived class's
> operators when working with a base class and a derived class?

I can't find the reference, but yes.

So the broken datetime behavior would only be noticed by a non-datetime derived class.

got it -  that's why my version didn't work.

So this is a good reason to derive from datetime. but I'd make sure to override everything that doesn't make sense.

-Chris


 
--
~Ethan~



_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Yawar Amin

unread,
Jan 29, 2015, 7:56:09 PM1/29/15
to Chris Barker, Python-Ideas
Hi Chris, agreed, it's not great to have years, months and dates inside the infinity datetimes. That's why ideally datetime, datetime_neg_inf and datetime_pos_inf should have been sibling types deriving from datetime_base.

I'll try to explore making this change in the stdlib ad seeing if that breaks th vs really badly.
Reply all
Reply to author
Forward
0 new messages