Source code for calendaring_jmap.objects.busy_interval
# SPDX-FileCopyrightText: 2026 calendaring-jmap contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
JMAP BusyPeriod object.
Represents one interval of a ``Principal/getAvailability`` response
(draft-ietf-jmap-calendars section 2.2), or one computed client-side by the
``CalendarEvent/query`` fallback path when a server doesn't implement that
method. Read-only: nothing here is ever sent back to the server, so there
is no ``to_jmap``.
"""
from __future__ import annotations
from dataclasses import dataclass
from calendaring_jmap.constants import BUSY_STATUS_UNAVAILABLE
from calendaring_jmap.objects.calendar_object import JMAPCalendarObject
[docs]
@dataclass
class BusyInterval:
"""One busy/free interval.
Attributes:
start: Start of the interval (``UTCDateTime`` string, always
``Z``-suffixed). Normalized to this one shape regardless of
whether it came from ``Principal/getAvailability`` or the
``CalendarEvent/query`` fallback, since :rfc:`8984` allows a
JSCalendar ``start`` to be UTC, time-zone-qualified, or
floating; a floating start has no true UTC equivalent and is
treated as UTC.
end: End of the interval (``UTCDateTime`` string), same
normalization as ``start``.
busy_status: One of ``"confirmed"``, ``"tentative"``,
``"unavailable"`` (see ``constants.BUSY_STATUS_*``).
event: The underlying event, when the server populated it. This can
be ``None`` even when details were requested: confirmed live
that this happens when the caller lacks ``mayReadItems``, the
event is marked private, or (Stalwart-specific) the caller
didn't also pass a server-supported ``eventProperties`` list.
"""
start: str
end: str
busy_status: str
event: JMAPCalendarObject | None = None
[docs]
@classmethod
def from_jmap(cls, data: dict) -> BusyInterval:
"""Construct a BusyInterval from a raw JMAP BusyPeriod JSON dict.
Unknown keys in ``data`` are silently ignored so that forward
compatibility is maintained as the spec evolves.
"""
event_data = data.get("event")
return cls(
start=data["utcStart"],
end=data["utcEnd"],
busy_status=data.get("busyStatus", BUSY_STATUS_UNAVAILABLE),
event=JMAPCalendarObject(data=event_data, parent=None)
if event_data is not None
else None,
)