Problem
frequenz.client.common.proto.datetime_from_proto() currently calls datetime.fromtimestamp(). A protobuf Timestamp can carry a value that Python cannot represent, causing conversion to raise instead of preserving the received data in the return type.
For example:
from google.protobuf.timestamp_pb2 import Timestamp
from frequenz.client.common.proto import datetime_from_proto
datetime_from_proto(Timestamp(seconds=253402300800))
# ValueError: year 10000 is out of range
This exception also escapes higher-level converters such as metric_sample_from_proto(), contrary to the goal of representing malformed wire data explicitly.
Proposed change
- Add a protobuf-independent
InvalidDateTime wrapper that preserves the raw timestamp data needed for inspection.
- Add a
datetime_from_proto2() if datetime_from_proto() was already released that returns datetime | InvalidDateTime instead of raising for invalid or unrepresentable protobuf timestamps. Change the current function instead if it is unreleased.
- Propagate the union through all wrappers and converters that use
datetime_from_proto/2(), including metric samples, microgrids, and lifetimes.
- Add semantic accessors and a package-specific error where callers commonly require a valid
datetime, following the existing invalid-field pattern.
- Handle the public API change according to the project's 0.x compatibility policy.
Tests
Cover at least:
- valid timestamps, including timezone behavior;
- the minimum and maximum values representable by both protobuf and Python;
- values outside Python's
datetime range;
- invalid seconds/nanoseconds combinations accepted from decoded wire data;
- higher-level converters preserving
InvalidDateTime instead of raising;
- safe accessors returning valid values and raising typed errors for invalid ones.
Downstream migration
Find downstream users of datetime_from_proto() and affected wrapper datetime fields, update their annotations and exhaustive handling, and document the migration in the release notes.
Problem
frequenz.client.common.proto.datetime_from_proto()currently callsdatetime.fromtimestamp(). A protobufTimestampcan carry a value that Python cannot represent, causing conversion to raise instead of preserving the received data in the return type.For example:
This exception also escapes higher-level converters such as
metric_sample_from_proto(), contrary to the goal of representing malformed wire data explicitly.Proposed change
InvalidDateTimewrapper that preserves the raw timestamp data needed for inspection.datetime_from_proto2()ifdatetime_from_proto()was already released that returnsdatetime | InvalidDateTimeinstead of raising for invalid or unrepresentable protobuf timestamps. Change the current function instead if it is unreleased.datetime_from_proto/2(), including metric samples, microgrids, and lifetimes.datetime, following the existing invalid-field pattern.Tests
Cover at least:
datetimerange;InvalidDateTimeinstead of raising;Downstream migration
Find downstream users of
datetime_from_proto()and affected wrapper datetime fields, update their annotations and exhaustive handling, and document the migration in the release notes.