Skip to content

Commit 09e5cf2

Browse files
committed
Issue python#22117: Use the _PyTime_t API in _datetime.datetime() constructor
* Remove _PyTime_gettimeofday() * Add _PyTime_GetSystemClock()
1 parent 10915aa commit 09e5cf2

4 files changed

Lines changed: 35 additions & 124 deletions

File tree

Include/pytime.h

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,6 @@ functions and constants
1313
extern "C" {
1414
#endif
1515

16-
#ifdef HAVE_GETTIMEOFDAY
17-
typedef struct timeval _PyTime_timeval;
18-
#else
19-
typedef struct {
20-
time_t tv_sec; /* seconds since Jan. 1, 1970 */
21-
long tv_usec; /* and microseconds */
22-
} _PyTime_timeval;
23-
#endif
24-
2516
/* Structure used by time.get_clock_info() */
2617
typedef struct {
2718
const char *implementation;
@@ -30,11 +21,6 @@ typedef struct {
3021
double resolution;
3122
} _Py_clock_info_t;
3223

33-
/* Similar to POSIX gettimeofday but cannot fail. If system gettimeofday
34-
* fails or is not available, fall back to lower resolution clocks.
35-
*/
36-
PyAPI_FUNC(void) _PyTime_gettimeofday(_PyTime_timeval *tp);
37-
3824
typedef enum {
3925
/* Round towards zero. */
4026
_PyTime_ROUND_DOWN=0,
@@ -133,6 +119,12 @@ PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t,
133119
PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts);
134120
#endif
135121

122+
/* Get the current time from the system clock.
123+
124+
The function cannot fail. _PyTime_Init() ensures that the system clock
125+
works. */
126+
PyAPI_FUNC(_PyTime_t) _PyTime_GetSystemClock(void);
127+
136128
/* Get the current time from the system clock.
137129
* Fill clock information if info is not NULL.
138130
* Raise an exception and return -1 on error, return 0 on success.

Modules/_datetimemodule.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
#include <time.h>
99

10+
#ifdef MS_WINDOWS
11+
# include <winsock2.h> /* struct timeval */
12+
#endif
13+
1014
/* Differentiate between building the core module and building extension
1115
* modules.
1216
*/
@@ -4093,6 +4097,8 @@ datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
40934097

40944098
if (_PyTime_ObjectToTimeval(timestamp, &timet, &us, _PyTime_ROUND_DOWN) == -1)
40954099
return NULL;
4100+
assert(0 <= us && us <= 999999);
4101+
40964102
return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo);
40974103
}
40984104

@@ -4103,10 +4109,14 @@ datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
41034109
static PyObject *
41044110
datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
41054111
{
4106-
_PyTime_timeval t;
4107-
_PyTime_gettimeofday(&t);
4108-
return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec,
4109-
tzinfo);
4112+
_PyTime_t ts = _PyTime_GetSystemClock();
4113+
struct timeval tv;
4114+
4115+
if (_PyTime_AsTimeval(ts, &tv, _PyTime_ROUND_FLOOR) < 0)
4116+
return NULL;
4117+
assert(0 <= tv.tv_usec && tv.tv_usec <= 999999);
4118+
4119+
return datetime_from_timet_and_us(cls, f, tv.tv_sec, tv.tv_usec, tzinfo);
41104120
}
41114121

41124122
/*[clinic input]

Modules/_testcapimodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <signal.h>
1616

1717
#ifdef MS_WINDOWS
18-
# include <winsock2.h>
18+
# include <winsock2.h> /* struct timeval */
1919
#endif
2020

2121
#ifdef WITH_THREAD

Python/pytime.c

Lines changed: 14 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -19,106 +19,6 @@
1919
#define MS_TO_NS (MS_TO_US * US_TO_NS)
2020
#define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)
2121

