DateTime
SUMMARY
An absolute timezone-aware wall-clock datetime.
from datetime import datetime, timezone
from telekinesis import datatypes
value = datatypes.DateTime(datetime.now(timezone.utc))Parameters
| Field | Type | Description |
|---|---|---|
data | datetime.datetime | A timezone-aware datetime, normalized to UTC on storage. Intended for metadata such as created_at/updated_at/deleted_at. Unlike Timestamp, DateTime has timezone semantics rather than an arbitrary clock epoch. |
Raises
| Exception | Condition |
|---|---|
TypeError | data is not a datetime.datetime |
ValueError | data is naive (tzinfo is None, or utcoffset() is None) |
Attributes
| Attribute | Type | Description |
|---|---|---|
data | datetime.datetime | The wrapped value, converted to UTC (tzinfo=timezone.utc) via astimezone. Since datetime.datetime is immutable, no copying is ever required — reading data returns the normalized value directly. Assigning a new value re-validates and re-normalizes it the same way as construction. |
Methods
| Method | Description |
|---|---|
DateTime.coerce(value, name="value") | Returns value unchanged if it's already a DateTime; otherwise wraps a timezone-aware datetime.datetime. name sets the label used to identify the value in a raised error message. Raises TypeError if value is neither a DateTime nor a datetime.datetime, or ValueError if it's a naive datetime.datetime. |
Operators
| Operation | Returns |
|---|---|
a == b | bool |
a != b | bool |
a < b | bool |
a > b | bool |
==/< accept a DateTime or a datetime.datetime on the right-hand side; comparing against a naive datetime.datetime raises ValueError rather than returning False/NotImplemented, since normalization is attempted before comparing. > works only through Python's automatic reflected fallback to __lt__ — there is no explicit __gt__. <= and >= are intentionally not implemented and raise TypeError. Because .data is a real datetime.datetime, arithmetic like value.data - other_datetime works directly through Python's datetime API and returns a timedelta. Not hashable (__hash__ is None) — data is mutable via its setter.
Visualization
datatypes.visualize(value, entity_path=...) renders the value as text — the human-readable UTC form (e.g. "2026-08-06 12:34:56.789012+00:00"), rather than a numeric epoch.
Example
"""Demonstrates the Telekinesis DateTime datatype."""
import time
from datetime import datetime, timedelta, timezone
import rerun as rr
from loguru import logger
from telekinesis import datatypes
def datetime_example():
"""Demonstrate creation, inspection, operations, visualization, and serialization."""
# ======================= Create ============================================
created_at = datatypes.DateTime(datetime.now(timezone.utc))
logger.info(f"Created DateTime: {created_at}")
coerced = datatypes.DateTime.coerce(datetime.now(timezone.utc))
logger.info(f"DateTime coerced from datetime: {coerced}")
# ======================= Inspect ===========================================
logger.info(f"data={created_at.data}")
# ======================= Operations ========================================
created_at.data = created_at.data + timedelta(minutes=5)
logger.info(f"Updated DateTime: {created_at}")
# Any timezone-aware datetime is accepted; it is normalized to UTC on storage.
pst = datatypes.DateTime(datetime.now(timezone(timedelta(hours=-8))))
logger.info(f"DateTime from PST input, normalized to UTC: {pst}")
earlier = datatypes.DateTime(created_at.data - timedelta(minutes=1))
logger.info(f"EQ: {created_at} == {created_at} = {created_at == created_at}")
logger.info(f"LT: {earlier} < {created_at} = {earlier < created_at}")
logger.info(f"GT (via reflected __lt__): {created_at} > {earlier} = {created_at > earlier}")
# ======================= Visualize =========================================
rr.init("datetime_example", spawn=True)
datatypes.visualize(created_at, entity_path="/datetime/updated")
datatypes.visualize(pst, entity_path="/datetime/pst")
# ======================= Serialize / Deserialize ===========================
start = time.perf_counter()
serialized = datatypes.serialize(created_at)
serialization_ms = (time.perf_counter() - start) * 1000
start = time.perf_counter()
deserialized = datatypes.deserialize(serialized)["param_0"]
deserialization_ms = (time.perf_counter() - start) * 1000
logger.info(f"Deserialized DateTime: {deserialized}")
logger.info(f"Round-trip successful: {created_at == deserialized}")
logger.info(f"Serialization time: {serialization_ms:.3f} ms")
logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")
if __name__ == "__main__":
datetime_example()
