[Python-checkins] python/dist/src/Modules timemodule.c,2.140,2.141
bcannon at users.sourceforge.net
bcannon at users.sourceforge.net
Sat Jun 19 16:48:46 EDT 2004
Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18933/Modules
Modified Files:
timemodule.c
Log Message:
Raise ValueError when value being stored in a time_t variable will result in
more than a second of precision. Primarily affects ctime, localtime, and
gmtime.
Closes bug #919012 thanks to Tim Peters' code.
Tim suggests that the new funciton being introduced, _PyTime_DoubletoTimet(),
should be added to the internal C API and then used in datetime where
appropriate. Not being done now for lack of time.
Index: timemodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/timemodule.c,v
retrieving revision 2.140
retrieving revision 2.141
diff -C2 -d -r2.140 -r2.141
*** timemodule.c 2 Mar 2004 04:38:10 -0000 2.140
--- timemodule.c 19 Jun 2004 20:48:43 -0000 2.141
***************
*** 85,88 ****
--- 85,117 ----
static PyObject *moddict;
+ /* Cast double x to time_t, but raise ValueError if x is too large
+ * to fit in a time_t. ValueError is set on return iff the return
+ * value is (time_t)-1 and PyErr_Occurred().
+ */
+ static time_t
+ _PyTime_DoubleToTimet(double x)
+ {
+ time_t result;
+ double diff;
+
+ result = (time_t)x;
+ /* How much info did we lose? time_t may be an integral or
+ * floating type, and we don't know which. If it's integral,
+ * we don't know whether C truncates, rounds, returns the floor,
+ * etc. If we lost a second or more, the C rounding is
+ * unreasonable, or the input just doesn't fit in a time_t;
+ * call it an error regardless. Note that the original cast to
+ * time_t can cause a C error too, but nothing we can do to
+ * worm around that.
+ */
+ diff = x - (double)result;
+ if (diff <= -1.0 || diff >= 1.0) {
+ PyErr_SetString(PyExc_ValueError,
+ "timestamp out of range for platform time_t");
+ result = (time_t)-1;
+ }
+ return result;
+ }
+
static PyObject *
time_time(PyObject *self, PyObject *args)
***************
*** 232,240 ****
static PyObject *
! time_convert(time_t when, struct tm * (*function)(const time_t *))
{
struct tm *p;
errno = 0;
! p = function(&when);
if (p == NULL) {
#ifdef EINVAL
--- 261,273 ----
static PyObject *
! time_convert(double when, struct tm * (*function)(const time_t *))
{
struct tm *p;
+ time_t whent = _PyTime_DoubleToTimet(when);
+
+ if (whent == (time_t)-1 && PyErr_Occurred())
+ return NULL;
errno = 0;
! p = function(&whent);
if (p == NULL) {
#ifdef EINVAL
***************
*** 255,259 ****
if (!PyArg_ParseTuple(args, "|d:gmtime", &when))
return NULL;
! return time_convert((time_t)when, gmtime);
}
--- 288,292 ----
if (!PyArg_ParseTuple(args, "|d:gmtime", &when))
return NULL;
! return time_convert(when, gmtime);
}
***************
*** 273,277 ****
if (!PyArg_ParseTuple(args, "|d:localtime", &when))
return NULL;
! return time_convert((time_t)when, localtime);
}
--- 306,310 ----
if (!PyArg_ParseTuple(args, "|d:localtime", &when))
return NULL;
! return time_convert(when, localtime);
}
***************
*** 481,485 ****
if (!PyArg_ParseTuple(args, "|d:ctime", &dt))
return NULL;
! tt = (time_t)dt;
}
p = ctime(&tt);
--- 514,520 ----
if (!PyArg_ParseTuple(args, "|d:ctime", &dt))
return NULL;
! tt = _PyTime_DoubleToTimet(dt);
! if (tt == (time_t)-1 && PyErr_Occurred())
! return NULL;
}
p = ctime(&tt);
More information about the Python-checkins
mailing list