comparing datetime with date

D

Donnal Walter

I was very surprised to discover that
True

How can these two objects be considered equal? Is there a *general* way
to test for date != datetime as well as 4.5 != 4.6?

Donnal Walter
Arkansas Children's Hospital
 
P

Peter Hansen

Donnal said:
I was very surprised to discover that

True

How can these two objects be considered equal?

Guessing:

In http://docs.python.org/lib/datetime-datetime.html
it says this """Note: In order to stop comparison from falling back to
the default scheme of comparing object addresses, datetime comparison
normally raises TypeError if the other comparand isn't also a datetime
object. However, NotImplemented is returned instead if the other
comparand has a timetuple attribute. This hook gives other kinds of date
objects a chance at implementing mixed-type comparison. """
(the docs for the date class say the same).

I suspect this means simply that datetime.date *does* use this
behaviour to provide a mixed-type comparison that makes sense,
to _it_.
> Is there a *general* way
> to test for date != datetime as well as 4.5 != 4.6?

Couldn't say, sorry.

-Peter
 
D

Diez B. Roggisch

Donnal said:
I was very surprised to discover that

True

I think thats perfectly legal - a date object should care only about if the
object it is compared to contains some sort of valid date information, and
restrict its comparision to that.

The matter is that you try to compare two different things here - so its up
to the implementation if how it deals with this, as there is no canonical
way to compare two things that aren't even structural equivalent.

The current implementation chose one way to do it - and thats as good as any
other one could think of, and certainly has some convenience advantage on
its side.
How can these two objects be considered equal? Is there a *general* way
to test for date != datetime as well as 4.5 != 4.6?

Try making a datetime-object from your date, with zeros for the time part -
then you'll get what you want.
 
P

Peter Hansen

Diez said:
Try making a datetime-object from your date, with zeros for the time part -
then you'll get what you want.

While trying to provide my first answer, I thought of suggesting
this, but there doesn't appear to be a simple way of doing it.
It looked like the following was the best I could do (where 'x'
is a datetime.date object):

z = datetime.datetime(x.year, x.month, x.day)

I just found timetuple(), which means this could be written
in the awful form:

z = datetime.datetime(*x.timetuple()[:3])

but that's hardly better, and definitely more inscrutable.

To answer Donnal's question above, however, it appears this
might be a reasonable approach:
False

Not sure there's a better approach readily available.

-Peter
 
T

Tim Peters

[Diez B. Roggisch]
[Peter Hansen]
While trying to provide my first answer, I thought of suggesting
this, but there doesn't appear to be a simple way of doing it.

datetime.datetime has a class constructor for building a datetime out
of a date and a time, so this can be done via a simple one-liner:
 
D

Donnal Walter

Peter said:
Diez said:
Try making a datetime-object from your date, with zeros for the time
part -
then you'll get what you want.


While trying to provide my first answer, I thought of suggesting
this, but there doesn't appear to be a simple way of doing it.
It looked like the following was the best I could do (where 'x'
is a datetime.date object):

z = datetime.datetime(x.year, x.month, x.day)

I just found timetuple(), which means this could be written
in the awful form:

z = datetime.datetime(*x.timetuple()[:3])

but that's hardly better, and definitely more inscrutable.

To answer Donnal's question above, however, it appears this
might be a reasonable approach:
False

Not sure there's a better approach readily available.

-Peter

Thanks for the suggestions. I have decided *not* to store date/datetime
objects, but rather store the corresponding time tuples: 3-tuple for
date only, and 5- or 6-tuple for date and time, depending on whether or
not seconds are given). Then the following method notifies observers if
a simple date is changed to the date with time (just like number changes
and string changes).

def set(self, value):
if value != self._state: # now this works!
self._state = value
self.notify_observers(self)

This means, of course, that if an observer wants to calculate a
TimeDelta, the corresponding datetimes have to be constructed, but I
don't think this is too inefficient.

time1 = datetime.datetime(*time1.get()) # 3-, 5-, or 6-tuple
time2 = datetime.datetime(*time2.get())
tdelta = time2 - time1

The observer object (and user) would need to understand the loss of
precision when times are not actually given, but at least the relevant
methods work regardless.

Thanks again,

Donnal Walter
Arkansas Children's Hospital
 
G

Graeme Matthew

This is very interesting because if you continue further and coerce both to
strings you get:

Even though there string values are different they still match?

If we perform a CRC (Cyclic Redundancy Check) i.e compute a one way hash:

import binasciiFalse

