Skip to content

gh-114728: Fix documentation for comparison of objects in datetime module #114749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 50 additions & 68 deletions Doc/library/datetime.rst
Original file line number Diff line number Diff line change
Expand Up @@ -400,30 +400,7 @@ objects (see below).
the :func:`divmod` function. True division and multiplication of a
:class:`timedelta` object by a :class:`float` object are now supported.


Comparisons of :class:`timedelta` objects are supported, with some caveats.

The comparisons ``==`` or ``!=`` *always* return a :class:`bool`, no matter
the type of the compared object::

>>> from datetime import timedelta
>>> delta1 = timedelta(seconds=57)
>>> delta2 = timedelta(hours=25, seconds=2)
>>> delta2 != delta1
True
>>> delta2 == 5
False

For all other comparisons (such as ``<`` and ``>``), when a :class:`timedelta`
object is compared to an object of a different type, :exc:`TypeError`
is raised::

>>> delta2 > delta1
True
>>> delta2 > 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'datetime.timedelta' and 'int'
:class:`timedelta` objects support equality and order comparisons.

In Boolean contexts, a :class:`timedelta` object is
considered to be true if and only if it isn't equal to ``timedelta(0)``.
Expand Down Expand Up @@ -606,8 +583,13 @@ Supported operations:
+-------------------------------+----------------------------------------------+
| ``timedelta = date1 - date2`` | \(3) |
+-------------------------------+----------------------------------------------+
| ``date1 < date2`` | *date1* is considered less than *date2* when |
| | *date1* precedes *date2* in time. (4) |
| | ``date1 == date2`` | Equality comparison. (4) |
| | ``date1 != date2`` | |
+-------------------------------+----------------------------------------------+
| | ``date1 < date2`` | Order comparison. (5) |
| | ``date1 > date2`` | |
| | ``date1 <= date2`` | |
| | ``date1 >= date2`` | |
+-------------------------------+----------------------------------------------+

Notes:
Expand All @@ -627,15 +609,12 @@ Notes:
timedelta.microseconds are 0, and date2 + timedelta == date1 after.

(4)
:class:`date` objects are equal if they represent the same date.

(5)
*date1* is considered less than *date2* when *date1* precedes *date2* in time.
In other words, ``date1 < date2`` if and only if ``date1.toordinal() <
date2.toordinal()``. Date comparison raises :exc:`TypeError` if
the other comparand isn't also a :class:`date` object. However,
``NotImplemented`` is returned instead if the other comparand has a
:attr:`~date.timetuple` attribute. This hook gives other kinds of date objects a
chance at implementing mixed-type comparison. If not, when a :class:`date`
object is compared to an object of a different type, :exc:`TypeError` is raised
unless the comparison is ``==`` or ``!=``. The latter cases return
:const:`False` or :const:`True`, respectively.
date2.toordinal()``.

In Boolean contexts, all :class:`date` objects are considered to be true.

Expand Down Expand Up @@ -1158,8 +1137,13 @@ Supported operations:
+---------------------------------------+--------------------------------+
| ``timedelta = datetime1 - datetime2`` | \(3) |
+---------------------------------------+--------------------------------+
| ``datetime1 < datetime2`` | Compares :class:`.datetime` to |
| | :class:`.datetime`. (4) |
| | ``datetime1 == datetime2`` | Equality comparison. (4) |
| | ``datetime1 != datetime2`` | |
+---------------------------------------+--------------------------------+
| | ``datetime1 < datetime2`` | Order comparison. (5) |
| | ``datetime1 > datetime2`` | |
| | ``datetime1 <= datetime2`` | |
| | ``datetime1 >= datetime2`` | |
+---------------------------------------+--------------------------------+

(1)
Expand Down Expand Up @@ -1187,40 +1171,41 @@ Supported operations:
are done in this case.

If both are aware and have different :attr:`~.datetime.tzinfo` attributes, ``a-b`` acts
as if *a* and *b* were first converted to naive UTC datetimes first. The
as if *a* and *b* were first converted to naive UTC datetimes. The
result is ``(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None)
- b.utcoffset())`` except that the implementation never overflows.

