|
10 | 10 | WrapSerializer, |
11 | 11 | ) |
12 | 12 |
|
| 13 | +_DatetimeTuple = tuple[datetime | None, datetime | None] |
13 | 14 |
|
14 | | -def validate_before( |
15 | | - value: str | tuple[datetime, datetime], |
16 | | -) -> tuple[datetime, datetime]: |
| 15 | + |
| 16 | +def validate_before(value: str | _DatetimeTuple) -> _DatetimeTuple: |
17 | 17 | if isinstance(value, str): |
18 | | - start, end = value.split("/", 1) |
19 | | - return (datetime.fromisoformat(start), datetime.fromisoformat(end)) |
| 18 | + start_str, end_str = value.split("/", 1) |
| 19 | + start = None if start_str == ".." else datetime.fromisoformat(start_str) |
| 20 | + end = None if end_str == ".." else datetime.fromisoformat(end_str) |
| 21 | + value = (start, end) |
20 | 22 | return value |
21 | 23 |
|
22 | 24 |
|
23 | | -def validate_after(value: tuple[datetime, datetime]) -> tuple[datetime, datetime]: |
24 | | - if value[1] < value[0]: |
| 25 | +def validate_after(value: _DatetimeTuple) -> _DatetimeTuple: |
| 26 | + # None/date & date/None are always valid |
| 27 | + if value[1] and value[0] and value[1] < value[0]: |
25 | 28 | raise ValueError("end before start") |
26 | 29 | return value |
27 | 30 |
|
28 | 31 |
|
29 | 32 | def serialize( |
30 | | - value: tuple[datetime, datetime], |
31 | | - serializer: Callable[[tuple[datetime, datetime]], tuple[str, str]], |
| 33 | + value: _DatetimeTuple, |
| 34 | + serializer: Callable[[_DatetimeTuple], tuple[str, str]], |
32 | 35 | ) -> str: |
33 | 36 | del serializer # unused |
34 | | - return f"{value[0].isoformat()}/{value[1].isoformat()}" |
| 37 | + start = value[0].isoformat() if value[0] else ".." |
| 38 | + end = value[1].isoformat() if value[1] else ".." |
| 39 | + return f"{start}/{end}" |
35 | 40 |
|
36 | 41 |
|
37 | 42 | DatetimeInterval = Annotated[ |
38 | | - tuple[AwareDatetime, AwareDatetime], |
| 43 | + tuple[AwareDatetime | None, AwareDatetime | None], |
39 | 44 | BeforeValidator(validate_before), |
40 | 45 | AfterValidator(validate_after), |
41 | 46 | WrapSerializer(serialize, return_type=str), |
|
0 commit comments