mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-31784: Implement PEP 564: add time.time_ns() (#3989)
Add new time functions: * time.clock_gettime_ns() * time.clock_settime_ns() * time.monotonic_ns() * time.perf_counter_ns() * time.process_time_ns() * time.time_ns() Add new _PyTime functions: * _PyTime_FromTimespec() * _PyTime_FromNanosecondsObject() * _PyTime_FromTimeval() Other changes: * Add also os.times() tests to test_os. * pytime_fromtimeval() and pytime_fromtimeval() now return _PyTime_MAX or _PyTime_MIN on overflow, rather than undefined behaviour * _PyTime_FromNanoseconds() parameter type changes from long long to _PyTime_t
This commit is contained in:
parent
e314853d57
commit
c29b585fd4
9 changed files with 593 additions and 175 deletions
107
Python/pytime.c
107
Python/pytime.c
|
@ -43,8 +43,7 @@ _PyTime_overflow(void)
|
|||
}
|
||||
|
||||
|
||||
#if defined(MS_WINDOWS) || defined(__APPLE__)
|
||||
Py_LOCAL_INLINE(_PyTime_t)
|
||||
_PyTime_t
|
||||
_PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div)
|
||||
{
|
||||
_PyTime_t intpart, remaining;
|
||||
|
@ -60,7 +59,6 @@ _PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div)
|
|||
remaining /= div;
|
||||
return intpart * mul + remaining;
|
||||
}
|
||||
#endif /* defined(MS_WINDOWS) || defined(__APPLE__) */
|
||||
|
||||
|
||||
time_t
|
||||
|
@ -254,19 +252,44 @@ _PyTime_FromSeconds(int seconds)
|
|||
}
|
||||
|
||||
_PyTime_t
|
||||
_PyTime_FromNanoseconds(long long ns)
|
||||
_PyTime_FromNanoseconds(_PyTime_t ns)
|
||||
{
|
||||
/* _PyTime_t already uses nanosecond resolution, no conversion needed */
|
||||
return ns;
|
||||
}
|
||||
|
||||
int
|
||||
_PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj)
|
||||
{
|
||||
long long nsec;
|
||||
_PyTime_t t;
|
||||
Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t));
|
||||
t = Py_SAFE_DOWNCAST(ns, long long, _PyTime_t);
|
||||
return t;
|
||||
|
||||
if (!PyLong_Check(obj)) {
|
||||
PyErr_Format(PyExc_TypeError, "expect int, got %s",
|
||||
Py_TYPE(obj)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_BUILD_ASSERT(sizeof(long long) == sizeof(_PyTime_t));
|
||||
nsec = PyLong_AsLongLong(obj);
|
||||
if (nsec == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||
_PyTime_overflow();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* _PyTime_t already uses nanosecond resolution, no conversion needed */
|
||||
t = (_PyTime_t)nsec;
|
||||
*tp = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
static int
|
||||
_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
|
||||
pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise)
|
||||
{
|
||||
_PyTime_t t;
|
||||
_PyTime_t t, nsec;
|
||||
int res = 0;
|
||||
|
||||
Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t));
|
||||
|
@ -277,19 +300,42 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
|
|||
_PyTime_overflow();
|
||||
}
|
||||
res = -1;
|
||||
t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
|
||||
}
|
||||
else {
|
||||
t = t * SEC_TO_NS;
|
||||
}
|
||||
t = t * SEC_TO_NS;
|
||||
|
||||
t += ts->tv_nsec;
|
||||
nsec = ts->tv_nsec;
|
||||
/* The following test is written for positive only nsec */
|
||||
assert(nsec >= 0);
|
||||
if (t > _PyTime_MAX - nsec) {
|
||||
if (raise) {
|
||||
_PyTime_overflow();
|
||||
}
|
||||
res = -1;
|
||||
t = _PyTime_MAX;
|
||||
}
|
||||
else {
|
||||
t += nsec;
|
||||
}
|
||||
|
||||
*tp = t;
|
||||
return res;
|
||||
}
|
||||
#elif !defined(MS_WINDOWS)
|
||||
static int
|
||||
_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
|
||||
|
||||
int
|
||||
_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts)
|
||||
{
|
||||
_PyTime_t t;
|
||||
return pytime_fromtimespec(tp, ts, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(MS_WINDOWS)
|
||||
static int
|
||||
pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise)
|
||||
{
|
||||
_PyTime_t t, usec;
|
||||
int res = 0;
|
||||
|
||||
Py_BUILD_ASSERT(sizeof(tv->tv_sec) <= sizeof(_PyTime_t));
|
||||
|
@ -300,14 +346,35 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
|
|||
_PyTime_overflow();
|
||||
}
|
||||
res = -1;
|
||||
t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
|
||||
}
|
||||
else {
|
||||
t = t * SEC_TO_NS;
|
||||
}
|
||||
t = t * SEC_TO_NS;
|
||||
|
||||
t += (_PyTime_t)tv->tv_usec * US_TO_NS;
|
||||
usec = (_PyTime_t)tv->tv_usec * US_TO_NS;
|
||||
/* The following test is written for positive only usec */
|
||||
assert(usec >= 0);
|
||||
if (t > _PyTime_MAX - usec) {
|
||||
if (raise) {
|
||||
_PyTime_overflow();
|
||||
}
|
||||
res = -1;
|
||||
t = _PyTime_MAX;
|
||||
}
|
||||
else {
|
||||
t += usec;
|
||||
}
|
||||
|
||||
*tp = t;
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv)
|
||||
{
|
||||
return pytime_fromtimeval(tp, tv, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
|
@ -632,7 +699,7 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
if (_PyTime_FromTimespec(tp, &ts, raise) < 0) {
|
||||
if (pytime_fromtimespec(tp, &ts, raise) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -662,7 +729,7 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
if (_PyTime_FromTimeval(tp, &tv, raise) < 0) {
|
||||
if (pytime_fromtimeval(tp, &tv, raise) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -841,7 +908,7 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
|||
}
|
||||
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
|
||||
}
|
||||
if (_PyTime_FromTimespec(tp, &ts, raise) < 0) {
|
||||
if (pytime_fromtimespec(tp, &ts, raise) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue