summaryrefslogtreecommitdiffstats
path: root/Python/pytime.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-09-18 11:23:02 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2015-09-18 11:23:02 (GMT)
commit1e2b6882fc28a3cded227f55e4dc3f937afd678e (patch)
tree761eed5c9da66d8748b6382cd49589850cdf1e49 /Python/pytime.c
parent1bd0b54c74ea7a108e4a7d921bf9ff904c6fa4d7 (diff)
downloadcpython-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.c79
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)