45
45
TODAY_UTC ,
46
46
WEEK ,
47
47
YEAR ,
48
+ ZERO_TIME ,
49
+ AddDurationError ,
48
50
AddWeekdaysError ,
49
51
CheckDateNotDatetimeError ,
50
52
CheckZonedDatetimeError ,
51
- DateAddTimeDeltaError ,
52
53
EnsureMonthError ,
53
54
MillisecondsSinceEpochError ,
54
55
Month ,
57
58
TimedeltaToMillisecondsError ,
58
59
YieldDaysError ,
59
60
YieldWeekdaysError ,
61
+ add_duration ,
60
62
add_weekdays ,
61
63
check_date_not_datetime ,
62
64
check_zoned_datetime ,
63
- date_add_timedelta ,
64
65
date_to_datetime ,
65
66
date_to_month ,
67
+ datetime_duration_to_float ,
68
+ datetime_duration_to_timedelta ,
66
69
days_since_epoch ,
67
70
days_since_epoch_to_date ,
68
71
drop_microseconds ,
69
72
drop_milli_and_microseconds ,
70
- duration_to_float ,
71
- duration_to_timedelta ,
72
73
ensure_month ,
73
74
format_datetime_local_and_utc ,
74
75
get_half_years ,
84
85
is_equal_as_months ,
85
86
is_equal_mod_tz ,
86
87
is_instance_date_not_datetime ,
88
+ is_integral_timedelta ,
87
89
is_local_datetime ,
88
90
is_subclass_date_not_datetime ,
89
91
is_weekday ,
120
122
from utilities .types import Number
121
123
122
124
125
+ class TestAddDuration :
126
+ @given (date = dates (), days = integers ())
127
+ def test_date (self , * , date : dt .date , days : int ) -> None :
128
+ with assume_does_not_raise (OverflowError ):
129
+ timedelta = days * DAY
130
+ with assume_does_not_raise (OverflowError ):
131
+ result = add_duration (date , timedelta = timedelta )
132
+ assert is_instance_date_not_datetime (result )
133
+
134
+ @given (date = dates (), timedelta = timedeltas ())
135
+ def test_datetime (self , * , date : dt .date , days : int ) -> None :
136
+ with assume_does_not_raise (OverflowError ):
137
+ timedelta = days * DAY
138
+ with assume_does_not_raise (OverflowError ):
139
+ result = add_duration (date , timedelta = timedelta )
140
+ assert is_instance_date_not_datetime (result )
141
+
142
+ @given (date = dates ())
143
+ def test_none (self , * , date : dt .date ) -> None :
144
+ result = add_duration (date )
145
+ assert result == date
146
+
147
+ @given (date = dates ())
148
+ def test_error (self , * , date : dt .date ) -> None :
149
+ with raises (AddDurationError , match = "Timedelta must be day-only; got .*" ):
150
+ _ = add_duration (date , timedelta = SECOND )
151
+
152
+
123
153
class TestAddWeekdays :
124
154
@given (date = dates (), n = integers (- 10 , 10 ))
125
155
@mark .parametrize ("predicate" , [param (gt ), param (lt )])
@@ -178,26 +208,6 @@ def test_datetime(self, *, datetime: dt.datetime) -> None:
178
208
check_zoned_datetime (datetime )
179
209
180
210
181
- class TestDateAddTimedelta :
182
- @given (date = dates (), days = integers ())
183
- def test_main (self , * , date : dt .date , days : int ) -> None :
184
- with assume_does_not_raise (OverflowError ):
185
- timedelta = days * DAY
186
- with assume_does_not_raise (OverflowError ):
187
- result = date_add_timedelta (date , timedelta = timedelta )
188
- assert is_instance_date_not_datetime (result )
189
-
190
- @given (date = dates ())
191
- def test_none (self , * , date : dt .date ) -> None :
192
- result = date_add_timedelta (date )
193
- assert result == date
194
-
195
- @given (date = dates ())
196
- def test_error (self , * , date : dt .date ) -> None :
197
- with raises (DateAddTimeDeltaError , match = "Timedelta must be day-only; got .*" ):
198
- _ = date_add_timedelta (date , timedelta = SECOND )
199
-
200
-
201
211
class TestDateToDatetime :
202
212
@given (date = dates ())
203
213
def test_main (self , * , date : dt .date ) -> None :
@@ -212,6 +222,18 @@ def test_main(self, *, date: dt.date) -> None:
212
222
assert result == date
213
223
214
224
225
+ class TestDateTimeDurationToFloat :
226
+ @given (duration = integers (0 , 10 ) | floats (0.0 , 10.0 ))
227
+ def test_number (self , * , duration : Number ) -> None :
228
+ result = datetime_duration_to_float (duration )
229
+ assert result == duration
230
+
231
+ @given (duration = timedeltas ())
232
+ def test_timedelta (self , * , duration : dt .timedelta ) -> None :
233
+ result = datetime_duration_to_float (duration )
234
+ assert result == duration .total_seconds ()
235
+
236
+
215
237
class TestDaysSinceEpoch :
216
238
@given (date = dates ())
217
239
def test_datetime_to_microseconds (self , * , date : dt .date ) -> None :
@@ -235,33 +257,21 @@ def test_main(self, *, datetime: dt.datetime) -> None:
235
257
assert result .microsecond == 0
236
258
237
259
238
- class TestDurationToFloat :
239
- @given (duration = integers (0 , 10 ) | floats (0.0 , 10.0 ))
240
- def test_number (self , * , duration : Number ) -> None :
241
- result = duration_to_float (duration )
242
- assert result == duration
243
-
244
- @given (duration = timedeltas ())
245
- def test_timedelta (self , * , duration : dt .timedelta ) -> None :
246
- result = duration_to_float (duration )
247
- assert result == duration .total_seconds ()
248
-
249
-
250
260
class TestDurationToTimedelta :
251
261
@given (duration = integers (0 , 10 ))
252
262
def test_int (self , * , duration : int ) -> None :
253
- result = duration_to_timedelta (duration )
263
+ result = datetime_duration_to_timedelta (duration )
254
264
assert result .total_seconds () == duration
255
265
256
266
@given (duration = floats (0.0 , 10.0 ))
257
267
def test_float (self , * , duration : float ) -> None :
258
268
duration = round (10 * duration ) / 10
259
- result = duration_to_timedelta (duration )
269
+ result = datetime_duration_to_timedelta (duration )
260
270
assert isclose (result .total_seconds (), duration )
261
271
262
272
@given (duration = timedeltas ())
263
273
def test_timedelta (self , * , duration : dt .timedelta ) -> None :
264
- result = duration_to_timedelta (duration )
274
+ result = datetime_duration_to_timedelta (duration )
265
275
assert result == duration
266
276
267
277
@@ -428,6 +438,25 @@ def test_local_vs_zoned(
428
438
assert result is expected
429
439
430
440
441
+ class TestIsIntegralTimeDelta :
442
+ @given (n = integers ())
443
+ def test_integral (self , * , n : int ) -> None :
444
+ with assume_does_not_raise (OverflowError ):
445
+ timedelta = dt .timedelta (days = n )
446
+ assert is_integral_timedelta (timedelta )
447
+
448
+ @given (
449
+ n = integers (),
450
+ frac = timedeltas (
451
+ min_value = - (DAY - MICROSECOND ), max_value = DAY - MICROSECOND
452
+ ).filter (lambda x : x != ZERO_TIME ),
453
+ )
454
+ def test_non_integral (self , * , n : int , frac : dt .timedelta ) -> None :
455
+ with assume_does_not_raise (OverflowError ):
456
+ timedelta = dt .timedelta (days = n ) + frac
457
+ assert not is_integral_timedelta (timedelta )
458
+
459
+
431
460
class TestIsLocalDateTime :
432
461
@mark .parametrize (
433
462
("obj" , "expected" ),
0 commit comments