0
# DateTime Types
1
2
Date and time comparison classes with support for approximate matching, range validation, timezone handling, and format parsing. These types enable flexible validation of temporal data including relative time comparisons and format-aware parsing.
3
4
## Capabilities
5
6
### IsDatetime
7
8
Comprehensive datetime comparison with multiple constraint options including approximate matching, range bounds, timezone enforcement, and format parsing from strings or Unix timestamps.
9
10
```python { .api }
11
class IsDatetime(DirtyEquals):
12
"""
13
Datetime comparison with configurable conditions.
14
15
Supports range checking, approximate matching, timezone validation,
16
and parsing from various string and numeric formats.
17
"""
18
19
def __init__(
20
self,
21
*,
22
approx: Optional[datetime] = None,
23
delta: Optional[Union[int, float, timedelta]] = None,
24
gt: Optional[datetime] = None,
25
lt: Optional[datetime] = None,
26
ge: Optional[datetime] = None,
27
le: Optional[datetime] = None,
28
unix_number: bool = False,
29
iso_string: bool = False,
30
format_string: Optional[str] = None,
31
enforce_tz: bool = False
32
):
33
"""
34
Initialize datetime comparison with constraints.
35
36
Args:
37
approx: Expected datetime for approximate comparison
38
delta: Tolerance for approximate comparison (seconds or timedelta)
39
gt: Value must be greater than this datetime
40
lt: Value must be less than this datetime
41
ge: Value must be greater than or equal to this datetime
42
le: Value must be less than or equal to this datetime
43
unix_number: If True, parse numeric values as Unix timestamps
44
iso_string: If True, parse strings as ISO format datetimes
45
format_string: Custom strptime format for parsing strings
46
enforce_tz: If True, require timezone information
47
"""
48
49
allowed_types: ClassVar[type] = datetime
50
51
def prepare(self) -> None:
52
"""Prepare constraints for comparison validation."""
53
54
def approx_equals(self, other: datetime, delta: timedelta) -> bool:
55
"""
56
Check if datetime is within delta of expected value.
57
58
Args:
59
other: Datetime to compare
60
delta: Maximum allowed difference
61
62
Returns:
63
bool: True if within tolerance
64
"""
65
66
def equals(self, other: Any) -> bool:
67
"""
68
Check if value matches datetime constraints.
69
70
Args:
71
other: Value to validate (datetime, string, or number)
72
73
Returns:
74
bool: True if value satisfies all conditions
75
"""
76
```
77
78
#### Usage Examples
79
80
```python
81
from dirty_equals import IsDatetime
82
from datetime import datetime, timedelta
83
84
# Basic datetime matching
85
now = datetime.now()
86
assert now == IsDatetime
87
88
# Approximate matching - within 5 seconds
89
target_time = datetime(2023, 1, 1, 12, 0, 0)
90
close_time = datetime(2023, 1, 1, 12, 0, 3)
91
assert close_time == IsDatetime(approx=target_time, delta=5)
92
93
# Range constraints
94
past_date = datetime(2022, 1, 1)
95
future_date = datetime(2024, 1, 1)
96
test_date = datetime(2023, 6, 15)
97
98
assert test_date == IsDatetime(gt=past_date, lt=future_date)
99
assert test_date == IsDatetime(ge=past_date, le=future_date)
100
101
# Parse from Unix timestamp
102
import time
103
timestamp = time.time()
104
assert timestamp == IsDatetime(unix_number=True)
105
106
# Parse from ISO string
107
iso_string = "2023-01-01T12:00:00"
108
assert iso_string == IsDatetime(iso_string=True)
109
110
# Parse with custom format
111
date_string = "2023/01/01 12:00:00"
112
assert date_string == IsDatetime(format_string="%Y/%m/%d %H:%M:%S")
113
114
# Timezone enforcement
115
from datetime import timezone
116
utc_time = datetime.now(timezone.utc)
117
naive_time = datetime.now()
118
119
assert utc_time == IsDatetime(enforce_tz=True)
120
# assert naive_time == IsDatetime(enforce_tz=True) # Would fail
121
122
# Complex validation in data structures
123
api_response = {
124
'created_at': '2023-01-01T12:00:00Z',
125
'updated_at': datetime.now(),
126
'expires_at': time.time() + 3600 # 1 hour from now
127
}
128
129
assert api_response == {
130
'created_at': IsDatetime(iso_string=True),
131
'updated_at': IsDatetime(approx=datetime.now(), delta=30),
132
'expires_at': IsDatetime(unix_number=True, gt=datetime.now())
133
}
134
```
135
136
### IsNow
137
138
Checks if a datetime is close to the current time with configurable tolerance. Useful for validating timestamps that should represent "now" within a reasonable margin.
139
140
```python { .api }
141
class IsNow(DirtyEquals):
142
"""
143
Checks if datetime is close to current time.
144
145
Validates that a datetime value is within a specified tolerance
146
of the current moment, with support for parsing and timezone handling.
147
"""
148
149
def __init__(
150
self,
151
*,
152
delta: Union[int, float, timedelta] = 2,
153
unix_number: bool = False,
154
iso_string: bool = False,
155
format_string: Optional[str] = None,
156
enforce_tz: bool = False,
157
tz: Optional[timezone] = None
158
):
159
"""
160
Initialize "now" comparison.
161
162
Args:
163
delta: Maximum allowed difference from current time (default 2 seconds)
164
unix_number: If True, parse numeric values as Unix timestamps
165
iso_string: If True, parse strings as ISO format datetimes
166
format_string: Custom strptime format for parsing strings
167
enforce_tz: If True, require timezone information
168
tz: Specific timezone to use for "now" calculation
169
"""
170
171
def _get_now(self) -> datetime:
172
"""
173
Get current datetime for comparison.
174
175
Returns:
176
datetime: Current time in appropriate timezone
177
"""
178
179
def equals(self, other: Any) -> bool:
180
"""
181
Check if value is close to current time.
182
183
Args:
184
other: Value to check (datetime, string, or number)
185
186
Returns:
187
bool: True if within delta of current time
188
"""
189
```
190
191
#### Usage Examples
192
193
```python
194
from dirty_equals import IsNow
195
from datetime import datetime, timedelta
196
import time
197
198
# Basic "now" checking with default 2-second tolerance
199
current_time = datetime.now()
200
assert current_time == IsNow
201
202
# Custom tolerance - within 10 seconds
203
slightly_past = datetime.now() - timedelta(seconds=5)
204
assert slightly_past == IsNow(delta=10)
205
206
# Parse timestamp as "now"
207
current_timestamp = time.time()
208
assert current_timestamp == IsNow(unix_number=True)
209
210
# Parse ISO string as "now"
211
import json
212
now_iso = datetime.now().isoformat()
213
assert now_iso == IsNow(iso_string=True)
214
215
# With timezone
216
from datetime import timezone
217
utc_now = datetime.now(timezone.utc)
218
assert utc_now == IsNow(tz=timezone.utc, delta=5)
219
220
# In API testing
221
user_registration = {
222
'username': 'john_doe',
223
'email': 'john@example.com',
224
'created_at': datetime.now(),
225
'last_login': time.time()
226
}
227
228
assert user_registration == {
229
'username': 'john_doe',
230
'email': 'john@example.com',
231
'created_at': IsNow(delta=30), # Created within last 30 seconds
232
'last_login': IsNow(unix_number=True, delta=60) # Logged in within last minute
233
}
234
235
# Database record validation
236
db_record = {
237
'id': 123,
238
'updated_timestamp': '2023-01-01T12:00:00.123Z',
239
'sync_time': datetime.now()
240
}
241
242
# Validate recent updates
243
assert db_record == {
244
'id': 123,
245
'updated_timestamp': IsNow(iso_string=True, delta=300), # Within 5 minutes
246
'sync_time': IsNow(delta=10) # Synced within 10 seconds
247
}
248
```
249
250
### IsDate
251
252
Date comparison with support for range constraints, approximate matching, and parsing from string formats. Works specifically with date objects and date components of datetime objects.
253
254
```python { .api }
255
class IsDate(DirtyEquals):
256
"""
257
Date comparison with configurable conditions.
258
259
Supports range checking, approximate matching, and parsing from
260
various string formats for date validation.
261
"""
262
263
def __init__(
264
self,
265
*,
266
approx: Optional[date] = None,
267
delta: Optional[Union[int, timedelta]] = None,
268
gt: Optional[date] = None,
269
lt: Optional[date] = None,
270
ge: Optional[date] = None,
271
le: Optional[date] = None,
272
iso_string: bool = False,
273
format_string: Optional[str] = None
274
):
275
"""
276
Initialize date comparison with constraints.
277
278
Args:
279
approx: Expected date for approximate comparison
280
delta: Tolerance for approximate comparison (days or timedelta)
281
gt: Value must be greater than this date
282
lt: Value must be less than this date
283
ge: Value must be greater than or equal to this date
284
le: Value must be less than or equal to this date
285
iso_string: If True, parse strings as ISO format dates
286
format_string: Custom strptime format for parsing strings
287
"""
288
289
allowed_types: ClassVar[type] = date
290
291
def prepare(self) -> None:
292
"""Prepare constraints for comparison validation."""
293
294
def equals(self, other: Any) -> bool:
295
"""
296
Check if value matches date constraints.
297
298
Args:
299
other: Value to validate (date, datetime, or string)
300
301
Returns:
302
bool: True if value satisfies all conditions
303
"""
304
```
305
306
#### Usage Examples
307
308
```python
309
from dirty_equals import IsDate
310
from datetime import date, timedelta
311
312
# Basic date matching
313
today = date.today()
314
assert today == IsDate
315
316
# Approximate matching - within 2 days
317
target_date = date(2023, 1, 15)
318
close_date = date(2023, 1, 16)
319
assert close_date == IsDate(approx=target_date, delta=2)
320
321
# Range constraints
322
start_date = date(2023, 1, 1)
323
end_date = date(2023, 12, 31)
324
test_date = date(2023, 6, 15)
325
326
assert test_date == IsDate(gt=start_date, lt=end_date)
327
assert test_date == IsDate(ge=start_date, le=end_date)
328
329
# Parse from ISO string
330
date_string = "2023-01-15"
331
assert date_string == IsDate(iso_string=True)
332
333
# Parse with custom format
334
date_string = "01/15/2023"
335
assert date_string == IsDate(format_string="%m/%d/%Y")
336
337
# Extract date from datetime
338
from datetime import datetime
339
dt = datetime(2023, 1, 15, 14, 30, 0)
340
assert dt == IsDate(approx=date(2023, 1, 15))
341
342
# In data validation
343
event_data = {
344
'title': 'Conference',
345
'start_date': '2023-06-15',
346
'end_date': date(2023, 6, 17),
347
'registration_deadline': datetime(2023, 6, 1, 23, 59, 59)
348
}
349
350
assert event_data == {
351
'title': 'Conference',
352
'start_date': IsDate(iso_string=True, ge=date.today()),
353
'end_date': IsDate(gt=date(2023, 6, 15)), # After start date
354
'registration_deadline': IsDate(lt=date(2023, 6, 15)) # Before start
355
}
356
```
357
358
### IsToday
359
360
Checks if a date represents today's date, with support for parsing from string formats. Useful for validating that dates represent the current day.
361
362
```python { .api }
363
class IsToday(DirtyEquals):
364
"""
365
Checks if date is today.
366
367
Validates that a date value represents the current date,
368
with support for string parsing.
369
"""
370
371
def __init__(
372
self,
373
*,
374
iso_string: bool = False,
375
format_string: Optional[str] = None
376
):
377
"""
378
Initialize today comparison.
379
380
Args:
381
iso_string: If True, parse strings as ISO format dates
382
format_string: Custom strptime format for parsing strings
383
"""
384
385
def equals(self, other: Any) -> bool:
386
"""
387
Check if value represents today's date.
388
389
Args:
390
other: Value to check (date, datetime, or string)
391
392
Returns:
393
bool: True if value represents today
394
"""
395
```
396
397
#### Usage Examples
398
399
```python
400
from dirty_equals import IsToday
401
from datetime import date, datetime
402
403
# Basic today checking
404
today = date.today()
405
assert today == IsToday
406
407
# Works with datetime objects (uses date part)
408
now = datetime.now()
409
assert now == IsToday
410
411
# Parse from ISO string
412
today_string = date.today().isoformat()
413
assert today_string == IsToday(iso_string=True)
414
415
# Parse with custom format
416
today_formatted = date.today().strftime("%m/%d/%Y")
417
assert today_formatted == IsToday(format_string="%m/%d/%Y")
418
419
# In logging/audit validation
420
log_entry = {
421
'user_id': 123,
422
'action': 'login',
423
'timestamp': datetime.now(),
424
'date': date.today().isoformat()
425
}
426
427
assert log_entry == {
428
'user_id': 123,
429
'action': 'login',
430
'timestamp': IsToday, # Timestamp should be today
431
'date': IsToday(iso_string=True) # Date field should be today
432
}
433
434
# Daily report validation
435
daily_stats = {
436
'report_date': '2023-01-15',
437
'generated_at': datetime.now(),
438
'stats': {'users': 100, 'orders': 25}
439
}
440
441
# Validate this is today's report
442
assert daily_stats == {
443
'report_date': IsToday(iso_string=True),
444
'generated_at': IsToday,
445
'stats': {'users': 100, 'orders': 25}
446
}
447
```
448
449
## Type Definitions
450
451
```python { .api }
452
from typing import Any, ClassVar, Optional, Union
453
from datetime import datetime, date, timedelta, timezone
454
455
# All datetime types inherit from DirtyEquals
456
# and work with Python's standard datetime/date types
457
```