Skip to content

Commit

Permalink
Add explicit grace period for util function to get recent clocktime_w…
Browse files Browse the repository at this point in the history
…indow (#510)

* Add explicit grace period for util function to get recent clocktime_window

Signed-off-by: Nicolas Höning <nicolas@seita.nl>

* Allow for periods with >60 seconds

Signed-off-by: Nicolas Höning <nicolas@seita.nl>

Signed-off-by: Nicolas Höning <nicolas@seita.nl>
  • Loading branch information
nhoening committed Sep 30, 2022
1 parent 074a33d commit 5cf7f2e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
32 changes: 28 additions & 4 deletions flexmeasures/utils/tests/test_time_utils.py
Expand Up @@ -97,48 +97,72 @@ def test_naturalized_datetime_str(


@pytest.mark.parametrize(
"window_size, now, exp_start, exp_end",
"window_size, now, exp_start, exp_end, grace_period",
[
(
5,
datetime(2021, 4, 30, 15, 1),
datetime(2021, 4, 30, 14, 55),
datetime(2021, 4, 30, 15),
0,
),
(
15,
datetime(2021, 4, 30, 3, 36),
datetime(2021, 4, 30, 3, 15),
datetime(2021, 4, 30, 3, 30),
0,
),
(
5,
datetime(2021, 4, 30, 9, 15, 16),
datetime(2021, 4, 30, 9, 10),
datetime(2021, 4, 30, 9, 15),
0,
),
(
10,
datetime(2021, 4, 30, 0, 5),
datetime(2021, 4, 29, 23, 50),
datetime(2021, 4, 30, 0, 0),
0,
),
(
5,
datetime(
2021, 5, 20, 10, 5, 34
), # less than grace period into the new window
datetime(2021, 5, 20, 9, 55),
datetime(2021, 5, 20, 10, 0),
60,
),
(
5,
datetime(2021, 5, 20, 10, 5, 34), # boundary condition
datetime(2021, 5, 20, 10, 7, 4),
datetime(2021, 5, 20, 9, 55),
datetime(2021, 5, 20, 10, 0),
130, # grace period > 2 minutes
),
(
60,
datetime(2021, 1, 1, 0, 4), # new year
datetime(2020, 12, 31, 23, 00),
datetime(2021, 1, 1, 0, 0),
0,
),
(
60,
datetime(2021, 3, 28, 3, 10), # DST transition
datetime(2021, 3, 28, 2),
datetime(2021, 3, 28, 3),
0,
),
],
)
def test_recent_clocktime_window(window_size, now, exp_start, exp_end):
start, end = get_most_recent_clocktime_window(window_size, now=now)
def test_recent_clocktime_window(window_size, now, exp_start, exp_end, grace_period):
start, end = get_most_recent_clocktime_window(
window_size, now=now, grace_period_in_seconds=grace_period
)
assert start == exp_start
assert end == exp_end

Expand Down
15 changes: 13 additions & 2 deletions flexmeasures/utils/time_utils.py
Expand Up @@ -199,7 +199,9 @@ def get_most_recent_hour() -> datetime:


def get_most_recent_clocktime_window(
window_size_in_minutes: int, now: Optional[datetime] = None
window_size_in_minutes: int,
now: Optional[datetime] = None,
grace_period_in_seconds: Optional[int] = 0,
) -> Tuple[datetime, datetime]:
"""
Calculate a recent time window, returning a start and end minute so that
Expand All @@ -208,6 +210,9 @@ def get_most_recent_clocktime_window(
Calling this function at 15:01:xx with window size 5 -> (14:55:00, 15:00:00)
Calling this function at 03:36:xx with window size 15 -> (03:15:00, 03:30:00)
We can demand a grace period (of x seconds) to have passed before we are ready to accept that we're in a new window:
Calling this function at 15:00:16 with window size 5 and grace period of 30 seconds -> (14:50:00, 14:55:00)
window_size_in_minutes is assumed to > 0 and < = 60, and a divisor of 60 (1, 2, ..., 30, 60).
If now is not given, the current server time is used.
Expand All @@ -221,7 +226,13 @@ def get_most_recent_clocktime_window(
assert 60 % window_size_in_minutes == 0
if now is None:
now = server_now()
last_full_minute = now.replace(second=0, microsecond=0) - timedelta(minutes=1)
last_full_minute = now.replace(second=0, microsecond=0)
if (
grace_period_in_seconds is not None
and grace_period_in_seconds > 0
and (now - last_full_minute).seconds < grace_period_in_seconds
):
last_full_minute -= timedelta(minutes=1 + grace_period_in_seconds // 60)
last_round_minute = last_full_minute.minute - (
last_full_minute.minute % window_size_in_minutes
)
Expand Down

0 comments on commit 5cf7f2e

Please sign in to comment.