Skip to content

Commit e163dff

Browse files
committed
Update isodatetime to 3.2
Fix bug where `next(...)` could return past datetime
1 parent cac813b commit e163dff

File tree

8 files changed

+39
-48
lines changed

8 files changed

+39
-48
lines changed

changes.d/5928.break.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed behaviour of `initial cycle point = next(...)` which could result in a time in the past, and equivalently for `previous()`. E.g. if the current time is `2024-01-01T12:30Z`, `next(--01-01)` now evaluates to `2025-01-01T00:00Z` instead of `2024-01-01T00:00Z`.

conda-environment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies:
99
- graphviz # for static graphing
1010
# Note: can't pin jinja2 any higher than this until we give up on Cylc 7 back-compat
1111
- jinja2 >=3.0,<3.1
12-
- metomi-isodatetime >=1!3.0.0, <1!3.2.0
12+
- metomi-isodatetime >=1!3.2.0, <1!3.3.0
1313
- packaging
1414
# Constrain protobuf version for compatible Scheduler-UIS comms across hosts
1515
- protobuf >=4.24.4,<4.25.0

cylc/flow/commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ async def stop(
197197
# schedule shutdown after wallclock time passes provided time
198198
parser = TimePointParser()
199199
schd.set_stop_clock(
200-
int(parser.parse(clock_time).seconds_since_unix_epoch)
200+
parser.parse(clock_time).seconds_since_unix_epoch
201201
)
202202
schd._update_workflow_state()
203203
elif task is not None:

cylc/flow/cycling/iso8601.py

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,52 @@
1919
import contextlib
2020
from functools import lru_cache
2121
import re
22-
from typing import List, Optional, TYPE_CHECKING, Tuple
22+
from typing import (
23+
TYPE_CHECKING,
24+
List,
25+
Optional,
26+
Tuple,
27+
)
2328

24-
from metomi.isodatetime.data import Calendar, CALENDAR, Duration
29+
from metomi.isodatetime.data import (
30+
CALENDAR,
31+
Calendar,
32+
)
2533
from metomi.isodatetime.dumpers import TimePointDumper
26-
from metomi.isodatetime.timezone import (
27-
get_local_time_zone, get_local_time_zone_format, TimeZoneFormatMode)
2834
from metomi.isodatetime.exceptions import IsodatetimeError
2935
from metomi.isodatetime.parsers import ISO8601SyntaxError
30-
from cylc.flow.time_parser import CylcTimeParser
36+
from metomi.isodatetime.timezone import (
37+
TimeZoneFormatMode,
38+
get_local_time_zone,
39+
get_local_time_zone_format,
40+
)
41+
3142
from cylc.flow.cycling import (
32-
PointBase, IntervalBase, SequenceBase, ExclusionBase, cmp
43+
ExclusionBase,
44+
IntervalBase,
45+
PointBase,
46+
SequenceBase,
47+
cmp,
3348
)
3449
from cylc.flow.exceptions import (
3550
CylcConfigError,
3651
IntervalParsingError,
3752
PointParsingError,
3853
SequenceDegenerateError,
39-
WorkflowConfigError
54+
WorkflowConfigError,
4055
)
41-
from cylc.flow.wallclock import get_current_time_string
4256
from cylc.flow.parsec.validate import IllegalValueError
57+
from cylc.flow.time_parser import CylcTimeParser
58+
from cylc.flow.wallclock import get_current_time_string
59+
4360

4461
if TYPE_CHECKING:
4562
from metomi.isodatetime.data import TimePoint
4663
from metomi.isodatetime.parsers import (
47-
DurationParser, TimePointParser, TimeRecurrenceParser)
64+
DurationParser,
65+
TimePointParser,
66+
TimeRecurrenceParser,
67+
)
4868

4969
CYCLER_TYPE_ISO8601 = "iso8601"
5070
CYCLER_TYPE_SORT_KEY_ISO8601 = 1
@@ -706,14 +726,6 @@ def ingest_time(value: str, now: Optional[str] = None) -> str:
706726
now = get_current_time_string()
707727
now_point = parser.parse(now)
708728

