Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 454b3d4

Browse files
michaelsaahvstinner
authored andcommitted
bpo-35066: _dateime.datetime.strftime copies trailing '%' (pythonGH-10692)
Previously, calling the strftime() method on a datetime object with a trailing '%' in the format string would result in an exception. However, this only occured when the datetime C module was being used; the python implementation did not match this behavior. Datetime is now PEP-399 compliant, and will not throw an exception on a trailing '%'.
1 parent 5bb146a commit 454b3d4

File tree

3 files changed

+24
-5
lines changed

3 files changed

+24
-5
lines changed

Lib/test/datetimetester.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,17 @@ def test_strftime(self):
13511351
#check that this standard extension works
13521352
t.strftime("%f")
13531353

1354+
def test_strftime_trailing_percent(self):
1355+
# bpo-35066: make sure trailing '%' doesn't cause
1356+
# datetime's strftime to complain
1357+
t = self.theclass(2005, 3, 2)
1358+
try:
1359+
_time.strftime('%')
1360+
except ValueError:
1361+
self.skipTest('time module does not support trailing %')
1362+
self.assertEqual(t.strftime('%'), '%')
1363+
self.assertEqual(t.strftime("m:%m d:%d y:%y %"), "m:03 d:02 y:05 %")
1364+
13541365
def test_format(self):
13551366
dt = self.theclass(2007, 9, 10)
13561367
self.assertEqual(dt.__format__(''), str(dt))
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Previously, calling the strftime() method on a datetime object with a
2+
trailing '%' in the format string would result in an exception. However,
3+
this only occured when the datetime C module was being used; the python
4+
implementation did not match this behavior. Datetime is now PEP-399
5+
compliant, and will not throw an exception on a trailing '%'.

Modules/_datetimemodule.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,10 +1528,13 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
15281528
ntoappend = 1;
15291529
}
15301530
else if ((ch = *pin++) == '\0') {
1531-
/* There's a lone trailing %; doesn't make sense. */
1532-
PyErr_SetString(PyExc_ValueError, "strftime format "
1533-
"ends with raw %");
1534-
goto Done;
1531+
/* Null byte follows %, copy only '%'.
1532+
*
1533+
* Back the pin up one char so that we catch the null check
1534+
* the next time through the loop.*/
1535+
pin--;
1536+
ptoappend = pin - 1;
1537+
ntoappend = 1;
15351538
}
15361539
/* A % has been seen and ch is the character after it. */
15371540
else if (ch == 'z') {
@@ -1616,7 +1619,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
16161619
usednew += ntoappend;
16171620
assert(usednew <= totalnew);
16181621
} /* end while() */
1619-
1622+
16201623
if (_PyBytes_Resize(&newfmt, usednew) < 0)
16211624
goto Done;
16221625
{

0 commit comments

Comments
 (0)