Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
martinvuyk opened this issue Jun 18, 2024 · 14 comments
Closed

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

martinvuyk opened this issue Jun 18, 2024 · 14 comments
Labels
type-bug An unexpected behavior, bug, or error

Comments

@martinvuyk
Copy link

martinvuyk commented Jun 18, 2024

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

@martinvuyk martinvuyk added the type-bug An unexpected behavior, bug, or error label Jun 18, 2024
@blhsing
Copy link
Contributor

blhsing commented Jun 19, 2024

Reproducible on 3.10 but not on 3.11+.

@serhiy-storchaka
Copy link
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.

@blhsing
Copy link
Contributor

blhsing commented Jun 19, 2024

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.

@serhiy-storchaka
Copy link
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.

@blhsing
Copy link
Contributor

blhsing commented Jun 21, 2024

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.

@serhiy-storchaka
Copy link
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.

@blhsing
Copy link
Contributor

blhsing commented Jun 21, 2024

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.

blhsing added a commit to blhsing/cpython that referenced this issue Jun 24, 2024
@blhsing
Copy link
Contributor

blhsing commented Jun 24, 2024

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.

blhsing added a commit to blhsing/cpython that referenced this issue Jun 24, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 24, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 24, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 24, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 24, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 24, 2024
@serhiy-storchaka
Copy link
Member

PR #120820 looks good if this is what we want to get. @pganssle, what are your thoughts?

Note that %G also needs a fix.

blhsing added a commit to blhsing/cpython that referenced this issue Jun 25, 2024
@blhsing
Copy link
Contributor

blhsing commented Jun 25, 2024

Note that %G also needs a fix.

Good point. I've updated the PR to account for '%G' then. Thanks.

blhsing added a commit to blhsing/cpython that referenced this issue Jun 25, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 25, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 25, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 25, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 25, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 26, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 26, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 29, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 29, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 29, 2024
blhsing added a commit to blhsing/cpython that referenced this issue Jun 29, 2024
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Jun 29, 2024
…ythonGH-120820)

(cherry picked from commit 6d34938)

Co-authored-by: blhsing <blhsing@gmail.com>
serhiy-storchaka pushed a commit to serhiy-storchaka/cpython that referenced this issue Jun 29, 2024
…time (pythonGH-120820)

(cherry picked from commit 6d34938)

Co-authored-by: blhsing <blhsing@gmail.com>
serhiy-storchaka added a commit that referenced this issue Jun 29, 2024
…H-120820) (GH-121145)

(cherry picked from commit 6d34938)

Co-authored-by: blhsing <blhsing@gmail.com>
serhiy-storchaka pushed a commit that referenced this issue Jun 29, 2024
…H-120820) (GH-121144)

(cherry picked from commit 6d34938)

Co-authored-by: blhsing <blhsing@gmail.com>
serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Jul 29, 2024
serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Jul 29, 2024
@picnixz
Copy link
Contributor

picnixz commented Sep 3, 2024

@serhiy-storchaka @blhsing 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? Also, the reason we reverted the commits on 3.12 and 3.13 was because it was more of a feature than a bugfix?

@blhsing
Copy link
Contributor

blhsing commented Sep 4, 2024

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.

@serhiy-storchaka
Copy link
Member

Please open a new issue and provide more details.

@picnixz
Copy link
Contributor

picnixz commented Sep 4, 2024

See #123681.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
Archived in project
Development

No branches or pull requests

4 participants