709-
# correct for year in 'now' if year is the only date unit specified -
710-
# https://github.com/cylc/cylc-flow/issues/4805#issuecomment-1103928604
711-
if re.search(r"\(-\d{2}[);T]", value):
712-
now_point += Duration(years=1)
713-
# likewise correct for month if year and month are the only date units
714-
elif re.search(r"\(-\d{4}[);T]", value):
715-
now_point += Duration(months=1)
716-
717729
# perform whatever transformation is required
718730
offset = None
719731
if is_prev_next:
@@ -806,28 +818,6 @@ def prev_next(
806818

807819
cycle_point = timepoints[my_diff.index(min(my_diff))]
808820

809-
# ensure truncated dates do not have time from 'now' included' -
810-
# https://github.com/metomi/isodatetime/issues/212
811-
if 'T' not in value.split(')')[0]:
812-
# NOTE: Strictly speaking we shouldn't forcefully mutate TimePoints
813-
# in this way as they're meant to be immutable since
814-
# https://github.com/metomi/isodatetime/pull/165, however it
815-
# should be ok as long as the TimePoint is not used as a dict key and
816-
# we don't call any of the TimePoint's cached methods until after we've
817-
# finished mutating it.
818-
cycle_point._hour_of_day = 0
819-
cycle_point._minute_of_hour = 0
820-
cycle_point._second_of_minute = 0
821-
# likewise ensure month and day from 'now' are not included
822-
# where they did not appear in the truncated datetime
823-
if re.search(r"\(-\d{2}[);T]", value):
824-
# case 1 - year only
825-
cycle_point._month_of_year = 1
826-
cycle_point._day_of_month = 1
827-
elif re.search(r"\(-(-\d{2}|\d{4})[;T)]", value):
828-
# case 2 - month only or year and month
829-
cycle_point._day_of_month = 1
830-
831821
return cycle_point, offset
832822

833823

cylc/flow/task_proxy.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ def get_point_as_seconds(self):
414414
"""Compute and store my cycle point as seconds since epoch."""
415415
if self.point_as_seconds is None:
416416
iso_timepoint = point_parse(str(self.point))
417-
self.point_as_seconds = int(iso_timepoint.seconds_since_unix_epoch)
417+
self.point_as_seconds = iso_timepoint.seconds_since_unix_epoch
418418
if iso_timepoint.time_zone.unknown:
419419
utc_offset_hours, utc_offset_minutes = (
420420
get_local_time_zone())
@@ -448,7 +448,7 @@ def get_clock_trigger_time(
448448
else:
449449
trigger_time = point_time + interval_parse(offset_str)
450450

451-
self.clock_trigger_times[offset_str] = int(
451+
self.clock_trigger_times[offset_str] = (
452452
trigger_time.seconds_since_unix_epoch
453453
)
454454
return self.clock_trigger_times[offset_str]

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ install_requires =
6868
graphene>=2.1,<3
6969
# Note: can't pin jinja2 any higher than this until we give up on Cylc 7 back-compat
7070
jinja2==3.0.*
71-
metomi-isodatetime>=1!3.0.0,<1!3.2.0
71+
metomi-isodatetime>=1!3.2.0,<1!3.3.0
7272
# Constrain protobuf version for compatible Scheduler-UIS comms across hosts
7373
packaging
7474
protobuf>=4.24.4,<4.25.0

tests/unit/cycling/test_iso8601.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ def test_simple(set_cycling_type):
700700
('next(--0325)', '20110325T0000Z'),
701701
('next(---10)', '20100810T0000Z'),
702702
('next(---05T1200Z)', '20100905T1200Z'),
703-
param('next(--08-08)', '20110808T0000Z', marks=pytest.mark.xfail),
703+
('next(--08-08)', '20110808T0000Z'),
704704
('next(T15)', '20100809T1500Z'),
705705
('next(T-41)', '20100808T1541Z'),
706706
]
@@ -724,7 +724,7 @@ def test_next_simple(value: str, expected: str, set_cycling_type):
724724
('previous(--0325)', '20100325T0000Z'),
725725
('previous(---10)', '20100710T0000Z'),
726726
('previous(---05T1200Z)', '20100805T1200Z'),
727-
param('previous(--08-08)', '20100808T0000Z', marks=pytest.mark.xfail),
727+
('previous(--08-08)', '20100808T0000Z'),
728728
('previous(T15)', '20100808T1500Z'),
729729
('previous(T-41)', '20100808T1441Z'),
730730
]
@@ -870,7 +870,7 @@ def test_weeks_days(set_cycling_type):
870870
('previous(--1225)', '20171225T0000Z'),
871871
('next(-2006)', '20200601T0000Z'),
872872
('previous(-W101)', '20180305T0000Z'),
873-
('next(-W-1; -W-3; -W-5)', '20180314T0000Z'),
873+
('next(-W-1; -W-3; -W-5)', '20180316T0000Z'),
874874
('next(-001; -091; -181; -271)', '20180401T0000Z'),
875875
('previous(-365T12Z)', '20171231T1200Z'),
876876
]

tests/unit/test_workflow_status.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def schd(
8989
WORKFLOW_STATUS_RUNNING_TO_STOP % 4
9090
),
9191
(
92-
{'stop_clock_time': int(STOP_TIME.seconds_since_unix_epoch)},
92+
{'stop_clock_time': STOP_TIME.seconds_since_unix_epoch},
9393
WorkflowStatus.RUNNING,
9494
WORKFLOW_STATUS_RUNNING_TO_STOP % str(STOP_TIME)
9595
),

0 commit comments

Comments
 (0)