From 073c4d145781aacd571091c87b359220b254e8bb Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 30 Jan 2024 14:02:54 +0200 Subject: [PATCH 1/3] gh-114728: Fix documentation for comparison of objects in datetime module --- Doc/library/datetime.rst | 125 ++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 68 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 4ff049c8709289..3441ced6c93089 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -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 "", line 1, in - 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)``. @@ -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: @@ -627,15 +609,20 @@ Notes: timedelta.microseconds are 0, and date2 + timedelta == date1 after. (4) + :class:`date` objects are equal if they represent the same date. + + :class:`!date` objects that are not also :class:`.datetime` instances + are never equal to :class:`!datetime` objects, even 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()``. + + Order comparison between a :class:`!date` object that is not also a + :class:`.datetime` instance and a :class:`!datetime` object raises + :exc:`TypeError`. In Boolean contexts, all :class:`date` objects are considered to be true. @@ -1158,8 +1145,12 @@ Supported operations: +---------------------------------------+--------------------------------+ | ``timedelta = datetime1 - datetime2`` | \(3) | +---------------------------------------+--------------------------------+ -| ``datetime1 < datetime2`` | Compares :class:`.datetime` to | -| | :class:`.datetime`. (4) | +| ``datetime1 == datetime2`` | Equality comparison. (4) | ++---------------------------------------+--------------------------------+ +| ``datetime1 < datetime2`` | Order comparison. (5) | +| ``datetime1 > datetime2`` | | +| ``datetime1 <= datetime2`` | | +| ``datetime1 >= datetime2`` | | +---------------------------------------+--------------------------------+ (1) @@ -1187,40 +1178,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() @@ -1754,21 +1746,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 From a33568907f3eb1582d0433f60c75055217d56dc9 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 30 Jan 2024 15:33:58 +0200 Subject: [PATCH 2/3] Fix multiline cells. --- Doc/library/datetime.rst | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 3441ced6c93089..d601120024b63d 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -583,13 +583,13 @@ Supported operations: +-------------------------------+----------------------------------------------+ | ``timedelta = date1 - date2`` | \(3) | +-------------------------------+----------------------------------------------+ -| ``date1 == date2`` | Equality comparison. (4) | -| ``date1 != date2`` | | +| | ``date1 == date2`` | Equality comparison. (4) | +| | ``date1 != date2`` | | +-------------------------------+----------------------------------------------+ -| ``date1 < date2`` | Order comparison. (5) | -| ``date1 > date2`` | | -| ``date1 <= date2`` | | -| ``date1 >= date2`` | | +| | ``date1 < date2`` | Order comparison. (5) | +| | ``date1 > date2`` | | +| | ``date1 <= date2`` | | +| | ``date1 >= date2`` | | +-------------------------------+----------------------------------------------+ Notes: @@ -1145,12 +1145,13 @@ Supported operations: +---------------------------------------+--------------------------------+ | ``timedelta = datetime1 - datetime2`` | \(3) | +---------------------------------------+--------------------------------+ -| ``datetime1 == datetime2`` | Equality comparison. (4) | +| | ``datetime1 == datetime2`` | Equality comparison. (4) | +| | ``datetime1 != datetime2`` | | +---------------------------------------+--------------------------------+ -| ``datetime1 < datetime2`` | Order comparison. (5) | -| ``datetime1 > datetime2`` | | -| ``datetime1 <= datetime2`` | | -| ``datetime1 >= datetime2`` | | +| | ``datetime1 < datetime2`` | Order comparison. (5) | +| | ``datetime1 > datetime2`` | | +| | ``datetime1 <= datetime2`` | | +| | ``datetime1 >= datetime2`` | | +---------------------------------------+--------------------------------+ (1) From 2f8c58f6235bd2f875c2cad56812c7f09d73910e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 30 Jan 2024 21:59:07 +0200 Subject: [PATCH 3/3] The implementation is not so symmetric. --- Doc/library/datetime.rst | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index d601120024b63d..f71c022196baff 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -611,19 +611,11 @@ Notes: (4) :class:`date` objects are equal if they represent the same date. - :class:`!date` objects that are not also :class:`.datetime` instances - are never equal to :class:`!datetime` objects, even 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()``. - Order comparison between a :class:`!date` object that is not also a - :class:`.datetime` instance and a :class:`!datetime` object raises - :exc:`TypeError`. - In Boolean contexts, all :class:`date` objects are considered to be true. Instance methods: