diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-09-18 11:23:02 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-09-18 11:23:02 (GMT) |
commit | 1e2b6882fc28a3cded227f55e4dc3f937afd678e (patch) | |
tree | 761eed5c9da66d8748b6382cd49589850cdf1e49 /Python/pytime.c | |
parent | 1bd0b54c74ea7a108e4a7d921bf9ff904c6fa4d7 (diff) | |
download | cpython-1e2b6882fc28a3cded227f55e4dc3f937afd678e.zip cpython-1e2b6882fc28a3cded227f55e4dc3f937afd678e.tar.gz cpython-1e2b6882fc28a3cded227f55e4dc3f937afd678e.tar.bz2 |
Issue #25155: Add _PyTime_AsTimevalTime_t() function
On Windows, the tv_sec field of the timeval structure has the type C long,
whereas it has the type C time_t on all other platforms. A C long has a size of
32 bits (signed inter, 1 bit for the sign, 31 bits for the value) which is not
enough to store an Epoch timestamp after the year 2038.
Add the _PyTime_AsTimevalTime_t() function written for datetime.datetime.now():
convert a _PyTime_t timestamp to a (secs, us) tuple where secs type is time_t.
It allows to support dates after the year 2038 on Windows.
Enhance also _PyTime_AsTimeval_impl() to detect overflow on the number of
seconds when rounding the number of microseconds.
Diffstat (limited to 'Python/pytime.c')
-rw-r--r-- | Python/pytime.c | 79 |
1 files changed, 60 insertions, 19 deletions
diff --git a/Python/pytime.c b/Python/pytime.c index 9d0b0fa..9889a3b 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -417,54 +417,95 @@ _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round) } static int -_PyTime_AsTimeval_impl(_PyTime_t t, struct timeval *tv, _PyTime_round_t round, - int raise) +_PyTime_AsTimeval_impl(_PyTime_t t, _PyTime_t *p_secs, int *p_us, + _PyTime_round_t round) { _PyTime_t secs, ns; - int res = 0; int usec; + int res = 0; secs = t / SEC_TO_NS; ns = t % SEC_TO_NS; -#ifdef MS_WINDOWS - tv->tv_sec = (long)secs; -#else - tv->tv_sec = secs; -#endif - if ((_PyTime_t)tv->tv_sec != secs) - res = -1; - usec = (int)_PyTime_Divide(ns, US_TO_NS, round); if (usec < 0) { usec += SEC_TO_US; - tv->tv_sec -= 1; + if (secs != _PyTime_MIN) + secs -= 1; + else + res = -1; } else if (usec >= SEC_TO_US) { usec -= SEC_TO_US; - tv->tv_sec += 1; + if (secs != _PyTime_MAX) + secs += 1; + else + res = -1; } - assert(0 <= usec && usec < SEC_TO_US); - tv->tv_usec = usec; - if (res && raise) - error_time_t_overflow(); + *p_secs = secs; + *p_us = usec; + return res; } +static int +_PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv, + _PyTime_round_t round, int raise) +{ + _PyTime_t secs; + int us; + int res; + + res = _PyTime_AsTimeval_impl(t, &secs, &us, round); + +#ifdef MS_WINDOWS + tv->tv_sec = (long)secs; +#else + tv->tv_sec = secs; +#endif + tv->tv_usec = us; + + if (res < 0 || (_PyTime_t)tv->tv_sec != secs) { + if (raise) + error_time_t_overflow(); + return -1; + } + return 0; +} + int _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) { - return _PyTime_AsTimeval_impl(t, tv, round, 1); + return _PyTime_AsTimevalStruct_impl(t, tv, round, 1); } int _PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) { - return _PyTime_AsTimeval_impl(t, tv, round, 0); + return _PyTime_AsTimevalStruct_impl(t, tv, round, 0); } +int +_PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us, + _PyTime_round_t round) +{ + _PyTime_t secs; + int res; + + res = _PyTime_AsTimeval_impl(t, &secs, us, round); + + *p_secs = secs; + + if (res < 0 || (_PyTime_t)*p_secs != secs) { + error_time_t_overflow(); + return -1; + } + return 0; +} + + #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) int _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts) |