Skip to content

Commit

Permalink
Add note / warning about non-existent datetimes
Browse files Browse the repository at this point in the history
In response to [^1].

This is a known issue with datetime [^2].

[^1]: #178 (comment)
[^2]: https://peps.python.org/pep-0495/#the-fold-attribute
  • Loading branch information
benthorner committed Dec 9, 2024
1 parent 2276ed7 commit 8f83a6d
Showing 1 changed file with 37 additions and 0 deletions.
37 changes: 37 additions & 0 deletions xocto/localtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,41 @@
from . import numbers, ranges


# Note [Non-existent datetimes]
#
# Python datetimes can be constructed for times that don't
# actually exist in certain timezones, due to clock changes
# at Daylight Savings Time (DST) boundaries.
#
# For example, 1AM on 29/02/2020 doesn't exist in GBR as the
# clocks go forwards one hour - to 2AM - at this time. But
#
# datetime(2020, 2, 29, hours=1, tzinfo=london_tz)
#
# does not error, even though it is invalid. This can cause
# problems comparing with other datetimes e.g.
#
# datetime(2020, 2, 29, hours=2, tzinfo=london_tz) -
# datetime(2020, 2, 29, hours=1, tzinfo=london_tz)
# => timedelta(hours=1) <== WRONG (should be 0)
#
# with pytest.raises(ValueError): # empty range
# FiniteDatetimeRange(
# localtime.as_utc(datetime(2020, 2, 29, hours=2, tzinfo=london_tz)),
# localtime.as_utc(datetime(2020, 2, 29, hours=1, tzinfo=london_tz)),
# )
#
# Although such datetimes are unlikely to be created directly,
# they may be created from other code in "datetime" e.g.
#
# datetime(2020, 2, 29, tzinfo=london_tz) + timedelta(hours=1)
# => datetime(2020, 2, 29, hours=1, tzinfo=london_tz)
#
# To ensure a datetime exists in its timezone, convert it
# to UTC (a timezone without DST) and back again e.g.
#
# localtime.as_localtime(localtime.as_utc(my_dt), tz=my_dt.tzinfo)

# Timezone aware datetime in the far future.
far_future = timezone.make_aware(datetime_.datetime.max - datetime_.timedelta(days=2))

Expand All @@ -35,6 +70,8 @@ def as_localtime(
Convert a tz aware datetime to localtime.
Wrapper for the `django.utils.timezone` function, taking the same arguments.
Warning: See Note [Non-existent datetimes]
"""
return timezone.localtime(dt, timezone=tz)

Expand Down

0 comments on commit 8f83a6d

Please sign in to comment.