Small cleanups to find_next_time_expression and addition of tests (#71845)

This commit is contained in:
J. Nick Koston 2022-05-14 15:13:32 -04:00 committed by GitHub
parent ebce5660e3
commit 4e9bc9eaff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 4 deletions

View File

@ -339,8 +339,8 @@ def find_next_time_expression_time(
now += dt.timedelta(seconds=1)
continue
now_is_ambiguous = _datetime_ambiguous(now)
result_is_ambiguous = _datetime_ambiguous(result)
if not _datetime_ambiguous(now):
return result
# When leaving DST and clocks are turned backward.
# Then there are wall clock times that are ambiguous i.e. exist with DST and without DST
@ -348,7 +348,7 @@ def find_next_time_expression_time(
# in a day.
# Example: on 2021.10.31 02:00:00 in CET timezone clocks are turned backward an hour
if now_is_ambiguous and result_is_ambiguous:
if _datetime_ambiguous(result):
# `now` and `result` are both ambiguous, so the next match happens
# _within_ the current fold.
@ -357,7 +357,7 @@ def find_next_time_expression_time(
# 2. 2021.10.31 02:00:00+01:00 with pattern 02:30 -> 2021.10.31 02:30:00+01:00
return result.replace(fold=now.fold)
if now_is_ambiguous and now.fold == 0 and not result_is_ambiguous:
if now.fold == 0:
# `now` is in the first fold, but result is not ambiguous (meaning it no longer matches
# within the fold).
# -> Check if result matches in the next fold. If so, emit that match

View File

@ -641,3 +641,53 @@ def test_find_next_time_expression_time_leave_dst_chicago_past_the_fold_ahead_2_
assert dt_util.as_utc(next_time) == datetime(
2021, 11, 7, 8, 20, 1, tzinfo=dt_util.UTC
)
def test_find_next_time_expression_microseconds():
"""Test finding next time expression with microsecond clock drift."""
hour_minute_second = (None, "5", "10")
test_time = datetime(2022, 5, 13, 0, 5, 9, tzinfo=dt_util.UTC)
matching_hours, matching_minutes, matching_seconds = _get_matches(
*hour_minute_second
)
next_time = dt_util.find_next_time_expression_time(
test_time, matching_seconds, matching_minutes, matching_hours
)
assert next_time == datetime(2022, 5, 13, 0, 5, 10, tzinfo=dt_util.UTC)
next_time_last_microsecond_plus_one = next_time.replace(
microsecond=999999
) + timedelta(seconds=1)
time_after = dt_util.find_next_time_expression_time(
next_time_last_microsecond_plus_one,
matching_seconds,
matching_minutes,
matching_hours,
)
assert time_after == datetime(2022, 5, 13, 1, 5, 10, tzinfo=dt_util.UTC)
def test_find_next_time_expression_tenth_second_pattern_does_not_drift_entering_dst():
"""Test finding next time expression tenth second pattern does not drift entering dst."""
tz = dt_util.get_time_zone("America/Chicago")
dt_util.set_default_time_zone(tz)
tenth_second_pattern = (None, None, "10")
# Entering DST, clocks go forward
test_time = datetime(2021, 3, 15, 2, 30, 0, tzinfo=tz, fold=0)
matching_hours, matching_minutes, matching_seconds = _get_matches(
*tenth_second_pattern
)
next_time = dt_util.find_next_time_expression_time(
test_time, matching_seconds, matching_minutes, matching_hours
)
assert next_time == datetime(2021, 3, 15, 2, 30, 10, tzinfo=tz)
prev_target = next_time
for i in range(1000):
next_target = dt_util.find_next_time_expression_time(
prev_target.replace(microsecond=999999) + timedelta(seconds=1),
matching_seconds,
matching_minutes,
matching_hours,
)
assert (next_target - prev_target).total_seconds() == 60
assert next_target.second == 10
prev_target = next_target