Struggling to understand timedelta rpesentation when applying an offset for an hour earlier - why is days = -1?

Chris Angelico rosuav at gmail.com
Tue Aug 31 15:39:32 EDT 2021


On Wed, Sep 1, 2021 at 1:55 AM dcs3spp via Python-list
<python-list at python.org> wrote:
>
> Hi,
>
> I wonder if anyone can help....
>
> I am struggling to understand the representation of timedelta when used in conjunction with astimezone.
>
> Given the code below, in a python interactive interpreter, I am trying to calculate a resultant datetime an hour earlier from a UTC datetime....
>
> ```bash
>     >>> dt = datetime(2021, 8, 22, 23, 59, 31, tzinfo=timezone.utc)
>     >>> hour_before=dt.astimezone(timezone(-timedelta(seconds=3600)))
>     >>> hour_before
>     datetime.datetime(2021, 8, 22, 22, 59, 31, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=82800)))
> ```
>
> I cannot understand why the resultant datetime.timedelta is days=-1, seconds=82800 (23 hours) .
>
> Why is it not an hour earlier as seconds=-3600? Why is days = -1 when the resultant calculated date is the same, year, day, month??

It's consistent with modulo arithmetic:

>>> x = -3600
>>> x // 86400
-1
>>> x % 86400
82800

>>> help(datetime.timedelta)
...
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  days
 |      Number of days.
 |
 |  microseconds
 |      Number of microseconds (>= 0 and less than 1 second).
 |
 |  seconds
 |      Number of seconds (>= 0 and less than 1 day).
 |
 |  ----------------------------------------------------------------------

The sub-day portions are guaranteed to be zero or above, meaning that
a small negative offset is described as "a day ago, plus 23 hours"
rather than "an hour ago". It's the exact same thing, though.

If you would prefer to see ALL components negative, just negate the
timedelta and then negate each component; that will give you an
equivalent timedelta.

>>> datetime.timedelta(seconds=-3600)
datetime.timedelta(days=-1, seconds=82800)
>>> -datetime.timedelta(seconds=-3600)
datetime.timedelta(seconds=3600)
>>> datetime.timedelta(seconds=-3600-86400)
datetime.timedelta(days=-2, seconds=82800)
>>> -datetime.timedelta(seconds=-3600-86400)
datetime.timedelta(days=1, seconds=3600)

Hope that explains it!

ChrisA


More information about the Python-list mailing list