(4)
:class:`.datetime` objects are equal if they represent the same date
and time, taking into account the time zone.

Naive and aware :class:`!datetime` objects are never equal.
:class:`!datetime` objects are never equal to :class:`date` objects
that are not also :class:`!datetime` instances, even if they represent
the same date.

If both comparands are aware and have different :attr:`~.datetime.tzinfo`
attributes, the comparison acts as comparands were first converted to UTC
datetimes except that the implementation never overflows.
:class:`!datetime` instances in a repeated interval are never equal to
:class:`!datetime` instances in other time zone.

(5)
*datetime1* is considered less than *datetime2* when *datetime1* precedes
*datetime2* in time.
*datetime2* in time, taking into account the time zone.

If one comparand is naive and the other is aware, :exc:`TypeError`
is raised if an order comparison is attempted. For equality
comparisons, naive instances are never equal to aware instances.
Order comparison between naive and aware :class:`.datetime` objects,
as well as a :class:`!datetime` object and a :class:`!date` object
that is not also a :class:`!datetime` instance, raises :exc:`TypeError`.

If both comparands are aware, and have the same :attr:`~.datetime.tzinfo` attribute, the
common :attr:`~.datetime.tzinfo` attribute is ignored and the base datetimes are
compared. If both comparands are aware and have different :attr:`~.datetime.tzinfo`
attributes, the comparands are first adjusted by subtracting their UTC
offsets (obtained from ``self.utcoffset()``).
If both comparands are aware and have different :attr:`~.datetime.tzinfo`
attributes, the comparison acts as comparands were first converted to UTC
datetimes except that the implementation never overflows.

.. versionchanged:: 3.3
Equality comparisons between aware and naive :class:`.datetime`
instances don't raise :exc:`TypeError`.

.. note::

In order to stop comparison from falling back to the default scheme of comparing
object addresses, datetime comparison normally raises :exc:`TypeError` if the
other comparand isn't also a :class:`.datetime` object. However,
``NotImplemented`` is returned instead if the other comparand has a
:attr:`~.datetime.timetuple` attribute. This hook gives other kinds of date objects a
chance at implementing mixed-type comparison. If not, when a :class:`.datetime`
object is compared to an object of a different type, :exc:`TypeError` is raised
unless the comparison is ``==`` or ``!=``. The latter cases return
:const:`False` or :const:`True`, respectively.

Instance methods:

.. method:: datetime.date()
Expand Down Expand Up @@ -1754,21 +1739,18 @@ Instance attributes (read-only):

.. versionadded:: 3.6

:class:`.time` objects support comparison of :class:`.time` to :class:`.time`,
where *a* is considered less
than *b* when *a* precedes *b* in time. If one comparand is naive and the other
is aware, :exc:`TypeError` is raised if an order comparison is attempted. For equality
comparisons, naive instances are never equal to aware instances.
:class:`.time` objects support equality and order comparisons,
where *a* is considered less than *b* when *a* precedes *b* in time.

Naive and aware :class:`!time` objects are never equal.
Order comparison between naive and aware :class:`!time` objects raises
:exc:`TypeError`.

If both comparands are aware, and have
the same :attr:`~.time.tzinfo` attribute, the common :attr:`!tzinfo` attribute is
ignored and the base times are compared. If both comparands are aware and
have different :attr:`!tzinfo` attributes, the comparands are first adjusted by
subtracting their UTC offsets (obtained from ``self.utcoffset()``). In order
to stop mixed-type comparisons from falling back to the default comparison by
object address, when a :class:`.time` object is compared to an object of a
different type, :exc:`TypeError` is raised unless the comparison is ``==`` or
``!=``. The latter cases return :const:`False` or :const:`True`, respectively.
subtracting their UTC offsets (obtained from ``self.utcoffset()``).

.. versionchanged:: 3.3
Equality comparisons between aware and naive :class:`.time` instances
Expand Down