So this confirms that there values do differ yet a comparision using ==
returns True?

All i can assume is that when a Date / DateTime comparision is made the
'lowest denominator' i.e Date is used but I may be very wrong

Will watch this thread closely
 
S

Sam Holden

This is very interesting because if you continue further and coerce both to
strings you get:

True

Of course if you actually do:
Even though there string values are different they still match?

No, they only matched becuase you compared y with y :)
 
G

Graeme Matthew

yes it was late, apologies therefore a simple way to solve this problem
would be:

str(x) == str(y)

:=-)
 
P

Pierre Fortin

This is very interesting because if you continue further and coerce both
to strings you get:
of course: ^ ^ :^)
Even though there string values are different they still match?

Looks like date and datetime have 3 arguments and minimum 3 args
respectively, so the comparison appears to simply use the minimum data
available... when given more data to compare, we get:
False


All i can assume is that when a Date / DateTime comparision is made the
'lowest denominator' i.e Date is used but I may be very wrong

I agree...
 
P

Peter Hansen

Graeme said:
Even though there string values are different they still match?

If we perform a CRC (Cyclic Redundancy Check) i.e compute a one way hash:

import binascii


False

So this confirms that there values do differ yet a comparision using ==
returns True?

I'm unclear why you think this binascii.crc32 stuff has anything
to do with anything. The strings are different, as you showed.

Ignoring collisions (which would be rare) two different strings
are going to have different CRC32 values. Did you confuse yourself
somewhere along the way?

(Now if the CRC values for those two strings were the same, *that*
would indeed be interesting.)

-Peter
 
P

Peter Maas

Diez said:
The matter is that you try to compare two different things here - so its up
to the implementation if how it deals with this, as there is no canonical
way to compare two things that aren't even structural equivalent.

datetime and date are different by implementation, not by meaning. Both
are time intervals.
 
D

Donnal Walter

Peter said:
datetime and date are different by implementation, not by meaning. Both
are time intervals.

Actually both are time *points* (as opposed to time intervals) with
differing degress of precision. My problem is somewhat akin to comparing
4.0 with 4.00001. For some purposes it might be appropriate to consider
these two values to be the same, but I need for them to be different.

Donnal Walter
Arkansas Children's Hospital
 
D

Diez B. Roggisch

The matter is that you try to compare two different things here - so its
datetime and date are different by implementation, not by meaning. Both
are time intervals.

Neither of them is - they are discrete points in time, with different
resolution.

There is a difference in saying "vacation starts at 9/9/2004" or "lets meet
at 9/9/2004, 12:00" - even to non-programmers.
 
P

Peter Maas

Diez said:
Neither of them is - they are discrete points in time, with different
resolution.

There is a difference in saying "vacation starts at 9/9/2004" or "lets meet
at 9/9/2004, 12:00" - even to non-programmers.

There are several meanings. A date is valid for 24 hours. If you think
of a date as point in time there is usually a time part of 0:00 silently
added. No matter which meaning you prefer: Evaluating 2004-09-16 ==
2004-09-16T3:14 as true is very surprising.

You could as well say that int(3) == 3.14 is true (disregarding the
fractional part of the second operand).
 
D

Diez B. Roggisch

There are several meanings. A date is valid for 24 hours. If you think
of a date as point in time there is usually a time part of 0:00 silently
added. No matter which meaning you prefer: Evaluating 2004-09-16 ==
2004-09-16T3:14 as true is very surprising.

Its a matter of taste - I've seen plenty of worarounds in my life -
especially in database-related code - that exactly tries to create that
behaviour of forced equality. The reason beeing that there are not two
distinct types date and datetime, but only the latter.

A date is all the times from 0:00 to 23:59 only if you you view it with the
greater resolution of datetime - if you restrict yourself to dates, its one
point.

I don't say that your POV isn't correct - but neither is the one currently
implemented: If you compare apples to oranges, it depends on what you focus
on: If you're strict, you'd say they're different. If you focus on them
beeing fruits, you might say they are equal.

We deal here with ternary logic - True, False and Bottom/Failure. One can
very well argue, that your example

int(3) == 3.14

shouldn't work at all, but produce an exception, forcing the programmer to
think about explicit conversion. Then you are in ADA-World :)

But as python tries to be a convenient language, they silently are coerced
to maching types and compared then. The same happened here - with a for
some people surprising outcome, for others it makes life much easier.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,206
Messages
2,571,069
Members
47,677
Latest member
MoisesKoeh

Latest Threads

Top