From 367a5a2c99da461f89efc1254b32eefe2b50fc0b Mon Sep 17 00:00:00 2001 From: MeeseeksMachine <39504233+meeseeksmachine@users.noreply.github.com> Date: Fri, 31 Mar 2023 21:22:00 +0200 Subject: [PATCH] Backport PR #52220 on branch 2.0.x (BUG: zero-pad shorter years in `Timestamp.isoformat`) (#52327) Backport PR #52220: BUG: zero-pad shorter years in `Timestamp.isoformat` Co-authored-by: Justus Magin --- pandas/_libs/tslibs/timestamps.pyx | 2 +- .../tests/scalar/timestamp/test_constructors.py | 16 ++++------------ pandas/tests/scalar/timestamp/test_formats.py | 11 +++++++++++ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 33e8344c79d6c..2134da209246e 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -1012,7 +1012,7 @@ cdef class _Timestamp(ABCTimestamp): base_ts = "microseconds" if timespec == "nanoseconds" else timespec base = super(_Timestamp, self).isoformat(sep=sep, timespec=base_ts) # We need to replace the fake year 1970 with our real year - base = f"{self.year}-" + base.split("-", 1)[1] + base = f"{self.year:04d}-" + base.split("-", 1)[1] if self.nanosecond == 0 and timespec != "nanoseconds": return base diff --git a/pandas/tests/scalar/timestamp/test_constructors.py b/pandas/tests/scalar/timestamp/test_constructors.py index ca0796e55f28d..b72f879e28b14 100644 --- a/pandas/tests/scalar/timestamp/test_constructors.py +++ b/pandas/tests/scalar/timestamp/test_constructors.py @@ -593,21 +593,13 @@ def test_bounds_with_different_units(self): @pytest.mark.parametrize("arg", ["001-01-01", "0001-01-01"]) def test_out_of_bounds_string_consistency(self, arg): # GH 15829 - msg = "|".join( - [ - "Cannot cast 1-01-01 00:00:00 to unit='ns' without overflow", - "Out of bounds nanosecond timestamp: 1-01-01 00:00:00", - ] - ) + msg = "Cannot cast 0001-01-01 00:00:00 to unit='ns' without overflow" with pytest.raises(OutOfBoundsDatetime, match=msg): Timestamp(arg).as_unit("ns") - if arg == "0001-01-01": - # only the 4-digit year goes through ISO path which gets second reso - # instead of ns reso - ts = Timestamp(arg) - assert ts.unit == "s" - assert ts.year == ts.month == ts.day == 1 + ts = Timestamp(arg) + assert ts.unit == "s" + assert ts.year == ts.month == ts.day == 1 def test_min_valid(self): # Ensure that Timestamp.min is a valid Timestamp diff --git a/pandas/tests/scalar/timestamp/test_formats.py b/pandas/tests/scalar/timestamp/test_formats.py index 71dbf3539bdb2..0c154963d3726 100644 --- a/pandas/tests/scalar/timestamp/test_formats.py +++ b/pandas/tests/scalar/timestamp/test_formats.py @@ -11,6 +11,15 @@ second=8, microsecond=132263, ) +ts_no_ns_year1 = Timestamp( + year=1, + month=5, + day=18, + hour=15, + minute=17, + second=8, + microsecond=132263, +) ts_ns = Timestamp( year=2019, month=5, @@ -50,6 +59,8 @@ (ts_no_ns, "auto", "2019-05-18T15:17:08.132263"), (ts_no_ns, "seconds", "2019-05-18T15:17:08"), (ts_no_ns, "nanoseconds", "2019-05-18T15:17:08.132263000"), + (ts_no_ns_year1, "seconds", "0001-05-18T15:17:08"), + (ts_no_ns_year1, "nanoseconds", "0001-05-18T15:17:08.132263000"), (ts_ns, "auto", "2019-05-18T15:17:08.132263123"), (ts_ns, "hours", "2019-05-18T15"), (ts_ns, "minutes", "2019-05-18T15:17"),