From f901abdd62c9067f993b85392dbb73a560af6325 Mon Sep 17 00:00:00 2001 From: Fred Drake Date: Tue, 3 Aug 2004 17:58:55 +0000 Subject: allow ctime(), gmtime(), and localtime() to take None as equivalent to an omitted arg (closes SF bug #658254, patch #663482) --- Doc/lib/libtime.tex | 25 +++++++++++++++++-------- Lib/test/test_time.py | 17 +++++++++++++++++ Misc/NEWS | 5 +++++ Modules/timemodule.c | 39 ++++++++++++++++++++++++++++++--------- 4 files changed, 69 insertions(+), 17 deletions(-) diff --git a/Doc/lib/libtime.tex b/Doc/lib/libtime.tex index 04d02fb..f21f6a3 100644 --- a/Doc/lib/libtime.tex +++ b/Doc/lib/libtime.tex @@ -157,11 +157,14 @@ The resolution is typically better than one microsecond. \begin{funcdesc}{ctime}{\optional{secs}} Convert a time expressed in seconds since the epoch to a string -representing local time. If \var{secs} is not provided, the current time -as returned by \function{time()} is used. \code{ctime(\var{secs})} -is equivalent to \code{asctime(localtime(\var{secs}))}. +representing local time. If \var{secs} is not provided or +\constant{None}, the current time as returned by \function{time()} is +used. \code{ctime(\var{secs})} is equivalent to +\code{asctime(localtime(\var{secs}))}. Locale information is not used by \function{ctime()}. \versionchanged[Allowed \var{secs} to be omitted]{2.1} +\versionchanged[If \var{secs} is \constant{None}, the current time is + used]{2.3} \end{funcdesc} \begin{datadesc}{daylight} @@ -171,16 +174,22 @@ Nonzero if a DST timezone is defined. \begin{funcdesc}{gmtime}{\optional{secs}} Convert a time expressed in seconds since the epoch to a \class{struct_time} in UTC in which the dst flag is always zero. If \var{secs} is not -provided, the current time as returned by \function{time()} is used. -Fractions of a second are ignored. See above for a description of the -\class{struct_time} object. +provided or \constant{None}, the current time as returned by +\function{time()} is used. Fractions of a second are ignored. See +above for a description of the \class{struct_time} object. \versionchanged[Allowed \var{secs} to be omitted]{2.1} +\versionchanged[If \var{secs} is \constant{None}, the current time is + used]{2.3} \end{funcdesc} \begin{funcdesc}{localtime}{\optional{secs}} -Like \function{gmtime()} but converts to local time. The dst flag is -set to \code{1} when DST applies to the given time. +Like \function{gmtime()} but converts to local time. If \var{secs} is +not provided or \constant{None}, the current time as returned by +\function{time()} is used. The dst flag is set to \code{1} when DST +applies to the given time. \versionchanged[Allowed \var{secs} to be omitted]{2.1} +\versionchanged[If \var{secs} is \constant{None}, the current time is + used]{2.3} \end{funcdesc} \begin{funcdesc}{mktime}{t} diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 64f1f01..768e7a0 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -185,6 +185,23 @@ class TimeTestCase(unittest.TestCase): for unreasonable in -1e200, 1e200: self.assertRaises(ValueError, func, unreasonable) + def test_ctime_without_arg(self): + # Not sure how to check the values, since the clock could tick + # at any time. Make sure these are at least accepted and + # don't raise errors. + time.ctime() + time.ctime(None) + + def test_gmtime_without_arg(self): + t0 = time.mktime(time.gmtime()) + t1 = time.mktime(time.gmtime(None)) + self.assert_(0 <= (t1-t0) < 0.2) + + def test_localtime_without_arg(self): + t0 = time.mktime(time.localtime()) + t1 = time.mktime(time.localtime(None)) + self.assert_(0 <= (t1-t0) < 0.2) + def test_main(): test_support.run_unittest(TimeTestCase) diff --git a/Misc/NEWS b/Misc/NEWS index 2ea4cb1..11e224b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -72,6 +72,11 @@ Extension modules Library ------- +- The following methods in time support passing of None: ctime(), gmtime(), + and localtime(). If None is provided, the current time is used (the + same as when the argument is omitted). + [SF bug 658254, patch 663482] + - nntplib does now allow to ignore a .netrc file. - urllib2 now recognizes Basic authentication even if other authentication diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 21745e0..2cd9a57 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -277,13 +277,33 @@ time_convert(double when, struct tm * (*function)(const time_t *)) return tmtotuple(p); } +/* Parse arg tuple that can contain an optional float-or-None value; + format needs to be "|O:name". + Returns non-zero on success (parallels PyArg_ParseTuple). +*/ +static int +parse_time_double_args(PyObject *args, char *format, double *pwhen) +{ + PyObject *ot = NULL; + + if (!PyArg_ParseTuple(args, format, &ot)) + return 0; + if (ot == NULL || ot == Py_None) + *pwhen = floattime(); + else { + double when = PyFloat_AsDouble(ot); + if (PyErr_Occurred()) + return 0; + *pwhen = when; + } + return 1; +} + static PyObject * time_gmtime(PyObject *self, PyObject *args) { double when; - if (PyTuple_Size(args) == 0) - when = floattime(); - if (!PyArg_ParseTuple(args, "|d:gmtime", &when)) + if (!parse_time_double_args(args, "|O:gmtime", &when)) return NULL; return time_convert(when, gmtime); } @@ -299,9 +319,7 @@ static PyObject * time_localtime(PyObject *self, PyObject *args) { double when; - if (PyTuple_Size(args) == 0) - when = floattime(); - if (!PyArg_ParseTuple(args, "|d:localtime", &when)) + if (!parse_time_double_args(args, "|O:localtime", &when)) return NULL; return time_convert(when, localtime); } @@ -502,14 +520,17 @@ is used."); static PyObject * time_ctime(PyObject *self, PyObject *args) { - double dt; + PyObject *ot = NULL; time_t tt; char *p; - if (PyTuple_Size(args) == 0) + if (!PyArg_ParseTuple(args, "|O:ctime", &ot)) + return NULL; + if (ot == NULL || ot == Py_None) tt = time(NULL); else { - if (!PyArg_ParseTuple(args, "|d:ctime", &dt)) + double dt = PyFloat_AsDouble(ot); + if (PyErr_Occurred()) return NULL; tt = _PyTime_DoubleToTimet(dt); if (tt == (time_t)-1 && PyErr_Occurred()) -- cgit v0.12