Why does datetime.timedelta only have the attributes 'days' and 'seconds'?

Peter J. Holzer hjp-python at hjp.at
Sat Apr 16 12:00:28 EDT 2022


On 2022-04-16 14:22:04 -0000, Jon Ribbens via Python-list wrote:
> On 2022-04-16, Jon Ribbens <jon+usenet at unequivocal.eu> wrote:
> > On 2022-04-16, Peter J. Holzer <hjp-python at hjp.at> wrote:
> >> Python missed the switch to DST here, the timezone is wrong.
> >
> > Because you didn't let it use any timezone information. You need to
> > either use the third-party 'pytz' module, or in Python 3.9 or above,
> > the built-in 'zoneinfo' module.
> 
> ... although now having looked into the new 'zoneinfo' module slightly,
> it really should have a giant red flashing notice at the top of it
> saying "BEWARE, TIMEZONES IN PYTHON ARE UTTERLY BROKEN, NEVER USE THEM".
> 
> Suppose we do this:
> 
>     >>> import datetime, zoneinfo
>     >>> LOS_ANGELES = zoneinfo.ZoneInfo('America/Los_Angeles')
>     >>> UTC = zoneinfo.ZoneInfo('UTC')
>     >>> d = datetime.datetime(2020, 10, 31, 12, tzinfo=LOS_ANGELES)
>     >>> print(d)
>     2020-10-31 12:00:00-07:00
>     >>> d1 = d + datetime.timedelta(days=1)
>     >>> print(d1)
>     2020-11-01 12:00:00-08:00
> 
> d1 is *wrong*.

No, this is correct. That's the result you want.

So why didn't this work for me (I also used Python 3.9)? My guess is
that astimezone() doesn't pick the correct time zone.


> timedelta(days=1) is 24 hours (as you can check by
> calling timedelta(days=1).total_seconds() ),

It shouldn't be. 1 Day is not 24 hours in the real world.

> but d1 is 25 hours later
> than 'd'. If we do the calculations in UTC instead, it works correctly:
> 
>     >>> print((d.astimezone(UTC) + datetime.timedelta(days=1)).astimezone(LOS_ANGELES))
>     2020-11-01 11:00:00-08:00
> 
> It seems that Python is assuming that if the tzinfo attributes of two
> datetimes are the same,

There is only one datetime in your examples.

> then it can pretend timezones don't exist and do 'naive' arithmetic.

On the contrary. When a datetime is timezone aware, it must use that
timezone's rules. Adding one day to a datetime just before a DST switch
must add 23 or 25 hours, not 24. This is NOT naive.

(There is an ambiguity, though: Should 2021-03-27T12:00 CEST -
2021-03-26T12:00 CET return 1 day or 25 hours? Both results are correct,
and depending on context you might prefer one or the other).

> There is a general guideline that you should always keep and use your
> datetimes as UTC, only ever using timezones for the purposes of display.
> Usually this is because it keeps things simpler for the programmer, and
> hence they are less likely to introduce bugs into their programs.

While I generally do this (and often preach it to my collegues) it must
be stated that this is only a GENERAL guide line. There are many
exceptions, especially when scheduling events in the future. For
example, if want to meet somebody on July 18th, 2023 at 19:00 in Vienna,
Austria, it would be wrong to store that date as 2023-07-18T17:00Z. The
EU has decided to abolish DST, and while I don't expect them to get
around to it within the next year (or maybe ever), it might still
happen. So we simply don't know yet whether 19:00 local time will be
17:00 or 18:00 UTC. There have been cases where countries have changed
their DST rules only days in advance.

> It appears that with Python it's not so much a guideline as an
> absolute concrete rule, and not because programmers will introduce
> bugs, but because you need to avoid bugs in the standard library!

As a programmer you must always adapt to the problem. Saying "I must do
it the wrong way because my library is buggy" is just lazy. Use a
different library or write one yourself. (Unless of course the customer
doesn't want to pay for the extra work, then they get what they pay
for.)

        hp

-- 
   _  | Peter J. Holzer    | Story must make more sense than reality.
|_|_) |                    |
| |   | hjp at hjp.at         |    -- Charles Stross, "Creative writing
__/   | http://www.hjp.at/ |       challenge!"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://mail.python.org/pipermail/python-list/attachments/20220416/671278bd/attachment.sig>


More information about the Python-list mailing list