From eb651c29ff8f293a4a4af5271486585dd12c1864 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Fri, 24 Mar 2023 11:26:25 +0100 Subject: [PATCH 1/4] add tests checking that non-4 digit years isoformat properly --- pandas/tests/scalar/timestamp/test_formats.py | 11 +++++++++++ 1 file changed, 11 insertions(+) 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"), From 1ccf53033876a01aea19b7f3c7a0b902ddb1d610 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Fri, 24 Mar 2023 14:56:36 +0100 Subject: [PATCH 2/4] zero-pad the year to 4 digits --- pandas/_libs/tslibs/timestamps.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 10a331f302cc4..02f1e43eda62d 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -1015,7 +1015,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 From 7450c13394d33c90d708f15f03966f6db1deee1d Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Sun, 26 Mar 2023 12:24:03 +0200 Subject: [PATCH 3/4] adapt the constructor consistency tests --- pandas/tests/scalar/timestamp/test_constructors.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pandas/tests/scalar/timestamp/test_constructors.py b/pandas/tests/scalar/timestamp/test_constructors.py index ca0796e55f28d..00a6bc991cfc1 100644 --- a/pandas/tests/scalar/timestamp/test_constructors.py +++ b/pandas/tests/scalar/timestamp/test_constructors.py @@ -595,19 +595,16 @@ 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", + "Cannot cast 0001-01-01 00:00:00 to unit='ns' without overflow", + "Out of bounds nanosecond timestamp: 0001-01-01 00:00:00", ] ) 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 From e5f7b48b7e37784058e351ac69e50af74dc6b3b1 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Sun, 26 Mar 2023 13:51:36 +0200 Subject: [PATCH 4/4] remove the constructor error message since that should not be raised anymore --- pandas/tests/scalar/timestamp/test_constructors.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pandas/tests/scalar/timestamp/test_constructors.py b/pandas/tests/scalar/timestamp/test_constructors.py index 00a6bc991cfc1..b72f879e28b14 100644 --- a/pandas/tests/scalar/timestamp/test_constructors.py +++ b/pandas/tests/scalar/timestamp/test_constructors.py @@ -593,12 +593,7 @@ 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 0001-01-01 00:00:00 to unit='ns' without overflow", - "Out of bounds nanosecond timestamp: 0001-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")