Index: Doc/library/time.rst =================================================================== --- Doc/library/time.rst (revision 87690) +++ Doc/library/time.rst (working copy) @@ -125,7 +125,7 @@ .. function:: asctime([t]) Convert a tuple or :class:`struct_time` representing a time as returned by - :func:`gmtime` or :func:`localtime` to a 24-character string of the following + :func:`gmtime` or :func:`localtime` to a string of the following form: ``'Sun Jun 20 23:21:05 1993'``. If *t* is not provided, the current time as returned by :func:`localtime` is used. Locale information is not used by :func:`asctime`. Index: Lib/test/test_time.py =================================================================== --- Lib/test/test_time.py (revision 87690) +++ Lib/test/test_time.py (working copy) @@ -123,32 +123,20 @@ time.asctime(time.gmtime(self.t)) self.assertRaises(TypeError, time.asctime, 0) self.assertRaises(TypeError, time.asctime, ()) - # XXX: POSIX-compliant asctime should refuse to convert year > 9999, - # but glibc implementation does not. For now, just check it doesn't - # segfault as it did before, and the result contains no newline. - try: - result = time.asctime((12345, 1, 0, 0, 0, 0, 0, 0, 0)) - except ValueError: - # for POSIX-compliant runtimes - pass - else: - self.assertNotIn('\n', result) + bigyear = 1234567890 + self.assertEqual(time.asctime((bigyear, 6, 1) + (0,)*6)[-10:], + str(bigyear)) def test_asctime_bounding_check(self): self._bounds_checking(time.asctime) def test_ctime(self): - # XXX: POSIX-compliant ctime should refuse to convert year > 9999, - # but glibc implementation does not. For now, just check it doesn't - # segfault as it did before, and the result contains no newline. try: - result = time.ctime(1e12) + bigval = time.mktime((10000, 1, 10) + (0,)*6) except ValueError: - # for POSIX-compliant runtimes (or 32-bit systems, where time_t - # cannot hold timestamps with a five-digit year) pass else: - self.assertNotIn('\n', result) + self.assertEquals(time.ctime(bigval)[-5:], '10000') @unittest.skipIf(not hasattr(time, "tzset"), "time module has no attribute tzset") Index: Modules/timemodule.c =================================================================== --- Modules/timemodule.c (revision 87690) +++ Modules/timemodule.c (working copy) @@ -599,19 +599,42 @@ return strptime_result; } + PyDoc_STRVAR(strptime_doc, "strptime(string, format) -> struct_time\n\ \n\ Parse a string to a time tuple according to a format specification.\n\ See the library reference manual for formatting codes (same as strftime())."); +static PyObject * +_asctime(struct tm *timeptr) +{ + /* Inspired by Open Group reference implementation available at + * http://pubs.opengroup.org/onlinepubs/009695399/functions/asctime.html */ + char buf[20]; /* 'Sun Sep 16 01:03:52\0' */ + static char wday_name[7][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + static char mon_name[12][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + sprintf(buf, "%.3s %.3s%3d %.2d:%.2d:%.2d", + wday_name[timeptr->tm_wday], + mon_name[timeptr->tm_mon], + timeptr->tm_mday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec); + + return PyUnicode_FromFormat("%s %d", buf, 1900 + timeptr->tm_year); +} + static PyObject * time_asctime(PyObject *self, PyObject *args) { PyObject *tup = NULL; struct tm buf; - char *p, *q; + if (!PyArg_UnpackTuple(args, "asctime", 0, 1, &tup)) return NULL; if (tup == NULL) { @@ -619,17 +642,7 @@ buf = *localtime(&tt); } else if (!gettmarg(tup, &buf) || !checktm(&buf)) return NULL; - p = asctime(&buf); - if (p == NULL) { - PyErr_SetString(PyExc_ValueError, "unconvertible time"); - return NULL; - } - /* Replace a terminating newline by a null byte, normally at position 24. - * It can occur later if the year has more than four digits. */ - for (q = p+24; *q != '\0'; q++) - if (*q == '\n') - *q = '\0'; - return PyUnicode_FromString(p); + return _asctime(&buf); } PyDoc_STRVAR(asctime_doc, @@ -644,7 +657,7 @@ { PyObject *ot = NULL; time_t tt; - char *p, *q; + struct tm *timeptr; if (!PyArg_UnpackTuple(args, "ctime", 0, 1, &ot)) return NULL; @@ -658,17 +671,12 @@ if (tt == (time_t)-1 && PyErr_Occurred()) return NULL; } - p = ctime(&tt); - if (p == NULL) { + timeptr = localtime(&tt); + if (timeptr == NULL) { PyErr_SetString(PyExc_ValueError, "unconvertible time"); - return NULL; + return NULL; } - /* Replace a terminating newline by a null byte, normally at position 24. - * It can occur later if the year has more than four digits. */ - for (q = p+24; *q != '\0'; q++) - if (*q == '\n') - *q = '\0'; - return PyUnicode_FromString(p); + return _asctime(timeptr); } PyDoc_STRVAR(ctime_doc,