Skip to content

Commit 2254932

Browse files
committed
Add support for np.datetime64 in TimeInterval
1 parent 7a39473 commit 2254932

2 files changed

Lines changed: 23 additions & 12 deletions

File tree

parcels/_core/utils/time.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import TypeVar
55

66
import cftime
7+
import numpy as np
78

89
T = TypeVar("T", datetime, cftime.datetime)
910

@@ -24,10 +25,10 @@ class TimeInterval:
2425
"""
2526

2627
def __init__(self, left: T, right: T) -> None:
27-
if not isinstance(left, (datetime, cftime.datetime)):
28-
raise ValueError(f"Expected left to be a datetime or cftime.datetime, got {type(left)}.")
29-
if not isinstance(right, (datetime, cftime.datetime)):
30-
raise ValueError(f"Expected right to be a datetime or cftime.datetime, got {type(right)}.")
28+
if not isinstance(left, (datetime, cftime.datetime, np.datetime64)):
29+
raise ValueError(f"Expected right to be a datetime, cftime.datetime, or np.datetime64. Got {type(left)}.")
30+
if not isinstance(right, (datetime, cftime.datetime, np.datetime64)):
31+
raise ValueError(f"Expected right to be a datetime, cftime.datetime, or np.datetime64. Got {type(right)}.")
3132
if left >= right:
3233
raise ValueError(f"Expected left to be strictly less than right, got left={left} and right={right}.")
3334
if not is_compatible(left, right):

tests/v4/utils/test_time.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,38 @@
22

33
from datetime import datetime, timedelta
44

5+
import numpy as np
56
import pytest
67
from cftime import datetime as cftime_datetime
78
from hypothesis import given
89
from hypothesis import strategies as st
910

1011
from parcels._core.utils.time import TimeInterval
1112

12-
calendar_strategy = st.sampled_from(["gregorian", "proleptic_gregorian", "365_day", "360_day", "julian", "366_day"])
13+
calendar_strategy = st.sampled_from(
14+
["gregorian", "proleptic_gregorian", "365_day", "360_day", "julian", "366_day", np.datetime64, datetime]
15+
)
1316

1417

1518
@st.composite
16-
def cftime_datetime_strategy(draw, calendar=None):
19+
def datetime_strategy(draw, calendar=None):
1720
year = draw(st.integers(1900, 2100))
1821
month = draw(st.integers(1, 12))
1922
day = draw(st.integers(1, 28))
2023
if calendar is None:
2124
calendar = draw(calendar_strategy)
25+
if calendar is datetime:
26+
return datetime(year, month, day)
27+
if calendar is np.datetime64:
28+
return np.datetime64(datetime(year, month, day))
29+
2230
return cftime_datetime(year, month, day, calendar=calendar)
2331

2432

2533
@st.composite
26-
def cftime_interval_strategy(draw, left=None, calendar=None):
34+
def time_interval_strategy(draw, left=None, calendar=None):
2735
if left is None:
28-
left = draw(cftime_datetime_strategy(calendar=calendar))
36+
left = draw(datetime_strategy(calendar=calendar))
2937
right = left + draw(
3038
st.timedeltas(
3139
min_value=timedelta(seconds=1),
@@ -41,6 +49,8 @@ def cftime_interval_strategy(draw, left=None, calendar=None):
4149
(cftime_datetime(2023, 1, 1, calendar="gregorian"), cftime_datetime(2023, 1, 2, calendar="gregorian")),
4250
(cftime_datetime(2023, 6, 1, calendar="365_day"), cftime_datetime(2023, 6, 2, calendar="365_day")),
4351
(cftime_datetime(2023, 12, 1, calendar="360_day"), cftime_datetime(2023, 12, 2, calendar="360_day")),
52+
(datetime(2023, 12, 1), datetime(2023, 12, 2)),
53+
(np.datetime64(datetime(2023, 12, 1)), np.datetime64(datetime(2023, 12, 2))),
4454
],
4555
)
4656
def test_time_interval_initialization(left, right):
@@ -53,7 +63,7 @@ def test_time_interval_initialization(left, right):
5363
TimeInterval(right, left)
5464

5565

56-
@given(cftime_interval_strategy())
66+
@given(time_interval_strategy())
5767
def test_time_interval_contains(interval):
5868
left = interval.left
5969
right = interval.right
@@ -64,12 +74,12 @@ def test_time_interval_contains(interval):
6474
assert middle in interval
6575

6676

67-
@given(cftime_interval_strategy(calendar="365_day"), cftime_interval_strategy(calendar="365_day"))
77+
@given(time_interval_strategy(calendar="365_day"), time_interval_strategy(calendar="365_day"))
6878
def test_time_interval_intersection_commutative(interval1, interval2):
6979
assert interval1.intersection(interval2) == interval2.intersection(interval1)
7080

7181

72-
@given(cftime_interval_strategy())
82+
@given(time_interval_strategy())
7383
def test_time_interval_intersection_with_self(interval):
7484
assert interval.intersection(interval) == interval
7585

@@ -81,7 +91,7 @@ def test_time_interval_repr():
8191
assert repr(interval) == expected
8292

8393

84-
@given(cftime_interval_strategy())
94+
@given(time_interval_strategy())
8595
def test_time_interval_equality(interval):
8696
assert interval == interval
8797

0 commit comments

Comments
 (0)