Daylight Saving Time (DST) changes occur usually twice a year. During fall clocks are moved backwards which creates a fold which means that a given local time has two possible meanings. This is covered in PEP-495. During spring clocks are moved forwards which creates a gap in possible local time values, typically with length of one hour.
For example in "Europe/London" timezone the possible minutes at 2023-03-26 near the DST change are: 00:58, 00:59, 02:00, 02:01; The values 01:00 to 01:59 do not exist.
Example
Here is an example of cases which should be detected as valid (possible) and impossible:
import datetime as dt
from zoneinfo import ZoneInfo
timestamp_possible = dt.datetime.strptime(
"2023-03-26 00:30:00", "%Y-%m-%d %H:%M:%S"
).replace(tzinfo=ZoneInfo("Europe/London"))
timestamp_impossible = dt.datetime.strptime(
"2023-03-26 01:30:00", "%Y-%m-%d %H:%M:%S"
).replace(tzinfo=ZoneInfo("Europe/London"))
Here is how I could do it using pandas.to_datetime, but I'm not entirely sure why it works and if that is an implementation detail of pandas (which might change?) or guaranteed behaviour.
def is_valid(timestamp):
return pd.to_datetime(timestamp).to_pydatetime(timestamp) == timestamp
which gives
>>> is_valid(timestamp_possible)
True
>>> is_valid(timestamp_impossible)
False
Question
What would be the simplest possible way to detect if a given datetime.datetime object is valid or hitting the "nonexistent time values" gap? Is there some way to do this in Python standard library?
I took a closer look on the PEP-495 and there's actually a pretty useful function down in the Strict Invalid Time Checking section:
It is pretty easy to modify that to make it return a flag which tells if the timestamp is at the gap:
The
(u < v) == timestamp.folddoes not look very understandable but anyway it looks like it's working well. Some test values:and test return values: