@@ -1851,13 +1851,23 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
18511851 const char * ptoappend ; /* ptr to string to append to output buffer */
18521852 Py_ssize_t ntoappend ; /* # of bytes to append to output buffer */
18531853
1854+ #ifdef Py_NORMALIZE_CENTURY
1855+ /* Buffer of maximum size of formatted year permitted by long. */
1856+ char buf [SIZEOF_LONG * 5 /2 + 2 ];
1857+ #endif
1858+
18541859 assert (object && format && timetuple );
18551860 assert (PyUnicode_Check (format ));
18561861 /* Convert the input format to a C string and size */
18571862 pin = PyUnicode_AsUTF8AndSize (format , & flen );
18581863 if (!pin )
18591864 return NULL ;
18601865
1866+ PyObject * strftime = _PyImport_GetModuleAttrString ("time" , "strftime" );
1867+ if (strftime == NULL ) {
1868+ goto Done ;
1869+ }
1870+
18611871 /* Scan the input format, looking for %z/%Z/%f escapes, building
18621872 * a new format. Since computing the replacements for those codes
18631873 * is expensive, don't unless they're actually used.
@@ -1939,8 +1949,47 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
19391949 ptoappend = PyBytes_AS_STRING (freplacement );
19401950 ntoappend = PyBytes_GET_SIZE (freplacement );
19411951 }
1952+ #ifdef Py_NORMALIZE_CENTURY
1953+ else if (ch == 'Y' || ch == 'G' ) {
1954+ /* 0-pad year with century as necessary */
1955+ PyObject * item = PyTuple_GET_ITEM (timetuple , 0 );
1956+ long year_long = PyLong_AsLong (item );
1957+
1958+ if (year_long == -1 && PyErr_Occurred ()) {
1959+ goto Done ;
1960+ }
1961+ /* Note that datetime(1000, 1, 1).strftime('%G') == '1000' so year
1962+ 1000 for %G can go on the fast path. */
1963+ if (year_long >= 1000 ) {
1964+ goto PassThrough ;
1965+ }
1966+ if (ch == 'G' ) {
1967+ PyObject * year_str = PyObject_CallFunction (strftime , "sO" ,
1968+ "%G" , timetuple );
1969+ if (year_str == NULL ) {
1970+ goto Done ;
1971+ }
1972+ PyObject * year = PyNumber_Long (year_str );
1973+ Py_DECREF (year_str );
1974+ if (year == NULL ) {
1975+ goto Done ;
1976+ }
1977+ year_long = PyLong_AsLong (year );
1978+ Py_DECREF (year );
1979+ if (year_long == -1 && PyErr_Occurred ()) {
1980+ goto Done ;
1981+ }
1982+ }
1983+
1984+ ntoappend = PyOS_snprintf (buf , sizeof (buf ), "%04ld" , year_long );
1985+ ptoappend = buf ;
1986+ }
1987+ #endif
19421988 else {
19431989 /* percent followed by something else */
1990+ #ifdef Py_NORMALIZE_CENTURY
1991+ PassThrough :
1992+ #endif
19441993 ptoappend = pin - 2 ;
19451994 ntoappend = 2 ;
19461995 }
@@ -1972,24 +2021,21 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
19722021 goto Done ;
19732022 {
19742023 PyObject * format ;
1975- PyObject * strftime = _PyImport_GetModuleAttrString ("time" , "strftime" );
19762024
1977- if (strftime == NULL )
1978- goto Done ;
19792025 format = PyUnicode_FromString (PyBytes_AS_STRING (newfmt ));
19802026 if (format != NULL ) {
19812027 result = PyObject_CallFunctionObjArgs (strftime ,
19822028 format , timetuple , NULL );
19832029 Py_DECREF (format );
19842030 }
1985- Py_DECREF (strftime );
19862031 }
19872032 Done :
19882033 Py_XDECREF (freplacement );
19892034 Py_XDECREF (zreplacement );
19902035 Py_XDECREF (colonzreplacement );
19912036 Py_XDECREF (Zreplacement );
19922037 Py_XDECREF (newfmt );
2038+ Py_XDECREF (strftime );
19932039 return result ;
19942040}
19952041
0 commit comments