Skip to content

Timezone-aware datetime subtracting timedelta does not adjust DST offset correctly #96651

Closed as not planned
@alanhamlett

Description

@alanhamlett

Using Python 3.8 I'm trying to convert a timezone-aware datetime in Europe/Sofia to the start of the day in Europe/Sofia, but returning the datetime in UTC. Doing this, I encountered a strange problem:

#!/usr/bin/env python

import sys
import pytz
from datetime import datetime, timedelta


def main():
    tz = pytz.timezone('Europe/Sofia')
    dt = pytz.utc.localize(datetime(year=2019, month=3, day=31, hour=14, minute=45))
    print(f'We start with the datetime in UTC: {dt}')
    dt = dt.astimezone(tz)
    print(f'Then convert it to Europe/Sofia timezone: {dt}')

    result = dt.replace(hour=0, minute=0, second=0, microsecond=0)
    print(f'Then make it the start of the day midnight: {result}')
    result = result.astimezone(pytz.utc)
    print(f'Then convert it back to UTC (the final result we want): {result}')
    print(f'But notice the time is wrong now when converted back to Europe/Sofia: {result.astimezone(tz)}')

    result = dt - timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second, microseconds=dt.microsecond)
    print(f'Using a timedelta instead of replace has the same result: {result}')
    print(f'The time is still wrong when converted back to Europe/Sofia: {result.astimezone(pytz.utc).astimezone(tz)}')

    return 0


if __name__ == '__main__':
    sys.exit(main())

Which prints:

We start with the datetime in UTC: 2019-03-31 14:45:00+00:00
Then convert it to Europe/Sofia timezone: 2019-03-31 17:45:00+03:00
Then make it the start of the day midnight: 2019-03-31 00:00:00+03:00
Then convert it back to UTC (the final result we want): 2019-03-30 21:00:00+00:00
But notice the time is wrong now when converted back to Europe/Sofia: 2019-03-30 23:00:00+02:00
Using a timedelta instead of replace has the same result: 2019-03-31 00:00:00+03:00
The time is still wrong when converted back to Europe/Sofia: 2019-03-30 23:00:00+02:00

The bug happens when subtracting the timedelta or doing the replace(), because the result should be midnight in Europe/Sofia with +2 offset, however we're seeing an incorrect +3 offset. It should be +2 because at 3 AM on Mar 31 2019 there was a DST transition of +1 hour. [1]

Is this a bug in Python or a known limitation with a known workaround?

Originally posted on StackOverflow

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions