Skip to content

Commit c2e4782

Browse files
author
marat
committed
gh-137165: Add non-zero-padded Windows support for datetime.strftime
1 parent 01cc532 commit c2e4782

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

Lib/test/datetimetester.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import textwrap
1515
import unittest
1616
import warnings
17+
import platform
1718

1819
from array import array
1920

@@ -1587,6 +1588,17 @@ def test_strftime(self):
15871588
self.assertEqual(t.strftime("m:%m d:%d y:%y"), "m:03 d:02 y:05")
15881589
self.assertEqual(t.strftime(""), "") # SF bug #761337
15891590
self.assertEqual(t.strftime('x'*1000), 'x'*1000) # SF bug #1556784
1591+
self.assertEqual(t.strftime("m:%-m d:%-d"), "m:3 d:2") # SF bug #137165
1592+
if platform.system() == 'Darwin': # SF bug #137165
1593+
self.assertEqual(t.strftime("m:%-m d:%-d y:%-y"), "m:3 d:2 y:05")
1594+
elif (
1595+
platform.system() == 'Linux'
1596+
and platform.machine() == 'x86_64'
1597+
and 'android' in platform.platform()
1598+
):
1599+
raise self.skipTest('Android x86_64 is not support non-zero-padded strftime')
1600+
else:
1601+
self.assertEqual(t.strftime("m:%-m d:%-d y:%-y"), "m:3 d:2 y:5")
15901602

15911603
self.assertRaises(TypeError, t.strftime) # needs an arg
15921604
self.assertRaises(TypeError, t.strftime, "one", "two") # too many args
@@ -3889,6 +3901,14 @@ def test_strftime(self):
38893901
self.assertEqual(t.strftime('%H %M %S %f'), "01 02 03 000004")
38903902
# A naive object replaces %z, %:z and %Z with empty strings.
38913903
self.assertEqual(t.strftime("'%z' '%:z' '%Z'"), "'' '' ''")
3904+
if (
3905+
platform.system() == 'Linux'
3906+
and platform.machine() == 'x86_64'
3907+
and 'android' in platform.platform()
3908+
):
3909+
raise self.skipTest('Android x86_64 is not support non-zero-padded strftime')
3910+
else:
3911+
self.assertEqual(t.strftime('%-H %-M %-S %f'), "1 2 3 000004") # SF bug #137165
38923912

38933913
# bpo-34482: Check that surrogates don't cause a crash.
38943914
try:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add support for Windows non-zero-padded formatting directives in
2+
:func:`datetime.datetime.strftime` (e.g., ``"m:%-m d:%-d y:%-y"``).

Modules/_datetimemodule.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,6 +2002,21 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
20022002
}
20032003
continue;
20042004
}
2005+
#ifdef MS_WINDOWS
2006+
/* non-0-pad Windows support */
2007+
else if (ch == '-' && i < flen) {
2008+
Py_UCS4 next_ch = PyUnicode_READ_CHAR(format, i);
2009+
if (strchr("dHImMSUwWyY", next_ch) != NULL) {
2010+
i++;
2011+
replacement = PyUnicode_FromFormat("%s%c", "%#", next_ch);
2012+
if (replacement == NULL) {
2013+
goto Error;
2014+
}
2015+
} else {
2016+
continue;
2017+
}
2018+
}
2019+
#endif
20052020
else {
20062021
/* percent followed by something else */
20072022
continue;
@@ -2034,6 +2049,28 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
20342049
result = PyObject_CallFunctionObjArgs(strftime,
20352050
newformat, timetuple, NULL);
20362051
Py_DECREF(newformat);
2052+
if (result == NULL && PyErr_ExceptionMatches(PyExc_ValueError)) {
2053+
PyObject *err_type, *err_value, *err_tb;
2054+
PyErr_Fetch(&err_type, &err_value, &err_tb);
2055+
2056+
Py_UCS4 bad_char = 0;
2057+
if (i > 0 && i <= PyUnicode_GET_LENGTH(format)) {
2058+
bad_char = PyUnicode_READ_CHAR(format, i-1);
2059+
}
2060+
2061+
PyObject *new_msg = PyUnicode_FromFormat(
2062+
"%U (invalid at position %zd, char '%C')",
2063+
err_value ? err_value : PyUnicode_FromString("ValueError"),
2064+
i > 0 ? i-1 : 0,
2065+
bad_char
2066+
);
2067+
2068+
Py_XDECREF(err_value);
2069+
Py_XDECREF(err_tb);
2070+
PyErr_Restore(err_type, new_msg, NULL);
2071+
2072+
goto Done;
2073+
}
20372074

20382075
Done:
20392076
Py_XDECREF(freplacement);

0 commit comments

Comments
 (0)