Skip to content

Commit 2270997

Browse files
author
marat
committed
Unify behavior of unsupported %-format specifiers
1 parent f851d74 commit 2270997

File tree

3 files changed

+27
-30
lines changed

3 files changed

+27
-30
lines changed

Lib/_pydatetime.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,6 @@ def _need_normalize_century():
214214
return _normalize_century
215215

216216
def _make_dash_replacement(ch, timetuple):
217-
if ch not in 'dmHIMSjUWVy':
218-
raise ValueError('invalid format string')
219-
220217
fmt = '%' + ch
221218
val = _time.strftime(fmt, timetuple)
222219
return val.lstrip('0') or '0'
@@ -296,10 +293,13 @@ def _wrap_strftime(object, format, timetuple):
296293
if i < n:
297294
next_ch = format[i]
298295
i += 1
299-
if sys.platform in ['win32', 'android']:
300-
push(_make_dash_replacement(next_ch, timetuple))
296+
if next_ch not in 'dmHIMSjUWVy':
297+
push('%%-' + next_ch)
301298
else:
302-
push('%-' + next_ch)
299+
if sys.platform in ['win32', 'android']:
300+
push(_make_dash_replacement(next_ch, timetuple))
301+
else:
302+
push('%-' + next_ch)
303303
else:
304304
push('%-')
305305
else:

Lib/test/datetimetester.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,20 +1600,10 @@ def test_strftime(self):
16001600

16011601
self.assertEqual(t.strftime("%-j. %-U. %-W. %-V."), "61. 9. 9. 9.")
16021602

1603-
if platform.system() in ("Windows", "Android"):
1604-
# invalid %-format specifiers must raise ValueError
1605-
self.assertRaises(ValueError, t.strftime, "%-1")
1606-
self.assertRaises(ValueError, t.strftime, "%--")
1607-
self.assertRaises(ValueError, t.strftime, "%-p")
1608-
self.assertRaises(ValueError, t.strftime, "%-#")
1609-
elif platform.system() in ("Darwin", "iOS", "FreeBSD"):
1610-
self.assertEqual(t.strftime("%-1"), "1")
1611-
self.assertEqual(t.strftime("%--"), "-")
1612-
self.assertEqual(t.strftime("%-#"), "#")
1613-
else:
1614-
self.assertEqual(t.strftime("%-1"), "%-1")
1615-
self.assertEqual(t.strftime("%--"), "%--")
1616-
self.assertEqual(t.strftime("%-#"), "%-#")
1603+
# unsupported %-format specifiers are passed through unchanged.
1604+
self.assertEqual(t.strftime("%-1"), "%-1")
1605+
self.assertEqual(t.strftime("%--"), "%--")
1606+
self.assertEqual(t.strftime("%-#"), "%-#")
16171607

16181608
self.assertRaises(TypeError, t.strftime) # needs an arg
16191609
self.assertRaises(TypeError, t.strftime, "one", "two") # too many args

Modules/_datetimemodule.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,24 +2052,31 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
20522052
}
20532053
continue;
20542054
}
2055-
#if defined(MS_WINDOWS) || defined(__ANDROID__)
20562055
/* non-0-pad Windows and Android support */
20572056
else if (ch == '-' && i < flen) {
20582057
Py_UCS4 next_ch = PyUnicode_READ_CHAR(format, i);
2058+
i++;
2059+
20592060
if (strchr("dmHIMSjUWVy", (int)next_ch) == NULL) {
2060-
PyErr_SetString(PyExc_ValueError, "invalid format string");
2061-
goto Error;
2061+
replacement = PyUnicode_FromFormat("%%%%-%c", (char)next_ch);
2062+
if (replacement == NULL) {
2063+
goto Error;
2064+
}
20622065
}
2063-
i++;
2066+
else {
2067+
#if defined(MS_WINDOWS) || defined(__ANDROID__)
2068+
Py_XDECREF(dash_replacement);
20642069

2065-
Py_XDECREF(dash_replacement);
2066-
dash_replacement = make_dash_replacement(object, next_ch, timetuple);
2067-
if (dash_replacement == NULL) {
2068-
goto Error;
2070+
dash_replacement = make_dash_replacement(object, next_ch, timetuple);
2071+
if (dash_replacement == NULL) {
2072+
goto Error;
2073+
}
2074+
replacement = dash_replacement;
2075+
#else
2076+
continue;
2077+
#endif
20692078
}
2070-
replacement = dash_replacement;
20712079
}
2072-
#endif
20732080
else {
20742081
/* percent followed by something else */
20752082
continue;

0 commit comments

Comments
 (0)