Skip to content

Commit fdbedc1

Browse files
committed
Prefer using built-in wrappers for timestamps & durations
1 parent 7eebe4c commit fdbedc1

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

src/dispatch/any.py

+17
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
from __future__ import annotations
22

33
import pickle
4+
from datetime import UTC, datetime, timedelta
45
from typing import Any
56

67
import google.protobuf.any_pb2
8+
import google.protobuf.duration_pb2
79
import google.protobuf.empty_pb2
810
import google.protobuf.message
11+
import google.protobuf.timestamp_pb2
912
import google.protobuf.wrappers_pb2
1013
from google.protobuf import descriptor_pool, message_factory
1114

@@ -30,6 +33,16 @@ def marshal_any(value: Any) -> google.protobuf.any_pb2.Any:
3033
value = google.protobuf.wrappers_pb2.StringValue(value=value)
3134
elif isinstance(value, bytes):
3235
value = google.protobuf.wrappers_pb2.BytesValue(value=value)
36+
elif isinstance(value, datetime):
37+
# Note: datetime only supports microsecond granularity
38+
seconds = int(value.timestamp())
39+
nanos = value.microsecond * 1000
40+
value = google.protobuf.timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
41+
elif isinstance(value, timedelta):
42+
# Note: timedelta only supports microsecond granularity
43+
seconds = int(value.total_seconds())
44+
nanos = value.microseconds * 1000
45+
value = google.protobuf.duration_pb2.Duration(seconds=seconds, nanos=nanos)
3346

3447
if not isinstance(value, google.protobuf.message.Message):
3548
value = pickled_pb.Pickled(pickled_value=pickle.dumps(value))
@@ -76,5 +89,9 @@ def unmarshal_any(any: google.protobuf.any_pb2.Any) -> Any:
7689
except Exception as e:
7790
# Otherwise, return the literal bytes.
7891
return proto.value
92+
elif isinstance(proto, google.protobuf.timestamp_pb2.Timestamp):
93+
return proto.ToDatetime(tzinfo=UTC)
94+
elif isinstance(proto, google.protobuf.duration_pb2.Duration):
95+
return proto.ToTimedelta()
7996

8097
return proto

tests/dispatch/test_any.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import pickle
2-
from datetime import datetime, timedelta
2+
from datetime import UTC, datetime, timedelta
33

44
from dispatch.any import INT64_MAX, INT64_MIN, marshal_any, unmarshal_any
55
from dispatch.sdk.v1 import error_pb2 as error_pb
@@ -70,16 +70,16 @@ def test_unmarshal_bytes():
7070

7171

7272
def test_unmarshal_timestamp():
73-
ts = datetime.fromtimestamp(
74-
1719372909.641448
75-
) # datetime.datetime(2024, 6, 26, 13, 35, 9, 641448)
73+
ts = datetime.fromtimestamp(1719372909.641448, UTC)
7674
boxed = marshal_any(ts)
75+
assert "type.googleapis.com/google.protobuf.Timestamp" == boxed.type_url
7776
assert ts == unmarshal_any(boxed)
7877

7978

8079
def test_unmarshal_duration():
8180
d = timedelta(seconds=1, microseconds=1234)
8281
boxed = marshal_any(d)
82+
assert "type.googleapis.com/google.protobuf.Duration" == boxed.type_url
8383
assert d == unmarshal_any(boxed)
8484

8585

0 commit comments

Comments
 (0)