Paul Ganssle <p.gans...@gmail.com> added the comment:

> What's the use case for subclassing DateTime? These classes were not designed 
> with subclassing as a use case in mind.

There are several reasons for doing it, of various levels of legitimacy. The 
overall theme is that people want different behaviors from their datetime 
classes and they want to maintain drop-in compatibility with datetime so that 
you don't need to re-build the whole world of datetime-handling libraries if 
you want to adopt one of these alternative datetime providers.

Ideally, you would tell people to just write API-compatible code and use 
duck-typing, but there's a lot of code in the standard library that uses 
`isinstance` checks, so things like 
`some_tzinfo.utcoffset(MyCoolDatetime.now())` will raise a TypeError.

Two popular datetime frameworks arrow and pendulum, both use datetime 
subclasses. A lot of what they are providing is convenience methods that could 
easily be free functions, but they also need to be subclasses so that they can 
change things like the semantics of arithmetic. For example, one motivation for 
the creation of pendulum was that the creator wanted this invariant to hold 
true:

    assert dt1 == (dt1 - dt2) + dt2

This is basically due to the fact that in Python's datetime library, no 
distinction is made between "absolute deltas" (the absolute time between two 
events) and "calendar deltas", which makes subtraction or addition across DST 
boundaries ambiguous and occasionally lossy. Arithmetic semantics are one of 
the things about datetime I'd most love to change but for backwards 
compatibility reasons it's just not feasible.

Another reason I've seen for subclassing datetime is that this is how dateutil 
provides its backport of PEP 495 (ambiguous datetime support). We have a 
datetime subclass called _DatetimeWithFold that supports the `fold` attribute, 
and is generated only when necessary (and does not exist in Python 3.6+). 
_DatetimeWithFold is not affected by this problem because PEP 495 specifies 
that the result of an arithmetic operation always sets fold to 0, but it *was* 
affected by the earlier (now fixed) bug where the subclass did not survive a 
`replace` operation.

One last place I've seen datetime subclasses used is when you have a thin 
wrapper used for dispatch or other purposes where you are mapping between 
types. For example, at work we had to create mappings between python types and 
the types specified by a standard (developed for another language), but that 
standard specified both a datetime type (with millisecond precision) and a 
datetimeus type (with microsecond precision). The solution was a thin wrapper 
around datetime called DatetimeUs: 
https://github.com/bloomberg/python-comdb2/blob/master/comdb2/_cdb2_types.py#L62

Preventing operations from reverting to datetime was a bit of a pain, which is 
why we have a bunch of tests to check that the subclass survives basic 
operations: 
https://github.com/bloomberg/python-comdb2/blob/master/tests/test_cdb2_datetimeus.py#L95

Although it was not originally *designed* to be subclassed, support for 
datetime subclasses is already quite good. This timedelta issue is one of the 
last major issues to fix to make them truly subclass-friendly. I'll note also 
that for the past 9 years, the test suite has run all datetime tests against a 
"thin wrapper" subclass of datetime: 
https://github.com/python/cpython/blame/028f0ef4f3111d2b3fc5b971642e337ba7990873/Lib/test/datetimetester.py#L2802

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue32417>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to