Skip to content

datetime.strftime("%Y") is not padding correctly #120713

Description

@martinvuyk

Bug report

Bug description:

docs say:

%Y

Year with century as a decimal number.

0001, 0002, …, 2013, 2014, …, 9998, 9999

but this is what is happening

from datetime import datetime

print(datetime(9, 6, 7).strftime("%Y-%m-%d")) # 9-06-07
print(datetime(99, 6, 7).strftime("%Y-%m-%d")) # 99-06-07
print(datetime(999, 6, 7).strftime("%Y-%m-%d")) # 999-06-07

CPython versions tested on:

3.10

Operating systems tested on:

No response

Linked PRs

Activity

  1. blhsing commented on Jun 19, 2024

    @blhsing
    Contributor

    Reproducible on 3.10 but not on 3.11+.

  2. serhiy-storchaka commented on Jun 19, 2024

    @serhiy-storchaka
    Member

    cc @pganssle

    I suppose that it works in such way since Python 3.0 (I tested in 3.3). 2.7 does not support years before 1900.

    You can use %4Y to always get 4-digit year. I wonder whether this is a documentation issue or the output is platform depending.

  3. blhsing commented on Jun 19, 2024

    @blhsing
    Contributor

    I wonder whether this is a documentation issue or the output is platform depending.

    Ah, so the issue is platform-dependent. When I reproduced the OP's issue in 3.10 I was doing it in Linux, while in Windows I tested the code in 3.11 and 3.13 and the issue was not reproduced. Now I realized that this is just a result of datetime.strftime being a thin wrapper over the platform's strftime in the C library:

    According to the doc:

    The full set of format codes supported varies across platforms, because Python calls the platform C library’s strftime() function, and platform variations are common. To see the full set of format codes supported on your platform, consult the strftime(3) documentation.

  4. serhiy-storchaka commented on Jun 20, 2024

    @serhiy-storchaka
    Member

    The limitation for year >= 1000 was removed in bpo-11930 (gh-56139). But there were various problems with the newly added test test_strftime_y2k, it required several corrections.

    For now, we cannot guarantee the result for %Y (and %G) with year < 1000. It is especially bad since strptime() requires the year to be 4 digits.

  5. added 2 commits that reference this issue on Jun 21, 2024
  6. blhsing commented on Jun 21, 2024

    @blhsing
    Contributor

    Since datetime.strftime already uses a wrapper function to handle format specifiers not conforming to the C strftime, I think a reasonable fix would be to add the translation of %Y to %4Y there as needed by the platform to make the function portable.

  7. serhiy-storchaka commented on Jun 21, 2024

    @serhiy-storchaka
    Member

    Yes, but the problem is that %4Y is a glibc extension. There are platforms that return non-4-digit number and do not support %4Y. If we are going to guarantee 4 digits, the workaround may be much more complex.

  8. blhsing commented on Jun 21, 2024

    @blhsing
    Contributor

    Yes, but the problem is that %4Y is a glibc extension. There are platforms that return non-4-digit number and do not support %4Y. If we are going to guarantee 4 digits, the workaround may be much more complex.

    With PR #120820 I've made sure that the translation is only used when explicitly supported by the platform so that it is at least an improvement and not a regression in any case. I did just revert my changes to the unit test to allow an outlier platform to pass the test.

  9. added 2 commits that reference this issue on Jun 24, 2024
  10. blhsing commented on Jun 24, 2024

    @blhsing
    Contributor

    Yes, but the problem is that %4Y is a glibc extension. There are platforms that return non-4-digit number and do not support %4Y. If we are going to guarantee 4 digits, the workaround may be much more complex.

    On second thought, guaranteeing 4 digits is actually not complex since we can simply format the year with "%04ld" using sprintf, which works on all platforms.

    I've updated the PR accordingly so that a 4-digit year with century can now be guaranteed.

  11. added a commit that references this issue on Jun 24, 2024
  12. 51 remaining items

  13. blhsing commented on Sep 4, 2024

    @blhsing
    Contributor

    I'm not sure why but we are seeing failures on JIT for the test_strftime_y2k on emulated Linux. Is it because emulated Linux have (yet) another weird case of glibc?

    Thanks for the heads-up. It is weird indeed that this can happen since according to the build log the configure script did detect that the platform would not 0-pad a century so the handler for %Y would format the year itself with snprintf using the "%04ld" format string.

    Since this happens only on aarch64 perhaps there is indeed some peculiarity of snprintf in the glibc of that platform.

    Will try debugging this on a Mac later.

    Also, the reason we reverted the commits on 3.12 and 3.13 was because it was more of a feature than a bugfix?

    It's a bug fix but was found to be incomplete, due to issue #122272.

  14. serhiy-storchaka commented on Sep 4, 2024

    @serhiy-storchaka
    Member

    Please open a new issue and provide more details.

  15. picnixz commented on Sep 4, 2024

    @picnixz
    Member

    See #123681.

  16. added a commit that references this issue on Jun 25, 2025
  17. added a commit that references this issue on Jul 7, 2025
  18. added a commit that references this issue on Jul 7, 2025
  19. added a commit that references this issue on Jul 8, 2025
  20. added a commit that references this issue on Jul 11, 2025
  21. added a commit that references this issue on Jul 12, 2025
  22. added a commit that references this issue on Jul 13, 2025
  23. added a commit that references this issue on Aug 4, 2025
  24. added a commit that references this issue on Aug 19, 2025
  25. added a commit that references this issue on Oct 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions