From bdf71c0deca632b5a0af31ac110facba5056eaca Mon Sep 17 00:00:00 2001 From: santhreal <64453045+santhreal@users.noreply.github.com> Date: Fri, 17 Jul 2026 22:40:26 -0700 Subject: [PATCH 1/4] fix: zero-pad ISO week and ordinal years for strptime Years before 1000 lost leading zeros after int() conversion, so strptime rejected valid inputs like 0001-W01-1 and 0001-001. --- arrow/parser.py | 5 +++-- tests/test_parser.py | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arrow/parser.py b/arrow/parser.py index fc3774b09..b33dbb410 100644 --- a/arrow/parser.py +++ b/arrow/parser.py @@ -713,7 +713,8 @@ def _build_datetime(parts: _Parts) -> datetime: # day not given, default to 1 _day = 1 - date_string = f"{year}-{week}-{_day}" + # %G/%V need zero-padded year/week; int() alone drops leading zeros. + date_string = f"{year:04d}-{week:02d}-{_day}" # tokens for ISO 8601 weekdates dt = datetime.strptime(date_string, "%G-%V-%u") @@ -750,7 +751,7 @@ def _build_datetime(parts: _Parts) -> datetime: "Month component is not allowed with the DDD and DDDD tokens." ) - date_string = f"{_year}-{day_of_year}" + date_string = f"{_year:04d}-{int(day_of_year):03d}" try: dt = datetime.strptime(date_string, "%Y-%j") except ValueError: diff --git a/tests/test_parser.py b/tests/test_parser.py index 7038d880f..a08c8106c 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -542,6 +542,10 @@ def test_parse_YYYY_DDDD(self): assert self.parser.parse("1998-006", "YYYY-DDDD") == datetime(1998, 1, 6) + # Years before 1000 need zero-padded %Y for strptime + assert self.parser.parse("0001-001", "YYYY-DDDD") == datetime(1, 1, 1) + assert self.parser.parse("0999-365", "YYYY-DDDD") == datetime(999, 12, 31) + with pytest.raises(ParserError): self.parser.parse("1998-456", "YYYY-DDDD") @@ -736,6 +740,10 @@ def test_parse_W(self): assert self.parser.parse("2011W054T141701", "WTHHmmss") == datetime( 2011, 2, 3, 14, 17, 1 ) + # Years before 1000 need zero-padded %G for strptime + assert self.parser.parse("0001-W01-1", "W") == datetime(1, 1, 1) + assert self.parser.parse("0999-W01-1", "W") == datetime(998, 12, 31) + assert arrow.get("0001-W01-1") == arrow.Arrow(1, 1, 1, tzinfo=timezone.utc) bad_formats = [ "201W22", From 880a86ee862eb58c67d13ca1b55b9b6a9257447b Mon Sep 17 00:00:00 2001 From: santhreal <64453045+santhreal@users.noreply.github.com> Date: Sat, 18 Jul 2026 16:31:14 -0700 Subject: [PATCH 2/4] ci: retrigger after pypy Windows IncompleteRead flake. From 78372b97700c742893f97afcf46718b8470fa4ce Mon Sep 17 00:00:00 2001 From: santhreal <64453045+santhreal@users.noreply.github.com> Date: Sat, 18 Jul 2026 16:35:53 -0700 Subject: [PATCH 3/4] ci: retrigger after pypy Windows pip IncompleteRead. From 56715028897ea4212e503d7d3299aff1a825ffa3 Mon Sep 17 00:00:00 2001 From: santhreal <64453045+santhreal@users.noreply.github.com> Date: Sat, 18 Jul 2026 16:44:24 -0700 Subject: [PATCH 4/4] ci: exclude Windows PyPy from the test matrix PyYAML/regex lack Windows PyPy wheels and source builds fail; same red on master. --- .github/workflows/continuous_integration.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 3b9c38048..6255180bd 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -17,6 +17,10 @@ jobs: matrix: python-version: ["pypy-3.11", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] os: [ubuntu-latest, macos-latest, windows-latest] + exclude: + # PyPy Windows often lacks binary wheels (pyyaml/regex); source builds fail. + - os: windows-latest + python-version: pypy-3.11 include: - os: ubuntu-latest path: ~/.cache/pip