Skip to content

Time

Functions for working with time.


from_isoformat_8601

from_isoformat_8601(iso8601_str)

Convert ISO Format datetime string into a datetime object

Example Strings
  • 2022-06-09T06:58:14
  • 2022-06-09T06:58:14Z
  • 2022-06-09T06:58:14+11:00
  • 2022-06-09T06:58:14.000
  • 2022-06-09T06:58:14.000Z
  • 2022-06-09T06:58:14.000+11:00

Parameters:

Name Type Description Default
iso8601_str str

datetime string

required

Returns:

Type Description
datetime

dt.datetime

Source code in src/aibs_informatics_core/utils/time.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
def from_isoformat_8601(iso8601_str: str) -> dt.datetime:
    """Convert ISO Format datetime string into a datetime object

    Example Strings:
        - 2022-06-09T06:58:14
        - 2022-06-09T06:58:14Z
        - 2022-06-09T06:58:14+11:00
        - 2022-06-09T06:58:14.000
        - 2022-06-09T06:58:14.000Z
        - 2022-06-09T06:58:14.000+11:00

    Args:
        iso8601_str (str): datetime string

    Returns:
        dt.datetime
    """
    fmt = "%Y-%m-%dT%H:%M:%S.%f" if "." in iso8601_str else "%Y-%m-%dT%H:%M:%S"

    if len(iso8601_str) < 6:
        raise ValueError(f"{iso8601_str} does not match {fmt}")
    elif iso8601_str[-6] in frozenset(("+", "-")):
        fmt = fmt + "%z"
    elif iso8601_str[-1] == "Z":
        fmt = fmt + "Z"
    result = dt.datetime.strptime(iso8601_str, fmt)
    # strptime treats 'Z' as a literal, producing a naive datetime.
    # Since Z unambiguously means UTC, attach the UTC tzinfo.
    if result.tzinfo is None and iso8601_str[-1] == "Z":
        result = result.replace(tzinfo=dt.timezone.utc)
    return result

get_current_time

get_current_time(tz=None)

Return the current time as a timezone-aware datetime.

Parameters:

Name Type Description Default
tz timezone | None

Timezone to use. Defaults to UTC.

None

Returns:

Type Description
datetime

The current datetime in the specified timezone.

Source code in src/aibs_informatics_core/utils/time.py
15
16
17
18
19
20
21
22
23
24
def get_current_time(tz: dt.timezone | None = None) -> dt.datetime:
    """Return the current time as a timezone-aware datetime.

    Args:
        tz: Timezone to use. Defaults to UTC.

    Returns:
        The current ``datetime`` in the specified timezone.
    """
    return dt.datetime.now(tz=tz or dt.timezone.utc)

get_duration_in_secs

get_duration_in_secs(start, stop=None)

Calculate the duration between two datetimes in seconds.

Parameters:

Name Type Description Default
start datetime

Start datetime.

required
stop datetime | None

End datetime. Defaults to the current time.

None

Returns:

Type Description
int

The rounded number of seconds between start and stop.

Source code in src/aibs_informatics_core/utils/time.py
27
28
29
30
31
32
33
34
35
36
37
def get_duration_in_secs(start: dt.datetime, stop: dt.datetime | None = None) -> int:
    """Calculate the duration between two datetimes in seconds.

    Args:
        start: Start datetime.
        stop: End datetime. Defaults to the current time.

    Returns:
        The rounded number of seconds between ``start`` and ``stop``.
    """
    return round(((stop or get_current_time()) - start).total_seconds())

to_zulu_isoformat_8601

to_zulu_isoformat_8601(value, naive_handling='coerce')

Convert a datetime object or ISO 8601 string to a Zulu ISO 8601 formatted string.

Parameters:

Name Type Description Default
value datetime | str

The datetime object or ISO 8601 string to convert.

required
naive_handling Literal['coerce', 'error']

How to handle naive (timezone-unaware) datetimes. "coerce" (default) treats them as UTC. "error" raises a :class:ValueError.

'coerce'

Returns:

Type Description
str

The Zulu ISO 8601 formatted string.

Raises:

Type Description
ValueError

If naive_handling is "error" and the datetime is naive.

Source code in src/aibs_informatics_core/utils/time.py
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
def to_zulu_isoformat_8601(
    value: dt.datetime | str,
    naive_handling: Literal["coerce", "error"] = "coerce",
) -> str:
    """Convert a datetime object or ISO 8601 string to a Zulu ISO 8601 formatted string.

    Args:
        value: The datetime object or ISO 8601 string to convert.
        naive_handling: How to handle naive (timezone-unaware) datetimes.
            ``"coerce"`` (default) treats them as UTC.
            ``"error"`` raises a :class:`ValueError`.

    Returns:
        The Zulu ISO 8601 formatted string.

    Raises:
        ValueError: If *naive_handling* is ``"error"`` and the datetime is naive.
    """
    dt_obj = from_isoformat_8601(value) if isinstance(value, str) else value
    if dt_obj.tzinfo is None:
        if naive_handling == "error":
            raise ValueError(
                "Naive datetime provided but naive_handling='error'. "
                "Supply a timezone-aware datetime or use naive_handling='coerce'."
            )
        dt_obj = dt_obj.replace(tzinfo=dt.timezone.utc)
    return dt_obj.astimezone(dt.timezone.utc).isoformat().replace("+00:00", "Z")