From 339ba74a490a7be1df1e7d397d0788d7382eae1a Mon Sep 17 00:00:00 2001 From: fan wu <336798967+FanWu-ai@users.noreply.github.com> Date: Wed, 21 Oct 2026 06:33:57 +0900 Subject: [PATCH] Preserve fixed-width year formatting tokens --- docs/docs/string_formatting.md | 4 +-- src/pendulum/formatting/formatter.py | 4 +-- .../test_year_padding_regression.py | 36 +++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 tests/formatting/test_year_padding_regression.py diff --git a/docs/docs/string_formatting.md b/docs/docs/string_formatting.md index 91b95fc40..595faca4f 100644 --- a/docs/docs/string_formatting.md +++ b/docs/docs/string_formatting.md @@ -106,9 +106,9 @@ The following tokens are currently supported: | | Token | Output | | ------------------------------ | ------------- | ------------------------------------------ | -| **Year** | YYYY | 2000, 2001, 2002 ... 2012, 2013 | +| **Year** | YYYY | 0001, 0002 ... 2000, 2001 ... 9999 | | | YY | 00, 01, 02 ... 12, 13 | -| | Y | 2000, 2001, 2002 ... 2012, 2013 | +| | Y | 1, 2 ... 2000, 2001 ... 9999 | | **Quarter** | Q | 1 2 3 4 | | | Qo | 1st 2nd 3rd 4th | | **Month** | MMMM | January, February, March ... | diff --git a/src/pendulum/formatting/formatter.py b/src/pendulum/formatting/formatter.py index b09977d0d..c2667fec9 100644 --- a/src/pendulum/formatting/formatter.py +++ b/src/pendulum/formatting/formatter.py @@ -99,8 +99,8 @@ class Formatter: _TOKENS_RULES: ClassVar[dict[str, Callable[[pendulum.DateTime], str]]] = { # Year - "YYYY": lambda dt: f"{dt.year:d}", - "YY": lambda dt: f"{dt.year:d}"[2:], + "YYYY": lambda dt: f"{dt.year:04d}", + "YY": lambda dt: f"{dt.year % 100:02d}", "Y": lambda dt: f"{dt.year:d}", # Quarter "Q": lambda dt: f"{dt.quarter:d}", diff --git a/tests/formatting/test_year_padding_regression.py b/tests/formatting/test_year_padding_regression.py new file mode 100644 index 000000000..68c3a2ccd --- /dev/null +++ b/tests/formatting/test_year_padding_regression.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +import pytest + +import pendulum + +from pendulum.formatting import Formatter + + +@pytest.mark.parametrize( + "year, full, short", + [ + (1, "0001", "01"), + (9, "0009", "09"), + (10, "0010", "10"), + (99, "0099", "99"), + (100, "0100", "00"), + (101, "0101", "01"), + (999, "0999", "99"), + (1000, "1000", "00"), + (2009, "2009", "09"), + (9999, "9999", "99"), + ], +) +def test_year_tokens_have_fixed_width(year: int, full: str, short: str) -> None: + value = pendulum.datetime(year, 3, 14) + assert Formatter().format(value, "YYYY YY Y") == f"{full} {short} {year}" + assert value.format("YYYY-MM-DD") == f"{full}-03-14" + assert value.format("YY-MM-DD") == f"{short}-03-14" + assert pendulum.from_format(value.format("YYYY-MM-DD"), "YYYY-MM-DD") == value + + +def test_year_padding_applies_to_localized_long_formats() -> None: + value = pendulum.datetime(42, 3, 14) + assert value.format("L", locale="en") == "03/14/0042" + assert value.format("[YYYY] YYYY [YY] YY [Y] Y") == "YYYY 0042 YY 42 Y 42"