encode whole-second datetime timestamps as integers across full range#317
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
Under
datetime_as_timestamp,encode_datetimedecides whether a value can be written as an integer by narrowing the POSIX timestamp through au32and comparing it back against the float. That cast saturates: anything negative collapses to 0 and anything past 2106-02-07 collapses tou32::MAX, so the equality check never holds for a whole-second datetime before 1970 or after 2106. Those values still round-trip, but they go out as a tag 1 float64 rather than the compact integer the original pure-Python encoder always produced for whole-second timestamps. I spotted it while diffing the Rust output against the historical implementation, wheredatetime(1969, 12, 31, tzinfo=utc)came back asc1fb...instead of a negint.Widening the cast to
i64restores the integer path across the whole representable datetime range, negative timestamps included, while the existingtimestamp_int as f64 == timestamp_floatguard still falls back to a float when there are sub-second microseconds. The decision belongs here in the encoder because it is what shapes the wire form. Left as is it emits non-canonical, larger output and silently disagrees with every other cbor2 release for any timestamp outside a 136-year window.Checklist
tests/) which would fail without your patchdocs/), in case of behavior changes or new featuresdocs/versionhistory.rst).