Functional Weave
Code in Python

time.iso-to-unix@1.0.0

impl/python.py

1,943 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from .dates_add_days import epoch_day_from_iso  ← from dates.add-days ^1.0.0 · built alongside by fune


def _is_digit(ch: str) -> bool:
    # A character range, not str.isdigit(), which accepts other scripts' digits.
    return "0" <= ch <= "9"


def iso_to_unix(timestamp: str) -> int:
    """An RFC 3339 date-time to Unix seconds, parsed by position.

    datetime.fromisoformat accepts more shapes than this (and fewer before
    3.11), so the rules are written out to match the other languages.
    """
    if not isinstance(timestamp, str):
        raise ValueError('"%s" is not an RFC 3339 timestamp such as 2026-09-26T12:00:00Z' % (timestamp,))
    t = timestamp

    def bad() -> ValueError:
        return ValueError('"%s" is not an RFC 3339 timestamp such as 2026-09-26T12:00:00Z' % (t,))

    if len(t) < 20:
        raise bad()
    for i in (0, 1, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18):
        if not _is_digit(t[i]):
            raise bad()
    if t[4] != "-" or t[7] != "-" or t[10] not in ("T", "t") or t[13] != ":" or t[16] != ":":
        raise bad()
    i = 19
    if t[i] == ".":
        i += 1
        start = i
        while i < len(t) and _is_digit(t[i]):
            i += 1
        if i == start:
            raise bad()
    if i < len(t) and t[i] in ("Z", "z") and i + 1 == len(t):
        offset = 0
    elif (
        i < len(t)
        and t[i] in ("+", "-")
        and i + 6 == len(t)
        and _is_digit(t[i + 1])
        and _is_digit(t[i + 2])
        and t[i + 3] == ":"
        and _is_digit(t[i + 4])
        and _is_digit(t[i + 5])
    ):
        oh = int(t[i + 1 : i + 3])
        om = int(t[i + 4 : i + 6])
        if oh > 23 or om > 59:
            raise bad()
        offset = (1 if t[i] == "+" else -1) * (oh * 3600 + om * 60)
    else:
        raise bad()
    h, m, s = int(t[11:13]), int(t[14:16]), int(t[17:19])
    if h > 23 or m > 59 or s > 59:
        raise bad()
    return epoch_day_from_iso(t[0:10]) * 86400 + h * 3600 + m * 60 + s - offset