Skip to content

datetime.strftime("%Y") not consistent for years < 1000 #57514

Closed as not planned

Description

@florentx
mannequin
BPO 13305
Nosy @jaraco, @abalkin, @vstinner, @ned-deily, @ezio-melotti, @florentx, @vadmium, @elenaoat, @pganssle, @Fronkan
Superseder
  • bpo-3173: external strftime for Python?
  • Files
  • issue13305_xmlrpc_patch.diff
  • doc.patch
  • issue13305.diff
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2011-10-31.20:12:37.023>
    labels = ['easy', 'type-bug', '3.8', '3.9', '3.7', 'library', 'docs']
    title = 'datetime.strftime("%Y") not consistent for years < 1000'
    updated_at = <Date 2022-02-10.19:47:24.483>
    user = 'https://github.com/florentx'

    bugs.python.org fields:

    activity = <Date 2022-02-10.19:47:24.483>
    actor = 'jaraco'
    assignee = 'docs@python'
    closed = False
    closed_date = None
    closer = None
    components = ['Documentation', 'Library (Lib)']
    creation = <Date 2011-10-31.20:12:37.023>
    creator = 'flox'
    dependencies = []
    files = ['23577', '41476', '42136']
    hgrepos = []
    issue_num = 13305
    keywords = ['patch', 'easy']
    message_count = 30.0
    messages = ['146740', '146743', '146745', '146750', '146751', '146752', '146765', '146767', '146967', '146972', '146976', '146978', '252165', '257271', '257383', '257397', '261577', '261607', '261608', '261609', '261637', '261638', '261639', '261640', '307417', '359735', '359740', '394251', '413015', '413021']
    nosy_count = 13.0
    nosy_names = ['jaraco', 'belopolsky', 'vstinner', 'ned.deily', 'ezio.melotti', 'flox', 'docs@python', 'python-dev', 'martin.panter', 'Elena.Oat', 'p-ganssle', 'Fronkan', 'cklarson']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = 'needs patch'
    status = 'open'
    superseder = '3173'
    type = 'behavior'
    url = 'https://bugs.python.org/issue13305'
    versions = ['Python 3.7', 'Python 3.8', 'Python 3.9']

    Activity

    1. florentx commented on Oct 31, 2011

      florentxmannequin
      MannequinAuthor

      See msg146725 on bpo-13291.

      on linux
      >>> datetime(1,  2, 10, 11, 41, 23).strftime("%Y")
      '1'
      
      on osx
      >>> datetime(1,  2, 10, 11, 41, 23).strftime("%Y")
      '0001'
      
      
      >>> datetime.strptime('0001', '%Y')
      datetime.datetime(1, 1, 1, 0, 0)
      
      >>> datetime.strptime('1', '%Y')
      ValueError: time data '1' does not match format '%Y'
    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-bugAn unexpected behavior, bug, or error
      on Oct 31, 2011
    3. florentx commented on Oct 31, 2011

      florentxmannequin
      MannequinAuthor

      FWIW, issue bpo-1777412 added support for years < 1000 to Python 3.3 strftime.

    4. abalkin commented on Oct 31, 2011

      @abalkin
      Member

      I am not sure this can be fixed without distributing our own implementation of strftime. See bpo-3173.

    5. florentx commented on Oct 31, 2011

      florentxmannequin
      MannequinAuthor

      There's many discrepancies between OS X and Linux about time formatting...

      OS X
      >>> from datetime import datetime
      >>> datetime(1900, 1, 1).strftime("%6Y")
      '6Y'
      
      Linux
      >>> from datetime import datetime
      >>> datetime(1900, 1, 1).strftime("%6Y")
      '001900'

      BTW, these discrepancies are already mentioned:
      http://docs.python.org/dev/library/datetime.html#strftime-strptime-behavior

      “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.”

      We should had an asterisk to the "%Y" saying that the padding is not consistent across platforms.

    6. florentx commented on Oct 31, 2011

      florentxmannequin
      MannequinAuthor

      Proposed patch to fix the issue in xmlrpc.client

    7. python-dev commented on Oct 31, 2011

      python-devmannequin
      Mannequin

      New changeset 3f025427f02b by Florent Xicluna in branch 'default':
      Fix regression due to changeset 2096158376e5 (issue bpo-13305).
      http://hg.python.org/cpython/rev/3f025427f02b

    8. vstinner commented on Nov 1, 2011

      @vstinner
      Member

      Le 01/11/2011 00:07, Roundup Robot a écrit :

      Roundup Robot<devnull@psf.upfronthosting.co.za> added the comment:

      New changeset 3f025427f02b by Florent Xicluna in branch 'default':
      Fix regression due to changeset 2096158376e5 (issue bpo-13305).
      http://hg.python.org/cpython/rev/3f025427f02b

      I don't like this hack. If there is a bug in time.strftime(), we need to
      fix time.strftime(), not xmlrpclib.

      Is there a test for the hack?

    9. python-dev commented on Nov 1, 2011

      python-devmannequin
      Mannequin

      New changeset 230f0956aaa3 by Florent Xicluna in branch 'default':
      Strengthen the tests for format '%Y', in relation with issue bpo-13305.
      http://hg.python.org/cpython/rev/230f0956aaa3

    10. vstinner commented on Nov 3, 2011

      @vstinner
      Member

      Did your commit fix the issue or not?

    11. florentx commented on Nov 3, 2011

      florentxmannequin
      MannequinAuthor

      I understand that the issue is because the C standard does not specify the length of the string returned by '%Y'.

      The changeset 230f0956aaa3 adds a test to verify that either '%Y' or '%4Y' returns a 4-digits value usable to produce ISO-8601 representations.

      Now it is a documentation issue: add a comment to the "%Y" specifier saying that the padding is not applicable to all platforms and in such case the "%4Y" specifier should return the 4-digit value.

    12. vstinner commented on Nov 3, 2011

      @vstinner
      Member

      Since the changeset 55a3b563f0dbed04af317f632f7f3c0f6abe175b, test_strptime is failing on "AMD64 Gentoo Wide 3.x" buildbot:

      ======================================================================
      FAIL: test_strptime (test.test_time.TimeTestCase)
      ----------------------------------------------------------------------

      Traceback (most recent call last):
        File "/home/buildbot/buildarea/3.x.ochtman-gentoo-amd64/build/Lib/test/test_time.py", line 159, in test_strptime
          time.strptime(strf_output, format)
      ValueError: time data 'LMT' does not match format '%Z'
      
      During handling of the above exception, another exception occurred:
      
      Traceback (most recent call last):
        File "/home/buildbot/buildarea/3.x.ochtman-gentoo-amd64/build/Lib/test/test_time.py", line 162, in test_strptime
          (format, strf_output))
      AssertionError: conversion specifier '%Z' failed with 'LMT' input.

      http://www.python.org/dev/buildbot/all/builders/AMD64%20Gentoo%20Wide%203.x/builds/2661

    13. 17 remaining items

    14. jaraco commented on Jan 10, 2020

      @jaraco
      Member

      In bpo-39103, I filed a bug relating to this issue.

      I'd like for Python to provide a portable implementation of strftime instead of just documenting that the version isn't portable.

      Given that this ticket assigned to 'docs' suggests that a portable version is out of the question. Can we expand the scope of this issue to actually providing a portable version?

    15. vstinner commented on Jan 10, 2020

      @vstinner
      Member

      I'd like for Python to provide a portable implementation of strftime instead of just documenting that the version isn't portable.

      If someone wants to do that, I suggest to first start with a project on PyPI. It sounds like a tricky project. Date, time, locales and localization are hard problems!

    16. Fronkan commented on May 24, 2021

      Fronkanmannequin
      Mannequin

      This also causes an issue when using stftime and strptime together on Linux (Ubuntu 20.04.1 LTS).
      When encoding a datetime using strftime and decoding with strptime using the same pattern an error is raised if year < 1000.

      Example:
      >>> pattern = "%Y-%m-%d"
      >>> datetime.strptime(
      ...     datetime(1, 1, 1).strftime(pattern),
      ...     pattern
      ... )
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/usr/lib/python3.8/_strptime.py", line 568, in _strptime_datetime
          tt, fraction, gmtoff_fraction = _strptime(data_string, format)
        File "/usr/lib/python3.8/_strptime.py", line 349, in _strptime
          raise ValueError("time data %r does not match format %r" %
      ValueError: time data '1-01-01' does not match format '%Y-%m-%d'
    17. cklarson commented on Feb 10, 2022

      cklarsonmannequin
      Mannequin

      Has there been any work/progress on this? Alternatively, what suggested work around/mitigations are suggested?

    18. jaraco commented on Feb 10, 2022

      @jaraco
      Member

      The tempora library implements a portable strftime.

    19. transferred this issue fromon Apr 10, 2022
    20. codethief commented on Jul 13, 2024

      @codethief

      Given the age of the ticket and the lack of clarity on what to do, I don't think the "easy" label still applies here, does it? :-)

    21. jaraco commented on Jul 14, 2024

      @jaraco
      Member

      I'd like for Python to provide a portable implementation of strftime instead of just documenting that the version isn't portable.

      If someone wants to do that, I suggest to first start with a project on PyPI. It sounds like a tricky project. Date, time, locales and localization are hard problems!

      The wrapper in tempora has worked well for me for a couple of years. It defers most of the processing to the existing C implementation and merely performs the substitution early, allowing the C implementation to handle the rest.

      Would it make sense for CPython to adopt a similar technique to address the concern at hand and avoid doing a full re-implementation (with all of the bugs and performance regressions that would likely entail)?

    22. blhsing commented on Jul 15, 2024

      @blhsing
      Contributor

      Given the age of the ticket and the lack of clarity on what to do, I don't think the "easy" label still applies here, does it? :-)

      A fix for %Y alone would've been "easy" by PyOS_snprintf-formatting the year with "%04ld", but the issue is made more complex when taking into account the need to support %G (credit to @serhiy-storchaka for pointing this out).

      The issue is now resolved with PR #120820 by conditionally delegating the said format specifiers to time.strftime and wrapping the value with PyOS_snprintf.

    23. serhiy-storchaka commented on Jul 15, 2024

      @serhiy-storchaka
      Member

      Closing as a duplicate of #120713.

    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

      3.7 (EOL)end of life3.8 (EOL)end of life3.9 (EOL)end of lifedocsDocumentation in the Doc dirstdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

      Projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions