Issue #22117: Use the _PyTime_t API in _datetime.datetime() constructor
* Remove _PyTime_gettimeofday() * Add _PyTime_GetSystemClock()
This commit is contained in:
parent
10915aa85c
commit
09e5cf28ae
|
@ -13,15 +13,6 @@ functions and constants
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GETTIMEOFDAY
|
|
||||||
typedef struct timeval _PyTime_timeval;
|
|
||||||
#else
|
|
||||||
typedef struct {
|
|
||||||
time_t tv_sec; /* seconds since Jan. 1, 1970 */
|
|
||||||
long tv_usec; /* and microseconds */
|
|
||||||
} _PyTime_timeval;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Structure used by time.get_clock_info() */
|
/* Structure used by time.get_clock_info() */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *implementation;
|
const char *implementation;
|
||||||
|
@ -30,11 +21,6 @@ typedef struct {
|
||||||
double resolution;
|
double resolution;
|
||||||
} _Py_clock_info_t;
|
} _Py_clock_info_t;
|
||||||
|
|
||||||
/* Similar to POSIX gettimeofday but cannot fail. If system gettimeofday
|
|
||||||
* fails or is not available, fall back to lower resolution clocks.
|
|
||||||
*/
|
|
||||||
PyAPI_FUNC(void) _PyTime_gettimeofday(_PyTime_timeval *tp);
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/* Round towards zero. */
|
/* Round towards zero. */
|
||||||
_PyTime_ROUND_DOWN=0,
|
_PyTime_ROUND_DOWN=0,
|
||||||
|
@ -133,6 +119,12 @@ PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t,
|
||||||
PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts);
|
PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Get the current time from the system clock.
|
||||||
|
|
||||||
|
The function cannot fail. _PyTime_Init() ensures that the system clock
|
||||||
|
works. */
|
||||||
|
PyAPI_FUNC(_PyTime_t) _PyTime_GetSystemClock(void);
|
||||||
|
|
||||||
/* Get the current time from the system clock.
|
/* Get the current time from the system clock.
|
||||||
* Fill clock information if info is not NULL.
|
* Fill clock information if info is not NULL.
|
||||||
* Raise an exception and return -1 on error, return 0 on success.
|
* Raise an exception and return -1 on error, return 0 on success.
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
# include <winsock2.h> /* struct timeval */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Differentiate between building the core module and building extension
|
/* Differentiate between building the core module and building extension
|
||||||
* modules.
|
* modules.
|
||||||
*/
|
*/
|
||||||
|
@ -4093,6 +4097,8 @@ datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
|
||||||
|
|
||||||
if (_PyTime_ObjectToTimeval(timestamp, &timet, &us, _PyTime_ROUND_DOWN) == -1)
|
if (_PyTime_ObjectToTimeval(timestamp, &timet, &us, _PyTime_ROUND_DOWN) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
assert(0 <= us && us <= 999999);
|
||||||
|
|
||||||
return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo);
|
return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4103,10 +4109,14 @@ datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
|
||||||
static PyObject *
|
static PyObject *
|
||||||
datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
|
datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
|
||||||
{
|
{
|
||||||
_PyTime_timeval t;
|
_PyTime_t ts = _PyTime_GetSystemClock();
|
||||||
_PyTime_gettimeofday(&t);
|
struct timeval tv;
|
||||||
return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec,
|
|
||||||
tzinfo);
|
if (_PyTime_AsTimeval(ts, &tv, _PyTime_ROUND_FLOOR) < 0)
|
||||||
|
return NULL;
|
||||||
|
assert(0 <= tv.tv_usec && tv.tv_usec <= 999999);
|
||||||
|
|
||||||
|
return datetime_from_timet_and_us(cls, f, tv.tv_sec, tv.tv_usec, tzinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
# include <winsock2.h>
|
# include <winsock2.h> /* struct timeval */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
|
|
119
Python/pytime.c
119
Python/pytime.c
|
@ -19,106 +19,6 @@
|
||||||
#define MS_TO_NS (MS_TO_US * US_TO_NS)
|
#define MS_TO_NS (MS_TO_US * US_TO_NS)
|
||||||
#define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)
|
#define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)
|
||||||
|
|
||||||
static int
|
|
||||||
pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
|
|
||||||
{
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
FILETIME system_time;
|
|
||||||
ULARGE_INTEGER large;
|
|
||||||
ULONGLONG microseconds;
|
|
||||||
|
|
||||||
assert(info == NULL || raise);
|
|
||||||
|
|
||||||
GetSystemTimeAsFileTime(&system_time);
|
|
||||||
large.u.LowPart = system_time.dwLowDateTime;
|
|
||||||
large.u.HighPart = system_time.dwHighDateTime;
|
|
||||||
/* 11,644,473,600,000,000: number of microseconds between
|
|
||||||
the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
|
|
||||||
days). */
|
|
||||||
microseconds = large.QuadPart / 10 - 11644473600000000;
|
|
||||||
tp->tv_sec = microseconds / SEC_TO_US;
|
|
||||||
tp->tv_usec = microseconds % SEC_TO_US;
|
|
||||||
if (info) {
|
|
||||||
DWORD timeAdjustment, timeIncrement;
|
|
||||||
BOOL isTimeAdjustmentDisabled, ok;
|
|
||||||
|
|
||||||
info->implementation = "GetSystemTimeAsFileTime()";
|
|
||||||
info->monotonic = 0;
|
|
||||||
ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
|
|
||||||
&isTimeAdjustmentDisabled);
|
|
||||||
if (!ok) {
|
|
||||||
PyErr_SetFromWindowsErr(0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
info->resolution = timeIncrement * 1e-7;
|
|
||||||
info->adjustable = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* MS_WINDOWS */
|
|
||||||
int err;
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
|
||||||
struct timespec ts;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
assert(info == NULL || raise);
|
|
||||||
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
|
||||||
err = clock_gettime(CLOCK_REALTIME, &ts);
|
|
||||||
if (err) {
|
|
||||||
if (raise)
|
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tp->tv_sec = ts.tv_sec;
|
|
||||||
tp->tv_usec = ts.tv_nsec / US_TO_NS;
|
|
||||||
|
|
||||||
if (info) {
|
|
||||||
struct timespec res;
|
|
||||||
info->implementation = "clock_gettime(CLOCK_REALTIME)";
|
|
||||||
info->monotonic = 0;
|
|
||||||
info->adjustable = 1;
|
|
||||||
if (clock_getres(CLOCK_REALTIME, &res) == 0)
|
|
||||||
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
|
|
||||||
else
|
|
||||||
info->resolution = 1e-9;
|
|
||||||
}
|
|
||||||
#else /* HAVE_CLOCK_GETTIME */
|
|
||||||
|
|
||||||
/* test gettimeofday() */
|
|
||||||
#ifdef GETTIMEOFDAY_NO_TZ
|
|
||||||
err = gettimeofday(tp);
|
|
||||||
#else
|
|
||||||
err = gettimeofday(tp, (struct timezone *)NULL);
|
|
||||||
#endif
|
|
||||||
if (err) {
|
|
||||||
if (raise)
|
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info) {
|
|
||||||
info->implementation = "gettimeofday()";
|
|
||||||
info->resolution = 1e-6;
|
|
||||||
info->monotonic = 0;
|
|
||||||
info->adjustable = 1;
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_CLOCK_GETTIME */
|
|
||||||
#endif /* !MS_WINDOWS */
|
|
||||||
assert(0 <= tp->tv_usec && tp->tv_usec < SEC_TO_US);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_PyTime_gettimeofday(_PyTime_timeval *tp)
|
|
||||||
{
|
|
||||||
if (pygettimeofday(tp, NULL, 0) < 0) {
|
|
||||||
/* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
|
|
||||||
assert(0);
|
|
||||||
tp->tv_sec = 0;
|
|
||||||
tp->tv_usec = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
error_time_t_overflow(void)
|
error_time_t_overflow(void)
|
||||||
{
|
{
|
||||||
|
@ -577,6 +477,20 @@ pygettimeofday_new(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_PyTime_t
|
||||||
|
_PyTime_GetSystemClock(void)
|
||||||
|
{
|
||||||
|
_PyTime_t t;
|
||||||
|
if (pygettimeofday_new(&t, NULL, 0) < 0) {
|
||||||
|
/* should not happen, _PyTime_Init() checked the clock at startup */
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
/* use a fixed value instead of a random value from the stack */
|
||||||
|
t = 0;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
|
_PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
|
||||||
{
|
{
|
||||||
|
@ -715,13 +629,8 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
int
|
int
|
||||||
_PyTime_Init(void)
|
_PyTime_Init(void)
|
||||||
{
|
{
|
||||||
_PyTime_timeval tv;
|
|
||||||
_PyTime_t t;
|
_PyTime_t t;
|
||||||
|
|
||||||
/* ensure that the system clock works */
|
|
||||||
if (pygettimeofday(&tv, NULL, 1) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* ensure that the system clock works */
|
/* ensure that the system clock works */
|
||||||
if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0)
|
if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue