]> granicus.if.org Git - python/commitdiff
Issue #22117: Use the _PyTime_t API in _datetime.datetime() constructor
authorVictor Stinner <victor.stinner@gmail.com>
Sun, 29 Mar 2015 22:09:18 +0000 (00:09 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Sun, 29 Mar 2015 22:09:18 +0000 (00:09 +0200)
* Remove _PyTime_gettimeofday()
* Add _PyTime_GetSystemClock()

Include/pytime.h
Modules/_datetimemodule.c
Modules/_testcapimodule.c
Python/pytime.c

index 0ff009a9505b4988362002d654b7cdaf8d6a5ed9..919ba30e5e5ba7153277e4e32157977c27585898 100644 (file)
@@ -13,15 +13,6 @@ functions and constants
 extern "C" {
 #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() */
 typedef struct {
     const char *implementation;
@@ -30,11 +21,6 @@ typedef struct {
     double resolution;
 } _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 {
     /* Round towards zero. */
     _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);
 #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.
  * Fill clock information if info is not NULL.
  * Raise an exception and return -1 on error, return 0 on success.
index 09285d919dea5502bbe38ca1c47386f5a126e5cd..c3e54f7af43530d198617d7df8630ae5c127853f 100644 (file)
@@ -7,6 +7,10 @@
 
 #include <time.h>
 
+#ifdef MS_WINDOWS
+#  include <winsock2.h>         /* struct timeval */
+#endif
+
 /* Differentiate between building the core module and building extension
  * 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)
         return NULL;
+    assert(0 <= us && us <= 999999);
+
     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 *
 datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
 {
-    _PyTime_timeval t;
-    _PyTime_gettimeofday(&t);
-    return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec,
-                                      tzinfo);
+    _PyTime_t ts = _PyTime_GetSystemClock();
+    struct timeval tv;
+
+    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]
index 5c54ad6785eef2da477784527e087d8c4adf09ad..9abb7ccd1955d6a3c584d765100478d280959439 100644 (file)
@@ -15,7 +15,7 @@
 #include <signal.h>
 
 #ifdef MS_WINDOWS
-#  include <winsock2.h>
+#  include <winsock2.h>         /* struct timeval */
 #endif
 
 #ifdef WITH_THREAD
index d23d9d36b9e1dd0f134213e38dbde85b39b7ce34..11e3a627ed9bcd6d820eda1cb4f1cc907239c5da 100644 (file)
 #define MS_TO_NS (MS_TO_US * US_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
 error_time_t_overflow(void)
 {
@@ -577,6 +477,20 @@ pygettimeofday_new(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
     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
 _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
 _PyTime_Init(void)
 {
-    _PyTime_timeval tv;
     _PyTime_t t;
 
-    /* ensure that the system clock works */
-    if (pygettimeofday(&tv, NULL, 1) < 0)
-        return -1;
-
     /* ensure that the system clock works */
     if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0)
         return -1;