Coverage for src/mlopus/utils/time_utils.py: 100%
15 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-07-13 14:49 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2025-07-13 14:49 +0000
1import re
2from datetime import datetime
3from typing import TypeVar
5import pytz
7T = TypeVar("T") # Any type
10class Patterns:
11 """Datetime patterns."""
13 SAFE_REPR = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+00:00$") # Match output format of `safe_repr`
16def to_utc(dt: datetime) -> datetime:
17 """Get equivalent datetime in UTC.
19 Example:
20 utc_plus_2 = pytz.FixedOffset(+2 * 60)
22 noon = datetime(2024, 4, 1, 12)
24 noon_in_berlin = utc_plus_2.localize(noon)
26 to_utc(noon_in_berlin) # 10 AM
27 """
28 return dt.astimezone(pytz.utc)
31def safe_repr(dt: datetime) -> str:
32 """Get safe string representation of datetime (UTC ISO with microseconds precision.)
34 This representation is lossless, independent of locale and preserves datetime sorting.
35 """
36 return to_utc(dt).isoformat(timespec="microseconds")
39def maybe_parse_safe_repr(val: T) -> T | datetime:
40 """Parse safe datetime representation if matches, no change otherwise."""
41 if isinstance(val, str) and Patterns.SAFE_REPR.fullmatch(val):
42 val = datetime.fromisoformat(val)
43 return val