mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
Close #14180: Factorize code to convert a number of seconds to time_t, timeval or timespec
time.ctime(), gmtime(), time.localtime(), datetime.date.fromtimestamp(), datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now raises an OverflowError, instead of a ValueError, if the timestamp does not fit in time_t. datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now round microseconds towards zero instead of rounding to nearest with ties going away from zero.
This commit is contained in:
parent
3cac309939
commit
5d272cc6a2
16 changed files with 278 additions and 222 deletions
101
Python/pytime.c
101
Python/pytime.c
|
@ -70,9 +70,37 @@ _PyTime_gettimeofday(_PyTime_timeval *tp)
|
|||
#endif /* MS_WINDOWS */
|
||||
}
|
||||
|
||||
int
|
||||
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
|
||||
static void
|
||||
error_time_t_overflow(void)
|
||||
{
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"timestamp out of range for platform time_t");
|
||||
}
|
||||
|
||||
static time_t
|
||||
_PyLong_AsTime_t(PyObject *obj)
|
||||
{
|
||||
#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
|
||||
PY_LONG_LONG val;
|
||||
val = PyLong_AsLongLong(obj);
|
||||
#else
|
||||
long val;
|
||||
assert(sizeof(time_t) <= sizeof(long));
|
||||
val = PyLong_AsLong(obj);
|
||||
#endif
|
||||
if (val == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
||||
error_time_t_overflow();
|
||||
return -1;
|
||||
}
|
||||
return (time_t)val;
|
||||
}
|
||||
|
||||
static int
|
||||
_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
||||
double denominator)
|
||||
{
|
||||
assert(denominator <= LONG_MAX);
|
||||
if (PyFloat_Check(obj)) {
|
||||
double d, intpart, floatpart, err;
|
||||
|
||||
|
@ -85,34 +113,61 @@ _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
|
|||
|
||||
*sec = (time_t)intpart;
|
||||
err = intpart - (double)*sec;
|
||||
if (err <= -1.0 || err >= 1.0)
|
||||
goto overflow;
|
||||
if (err <= -1.0 || err >= 1.0) {
|
||||
error_time_t_overflow();
|
||||
return -1;
|
||||
}
|
||||
|
||||
floatpart *= 1e9;
|
||||
*nsec = (long)floatpart;
|
||||
floatpart *= denominator;
|
||||
*numerator = (long)floatpart;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
|
||||
*sec = PyLong_AsLongLong(obj);
|
||||
#else
|
||||
assert(sizeof(time_t) <= sizeof(long));
|
||||
*sec = PyLong_AsLong(obj);
|
||||
#endif
|
||||
if (*sec == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
||||
goto overflow;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
*nsec = 0;
|
||||
*sec = _PyLong_AsTime_t(obj);
|
||||
if (*sec == (time_t)-1 && PyErr_Occurred())
|
||||
return -1;
|
||||
*numerator = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
overflow:
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"timestamp out of range for platform time_t");
|
||||
return -1;
|
||||
int
|
||||
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec)
|
||||
{
|
||||
if (PyFloat_Check(obj)) {
|
||||
double d, intpart, err;
|
||||
|
||||
/*whent = _PyTime_DoubleToTimet(d);*/
|
||||
|
||||
d = PyFloat_AsDouble(obj);
|
||||
(void)modf(d, &intpart);
|
||||
|
||||
*sec = (time_t)intpart;
|
||||
err = intpart - (double)*sec;
|
||||
if (err <= -1.0 || err >= 1.0) {
|
||||
error_time_t_overflow();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
*sec = _PyLong_AsTime_t(obj);
|
||||
if (*sec == (time_t)-1 && PyErr_Occurred())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
|
||||
{
|
||||
return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9);
|
||||
}
|
||||
|
||||
int
|
||||
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec)
|
||||
{
|
||||
return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue