1
1
from __future__ import annotations
2
2
3
3
import pickle
4
+ from datetime import UTC , datetime , timedelta
4
5
from typing import Any
5
6
6
7
import google .protobuf .any_pb2
8
+ import google .protobuf .duration_pb2
7
9
import google .protobuf .empty_pb2
8
10
import google .protobuf .message
11
+ import google .protobuf .timestamp_pb2
9
12
import google .protobuf .wrappers_pb2
10
13
from google .protobuf import descriptor_pool , message_factory
11
14
@@ -30,6 +33,16 @@ def marshal_any(value: Any) -> google.protobuf.any_pb2.Any:
30
33
value = google .protobuf .wrappers_pb2 .StringValue (value = value )
31
34
elif isinstance (value , bytes ):
32
35
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 )
33
46
34
47
if not isinstance (value , google .protobuf .message .Message ):
35
48
value = pickled_pb .Pickled (pickled_value = pickle .dumps (value ))
@@ -76,5 +89,9 @@ def unmarshal_any(any: google.protobuf.any_pb2.Any) -> Any:
76
89
except Exception as e :
77
90
# Otherwise, return the literal bytes.
78
91
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 ()
79
96
80
97
return proto
0 commit comments