|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
| 3 | +import re |
3 | 4 | from datetime import UTC, datetime, timedelta, timezone |
4 | 5 | from math import fmod |
5 | 6 | from typing import Any, SupportsFloat, SupportsIndex, SupportsInt, overload |
@@ -189,10 +190,26 @@ def timedelta_total_microseconds(td: timedelta) -> int: |
189 | 190 | return td.days * (24 * 3600) + td.seconds * 10**6 + td.microseconds |
190 | 191 |
|
191 | 192 |
|
192 | | -def parse(string: str, detectUTC: bool = False) -> DateTimeOffset: |
193 | | - from dateutil import parser # noqa: PLC0415 - lazy import to avoid top-level dependency |
| 193 | +_NON_ISO_FORMATS: dict[str, str] = { |
| 194 | + # 9/10/2014 1:50:34 PM |
| 195 | + r"^(0?[1-9]|1[0-2])\/(0?[1-9]|1[0-2])\/\d{4} ([0-9]|(0|1)[0-9]|2[0-4]):([0-5][0-9]|0?[0-9]):([0-5][0-9]|0?[0-9]) [AP]M$": "%m/%d/%Y %I:%M:%S %p", |
| 196 | + # 9/10/2014 1:50:34 |
| 197 | + r"^(0?[1-9]|1[0-2])\/(0?[1-9]|1[0-2])\/\d{4} ([0-9]|(0|1)[0-9]|2[0-4]):([0-5][0-9]|0?[0-9]):([0-5][0-9]|0?[0-9])$": "%m/%d/%Y %H:%M:%S", |
| 198 | +} |
| 199 | + |
| 200 | + |
| 201 | +def _parse_non_iso(string: str) -> datetime: |
| 202 | + for pattern, fmt in _NON_ISO_FORMATS.items(): |
| 203 | + if re.fullmatch(pattern, string): |
| 204 | + return datetime.strptime(string, fmt) |
| 205 | + raise ValueError(f"Unsupported format by Fable: {string}") |
194 | 206 |
|
195 | | - parsed_dt = parser.parse(string) |
| 207 | + |
| 208 | +def parse(string: str, detectUTC: bool = False) -> DateTimeOffset: |
| 209 | + try: |
| 210 | + parsed_dt = datetime.fromisoformat(string) |
| 211 | + except ValueError: |
| 212 | + parsed_dt = _parse_non_iso(string) |
196 | 213 |
|
197 | 214 | # Calculate offset in milliseconds |
198 | 215 | if parsed_dt.tzinfo is not None: |
|
0 commit comments