22-
static int
23-
pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
24-
{
25-
#ifdef MS_WINDOWS
26-
FILETIME system_time;
27-
ULARGE_INTEGER large;
28-
ULONGLONG microseconds;
29-
30-
assert(info == NULL || raise);
31-
32-
GetSystemTimeAsFileTime(&system_time);
33-
large.u.LowPart = system_time.dwLowDateTime;
34-
large.u.HighPart = system_time.dwHighDateTime;
35-
/* 11,644,473,600,000,000: number of microseconds between
36-
the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
37-
days). */
38-
microseconds = large.QuadPart / 10 - 11644473600000000;
39-
tp->tv_sec = microseconds / SEC_TO_US;
40-
tp->tv_usec = microseconds % SEC_TO_US;
41-
if (info) {
42-
DWORD timeAdjustment, timeIncrement;
43-
BOOL isTimeAdjustmentDisabled, ok;
44-
45-
info->implementation = "GetSystemTimeAsFileTime()";
46-
info->monotonic = 0;
47-
ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
48-
&isTimeAdjustmentDisabled);
49-
if (!ok) {
50-
PyErr_SetFromWindowsErr(0);
51-
return -1;
52-
}
53-
info->resolution = timeIncrement * 1e-7;
54-
info->adjustable = 1;
55-
}
56-
57-
#else /* MS_WINDOWS */
58-
int err;
59-
#ifdef HAVE_CLOCK_GETTIME
60-
struct timespec ts;
61-
#endif
62-
63-
assert(info == NULL || raise);
64-
65-
#ifdef HAVE_CLOCK_GETTIME
66-
err = clock_gettime(CLOCK_REALTIME, &ts);
67-
if (err) {
68-
if (raise)
69-
PyErr_SetFromErrno(PyExc_OSError);
70-
return -1;
71-
}
72-
tp->tv_sec = ts.tv_sec;
73-
tp->tv_usec = ts.tv_nsec / US_TO_NS;
74-
75-
if (info) {
76-
struct timespec res;
77-
info->implementation = "clock_gettime(CLOCK_REALTIME)";
78-
info->monotonic = 0;
79-
info->adjustable = 1;
80-
if (clock_getres(CLOCK_REALTIME, &res) == 0)
81-
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
82-
else
83-
info->resolution = 1e-9;
84-
}
85-
#else /* HAVE_CLOCK_GETTIME */
86-
87-
/* test gettimeofday() */
88-
#ifdef GETTIMEOFDAY_NO_TZ
89-
err = gettimeofday(tp);
90-
#else
91-
err = gettimeofday(tp, (struct timezone *)NULL);
92-
#endif
93-
if (err) {
94-
if (raise)
95-
PyErr_SetFromErrno(PyExc_OSError);
96-
return -1;
97-
}
98-
99-
if (info) {
100-
info->implementation = "gettimeofday()";
101-
info->resolution = 1e-6;
102-
info->monotonic = 0;
103-
info->adjustable = 1;
104-
}
105-
#endif /* !HAVE_CLOCK_GETTIME */
106-
#endif /* !MS_WINDOWS */
107-
assert(0 <= tp->tv_usec && tp->tv_usec < SEC_TO_US);
108-
return 0;
109-
}
110-
111-
void
112-
_PyTime_gettimeofday(_PyTime_timeval *tp)
113-
{
114-
if (pygettimeofday(tp, NULL, 0) < 0) {
115-
/* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
116-
assert(0);
117-
tp->tv_sec = 0;
118-
tp->tv_usec = 0;
119-
}
120-
}
121-
12222
static void
12323
error_time_t_overflow(void)
12424
{
@@ -577,6 +477,20 @@ pygettimeofday_new(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
577477
return 0;
578478
}
579479

480+
_PyTime_t
481+
_PyTime_GetSystemClock(void)
482+
{
483+
_PyTime_t t;
484+
if (pygettimeofday_new(&t, NULL, 0) < 0) {
485+
/* should not happen, _PyTime_Init() checked the clock at startup */
486+
assert(0);
487+
488+
/* use a fixed value instead of a random value from the stack */
489+
t = 0;
490+
}
491+
return t;
492+
}
493+
580494
int
581495
_PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
582496
{
@@ -715,13 +629,8 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
715629
int
716630
_PyTime_Init(void)
717631
{
718-
_PyTime_timeval tv;
719632
_PyTime_t t;
720633

721-
/* ensure that the system clock works */
722-
if (pygettimeofday(&tv, NULL, 1) < 0)
723-
return -1;
724-
725634
/* ensure that the system clock works */
726635
if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0)
727636
return -1;

0 commit comments

Comments
 (0)