1. Armin Rigo
  2. cpython-withatomic

Commits

Fred Drake  committed 582eb51

allow ctime(), gmtime(), and localtime() to take None as equivalent to an omitted arg
(closes SF bug #658254, patch #663482)

  • Participants
  • Parent commits 8ce344f
  • Branches legacy-trunk

Comments (0)

Files changed (4)

File Doc/lib/libtime.tex

View file
 
 \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}
 \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}

File Lib/test/test_time.py

View file
             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)
 

File Misc/NEWS

View file
 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

File Modules/timemodule.c

View file
 	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);
 }
 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);
 }
 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())