You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PolarsCursor truncates timestamp fractions wrongly for years outside 0000-9999 #1201
PolarsCursor truncates the fraction of a timestamp to the wrong digits when its year is not written with four digits.
_to_datetimes() (pyathena/polars/converter.py) cuts the timestamp text at a fixed length from _TIMESTAMP_TEXT_LENGTHS (pyathena/converter.py), such as 23 characters for ms and 26 for us, which assumes a four-digit year. Athena writes a year after 9999 with a + sign and five or more digits, and a year before 0001 with a - sign, so the cut drops fractional digits that the time unit holds. The values are returned without an error.
_to_datetimes() converts the timestamp columns of a CSV result read in chunks, and of a whole read whose native parse fails.
Reproduction
Athena writes these values in the CSV result file and the GetQueryResults rows (checked with a live query):
_to_datetimes() returns, with Polars 1.39.0 to 2.0.0:
text
Datetime("ms")
Datetime("us")
+11020-01-02 03:04:05.123
+11020-01-02 03:04:05.100
+11020-01-02 03:04:05.123000
+11020-01-02 03:04:05.123456789012
+11020-01-02 03:04:05.100
+11020-01-02 03:04:05.123400
-0001-01-02 03:04:05.123456789012
-0001-01-02 03:04:05.120
-0001-01-02 03:04:05.123450
Expected behavior
The fraction is truncated to the time unit regardless of the width of the year: .123 for ms and .123456 for us.
polars.Expr.str.to_datetime() with the format "%Y-%m-%d %H:%M:%S%.f" already parses these years and truncates fractional digits beyond the time unit, on Polars 1.39.0, 1.44.2, and 2.0.0, so the text does not need to be cut.
ArrowCursor shares _TIMESTAMP_TEXT_LENGTHS, but pyarrow does not parse a signed or five-digit year at all, so its read fails with ArrowInvalid before the cut matters.
Closing in favor of #1216 under the temporal contract in #1212.
The contract limits typed values to years 1 to 9999 in every cursor; a year written with a sign or five or more digits raises DataError instead of being parsed. This issue's expected behavior, truncating the fraction correctly whatever the width of the year, no longer applies. The fixed-length cut that caused it is handled in #1216, together with the year range.
Activity
laughingman7743 commentedon Oct 16, 2026
Closing in favor of #1216 under the temporal contract in #1212.
The contract limits typed values to years 1 to 9999 in every cursor; a year written with a sign or five or more digits raises
DataErrorinstead of being parsed. This issue's expected behavior, truncating the fraction correctly whatever the width of the year, no longer applies. The fixed-length cut that caused it is handled in #1216, together with the year range.