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

Peter J. Holzer hjp-python at hjp.at
Sun Apr 17 03:26:51 EDT 2022


On 2022-04-16 20:35:22 -0000, Jon Ribbens via Python-list wrote:
> On 2022-04-16, Peter J. Holzer <hjp-python at hjp.at> wrote:
> > On 2022-04-16 14:22:04 -0000, Jon Ribbens via Python-list wrote:
> >> ... 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.
> 
> I can categorically guarantee you it is not. But let's put it a
> different way, if you like, if I want to add 24 hours, i.e. 86,400
> seconds (or indeed any other fixed time period), to a timezone-aware
> datetime in Python, how do I do it?

What you *should* be able to do is use datetime.timedelta(hours=24).

Unfortunately, you can't, because somebody decided to add a
normalization rule to timedelta which turns this into timedelta(days=1,
hours=0).

> It would appear that, without converting to UTC before doing the
> calculation, you can't.

When doing calculations of this kind I frankly prefer converting to
"seconds since the epoch" and doing simple arithmetic. (Yes, leap
seconds, I know .. I just ignore those)


> > 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.
> 
> astimezone() doesn't pick a time zone at all. It works out the current
> local offset from UTC.

The timezone object it returns also includes a timezone string ("CET" in
my example). So it's not *just* the offset. The result is misleading,
though. You get something which looks like it's a timezone object for
Central European Time, but isn't.

> It doesn't know anything about when or if that
> offset ever changes.

astimezone() doesn't have to. It just has to pick the correct timezone
object. That object then knows about offset changes.


> >> 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.
> 
> Nevertheless, timedelta is a fixed time period so that is the only
> definition possible.

Yeah, you keep repeating that. I think we are talking at cross-purposes
here. You are talking about how timedelta is implemented while I'm
talking what semantics it *should* have.


> >> 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.
> 
> I didn't say any of that. I said you must do it the conservative way,
> and it's not "my library" that's buggy, it's the language's built-in
> *standard library* that's buggy.

With "your library" I meant "the library you have" not "the library you
wrote". And while having a buggy (or just badly designed) standard
library is especially annoying, you still aren't forced to use it if if
doesn't fit your needs. 

        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/20220417/991bff1d/attachment.sig>


More information about the Python-list mailing list