Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions langfuse/_utils/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,5 @@ def _serialize_zoned_datetime(v: dt.datetime) -> str:
if v.tzinfo is not None:
return _serialize_zoned_datetime(v)
else:
local_tz = dt.datetime.now().astimezone().tzinfo
localized_dt = v.replace(tzinfo=local_tz)
localized_dt = v.astimezone()
return _serialize_zoned_datetime(localized_dt)
40 changes: 40 additions & 0 deletions tests/unit/test_serializer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import threading
import time
from dataclasses import dataclass
from datetime import date, datetime, timezone
from enum import Enum
Expand Down Expand Up @@ -41,6 +42,45 @@ def test_datetime():
assert serializer.encode(dt) == '"2023-01-01T12:00:00Z"'


@pytest.mark.skipif(
not hasattr(time, "tzset"), reason="Requires local timezone control"
)
@pytest.mark.parametrize(
("value", "expected"),
[
(datetime(2026, 1, 15, 12), "2026-01-15T12:00:00-08:00"),
(datetime(2026, 7, 15, 12), "2026-07-15T12:00:00-07:00"),
(datetime(2026, 11, 1, 1, 30, fold=0), "2026-11-01T01:30:00-07:00"),
(datetime(2026, 11, 1, 1, 30, fold=1), "2026-11-01T01:30:00-08:00"),
],
)
def test_naive_datetime_uses_offset_at_its_own_date(
monkeypatch, value, expected, langfuse_memory_client, get_span
):
try:
with monkeypatch.context() as context:
context.setenv("TZ", "America/Los_Angeles")
time.tzset()
serialized = json.loads(EventSerializer().encode(value))
assert serialized == expected
assert datetime.fromisoformat(serialized).timestamp() == value.timestamp()
with langfuse_memory_client.start_as_current_observation(
name="historical-generation", as_type="generation"
) as generation:
generation.update(completion_start_time=value)
langfuse_memory_client.flush()
assert (
json.loads(
get_span("historical-generation").attributes[
"langfuse.observation.completion_start_time"
]
)
== expected
)
finally:
time.tzset()


def test_date():
d = date(2023, 1, 1)
serializer = EventSerializer()
Expand Down