1313
1414
1515class TimeInterval :
16- """A class representing a time interval between two datetime objects.
16+ """A class representing a time interval between two datetime or np.timedelta64 objects.
1717
1818 Parameters
1919 ----------
20- left : datetime or cftime.datetime
20+ left : np.datetime64 or cftime.datetime or np.timedelta64
2121 The left endpoint of the interval.
22- right : datetime or cftime.datetime
22+ right : np.datetime64 or cftime.datetime or np.timedelta64
2323 The right endpoint of the interval.
2424
2525 Notes
@@ -28,12 +28,17 @@ class TimeInterval:
2828 """
2929
3030 def __init__ (self , left : T , right : T ) -> None :
31- if not isinstance (left , (datetime , cftime .datetime , np .datetime64 )):
32- raise ValueError (f"Expected right to be a datetime, cftime.datetime, or np.datetime64. Got { type (left )} ." )
33- if not isinstance (right , (datetime , cftime .datetime , np .datetime64 )):
34- raise ValueError (f"Expected right to be a datetime, cftime.datetime, or np.datetime64. Got { type (right )} ." )
31+ if not isinstance (left , (np .timedelta64 , datetime , cftime .datetime , np .datetime64 )):
32+ raise ValueError (
33+ f"Expected right to be a np.timedelta64, datetime, cftime.datetime, or np.datetime64. Got { type (left )} ."
34+ )
35+ if not isinstance (right , (np .timedelta64 , datetime , cftime .datetime , np .datetime64 )):
36+ raise ValueError (
37+ f"Expected right to be a np.timedelta64, datetime, cftime.datetime, or np.datetime64. Got { type (right )} ."
38+ )
3539 if left >= right :
3640 raise ValueError (f"Expected left to be strictly less than right, got left={ left } and right={ right } ." )
41+
3742 if not is_compatible (left , right ):
3843 raise ValueError (f"Expected left and right to be compatible, got left={ left } and right={ right } ." )
3944
@@ -58,15 +63,26 @@ def intersection(self, other: TimeInterval) -> TimeInterval | None:
5863 """Return the intersection of two time intervals. Returns None if there is no overlap."""
5964 if not is_compatible (self .left , other .left ):
6065 raise ValueError ("TimeIntervals are not compatible." )
66+ if not is_compatible (self .right , other .right ):
67+ raise ValueError ("TimeIntervals are not compatible." )
6168
6269 start = max (self .left , other .left )
6370 end = min (self .right , other .right )
6471
6572 return TimeInterval (start , end ) if start <= end else None
6673
6774
68- def is_compatible (t1 : datetime | cftime .datetime , t2 : datetime | cftime .datetime ) -> bool :
69- """Checks whether two (cftime.)datetime objects are compatible."""
75+ def is_compatible (
76+ t1 : datetime | cftime .datetime | np .timedelta64 , t2 : datetime | cftime .datetime | np .timedelta64
77+ ) -> bool :
78+ """
79+ Defines whether two datetime or np.timedelta64 objects are compatible in the context
80+ of being left and right sides of an interval.
81+ """
82+ # Ensure if either is a timedelta64, both must be
83+ if isinstance (t1 , np .timedelta64 ) ^ isinstance (t2 , np .timedelta64 ):
84+ return False
85+
7086 try :
7187 t1 - t2
7288 except Exception :
0 commit comments