@@ -1848,13 +1848,23 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
18481848 const char * ptoappend ; /* ptr to string to append to output buffer */
18491849 Py_ssize_t ntoappend ; /* # of bytes to append to output buffer */
18501850
1851+ #ifdef Py_NORMALIZE_CENTURY
1852+ /* Buffer of maximum size of formatted year permitted by long. */
1853+ char buf [SIZEOF_LONG * 5 /2 + 2 ];
1854+ #endif
1855+
18511856 assert (object && format && timetuple );
18521857 assert (PyUnicode_Check (format ));
18531858 /* Convert the input format to a C string and size */
18541859 pin = PyUnicode_AsUTF8AndSize (format , & flen );
18551860 if (!pin )
18561861 return NULL ;
18571862
1863+ PyObject * strftime = _PyImport_GetModuleAttrString ("time" , "strftime" );
1864+ if (strftime == NULL ) {
1865+ goto Done ;
1866+ }
1867+
18581868 /* Scan the input format, looking for %z/%Z/%f escapes, building
18591869 * a new format. Since computing the replacements for those codes
18601870 * is expensive, don't unless they're actually used.
@@ -1936,8 +1946,47 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
19361946 ptoappend = PyBytes_AS_STRING (freplacement );
19371947 ntoappend = PyBytes_GET_SIZE (freplacement );
19381948 }
1949+ #ifdef Py_NORMALIZE_CENTURY
1950+ else if (ch == 'Y' || ch == 'G' ) {
1951+ /* 0-pad year with century as necessary */
1952+ PyObject * item = PyTuple_GET_ITEM (timetuple , 0 );
1953+ long year_long = PyLong_AsLong (item );
1954+
1955+ if (year_long == -1 && PyErr_Occurred ()) {
1956+ goto Done ;
1957+ }
1958+ /* Note that datetime(1000, 1, 1).strftime('%G') == '1000' so year
1959+ 1000 for %G can go on the fast path. */
1960+ if (year_long >= 1000 ) {
1961+ goto PassThrough ;
1962+ }
1963+ if (ch == 'G' ) {
1964+ PyObject * year_str = PyObject_CallFunction (strftime , "sO" ,
1965+ "%G" , timetuple );
1966+ if (year_str == NULL ) {
1967+ goto Done ;
1968+ }
1969+ PyObject * year = PyNumber_Long (year_str );
1970+ Py_DECREF (year_str );
1971+ if (year == NULL ) {
1972+ goto Done ;
1973+ }
1974+ year_long = PyLong_AsLong (year );
1975+ Py_DECREF (year );
1976+ if (year_long == -1 && PyErr_Occurred ()) {
1977+ goto Done ;
1978+ }
1979+ }
1980+
1981+ ntoappend = PyOS_snprintf (buf , sizeof (buf ), "%04ld" , year_long );
1982+ ptoappend = buf ;
1983+ }
1984+ #endif
19391985 else {
19401986 /* percent followed by something else */
1987+ #ifdef Py_NORMALIZE_CENTURY
1988+ PassThrough :
1989+ #endif
19411990 ptoappend = pin - 2 ;
19421991 ntoappend = 2 ;
19431992 }
@@ -1969,24 +2018,21 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
19692018 goto Done ;
19702019 {
19712020 PyObject * format ;
1972- PyObject * strftime = _PyImport_GetModuleAttrString ("time" , "strftime" );
19732021
1974- if (strftime == NULL )
1975- goto Done ;
19762022 format = PyUnicode_FromString (PyBytes_AS_STRING (newfmt ));
19772023 if (format != NULL ) {
19782024 result = PyObject_CallFunctionObjArgs (strftime ,
19792025 format , timetuple , NULL );
19802026 Py_DECREF (format );
19812027 }
1982- Py_DECREF (strftime );
19832028 }
19842029 Done :
19852030 Py_XDECREF (freplacement );
19862031 Py_XDECREF (zreplacement );
19872032 Py_XDECREF (colonzreplacement );
19882033 Py_XDECREF (Zreplacement );
19892034 Py_XDECREF (newfmt );
2035+ Py_XDECREF (strftime );
19902036 return result ;
19912037}
19922038
0 commit comments