blob: 31c8f66d11ce6d808d91bf194684690717e2b3d6 [file] [log] [blame]
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +00001#include "Python.h"
Victor Stinner09225b72012-02-07 23:41:01 +01002#ifdef MS_WINDOWS
3#include <windows.h>
4#endif
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +00005
Victor Stinner00111242014-08-29 16:31:59 +02006static int
7pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +00008{
Victor Stinner09225b72012-02-07 23:41:01 +01009#ifdef MS_WINDOWS
10 FILETIME system_time;
11 ULARGE_INTEGER large;
Victor Stinner4195b5c2012-02-08 23:03:19 +010012 ULONGLONG microseconds;
Victor Stinner09225b72012-02-07 23:41:01 +010013
Victor Stinner00111242014-08-29 16:31:59 +020014 assert(info == NULL || raise);
15
Victor Stinner09225b72012-02-07 23:41:01 +010016 GetSystemTimeAsFileTime(&system_time);
17 large.u.LowPart = system_time.dwLowDateTime;
18 large.u.HighPart = system_time.dwHighDateTime;
Victor Stinner4195b5c2012-02-08 23:03:19 +010019 /* 11,644,473,600,000,000: number of microseconds between
Victor Stinner09225b72012-02-07 23:41:01 +010020 the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
21 days). */
Victor Stinner4195b5c2012-02-08 23:03:19 +010022 microseconds = large.QuadPart / 10 - 11644473600000000;
23 tp->tv_sec = microseconds / 1000000;
24 tp->tv_usec = microseconds % 1000000;
Victor Stinnerec895392012-04-29 02:41:27 +020025 if (info) {
26 DWORD timeAdjustment, timeIncrement;
Victor Stinner00111242014-08-29 16:31:59 +020027 BOOL isTimeAdjustmentDisabled, ok;
Victor Stinnerec895392012-04-29 02:41:27 +020028
29 info->implementation = "GetSystemTimeAsFileTime()";
Benjamin Peterson49a69e42012-05-01 09:38:34 -040030 info->monotonic = 0;
Victor Stinner00111242014-08-29 16:31:59 +020031 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
32 &isTimeAdjustmentDisabled);
33 if (!ok) {
34 PyErr_SetFromWindowsErr(0);
35 return -1;
36 }
Victor Stinnerec895392012-04-29 02:41:27 +020037 info->resolution = timeIncrement * 1e-7;
Victor Stinner2b89fdf2012-06-12 22:46:37 +020038 info->adjustable = 1;
Victor Stinnerec895392012-04-29 02:41:27 +020039 }
Victor Stinner00111242014-08-29 16:31:59 +020040 return 0;
Victor Stinner09225b72012-02-07 23:41:01 +010041
Victor Stinner00111242014-08-29 16:31:59 +020042#else /* MS_WINDOWS */
Victor Stinnerec895392012-04-29 02:41:27 +020043 int err;
Victor Stinner7efb8332014-08-29 15:41:08 +020044#ifdef HAVE_CLOCK_GETTIME
45 struct timespec ts;
46#endif
Victor Stinner7efb8332014-08-29 15:41:08 +020047
Victor Stinner00111242014-08-29 16:31:59 +020048 assert(info == NULL || raise);
49
Victor Stinner7efb8332014-08-29 15:41:08 +020050#ifdef HAVE_CLOCK_GETTIME
Victor Stinner00111242014-08-29 16:31:59 +020051 err = clock_gettime(CLOCK_REALTIME, &ts);
52 if (err) {
53 if (raise)
54 PyErr_SetFromErrno(PyExc_OSError);
55 return -1;
Victor Stinner7efb8332014-08-29 15:41:08 +020056 }
Victor Stinner00111242014-08-29 16:31:59 +020057 tp->tv_sec = ts.tv_sec;
58 tp->tv_usec = ts.tv_nsec / 1000;
59
60 if (info) {
61 struct timespec res;
62 info->implementation = "clock_gettime(CLOCK_REALTIME)";
63 info->monotonic = 0;
64 info->adjustable = 1;
65 if (clock_getres(CLOCK_REALTIME, &res) == 0)
66 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
67 else
68 info->resolution = 1e-9;
69 }
70 return 0;
71#else /* HAVE_CLOCK_GETTIME */
Victor Stinner7efb8332014-08-29 15:41:08 +020072
73 /* test gettimeofday() */
74#ifdef HAVE_GETTIMEOFDAY
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000075#ifdef GETTIMEOFDAY_NO_TZ
Victor Stinnerec895392012-04-29 02:41:27 +020076 err = gettimeofday(tp);
77#else
78 err = gettimeofday(tp, (struct timezone *)NULL);
79#endif
Victor Stinner00111242014-08-29 16:31:59 +020080 if (err) {
81 if (raise)
82 PyErr_SetFromErrno(PyExc_OSError);
83 return -1;
Victor Stinnerec895392012-04-29 02:41:27 +020084 }
Victor Stinner00111242014-08-29 16:31:59 +020085
86 if (info) {
87 info->implementation = "gettimeofday()";
88 info->resolution = 1e-6;
89 info->monotonic = 0;
90 info->adjustable = 1;
91 }
92 return 0;
Victor Stinnerec895392012-04-29 02:41:27 +020093#endif /* HAVE_GETTIMEOFDAY */
Victor Stinner00111242014-08-29 16:31:59 +020094#endif /* !HAVE_CLOCK_GETTIME */
95#endif /* !MS_WINDOWS */
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000096}
97
Victor Stinnerec895392012-04-29 02:41:27 +020098void
99_PyTime_gettimeofday(_PyTime_timeval *tp)
100{
Victor Stinner00111242014-08-29 16:31:59 +0200101 if (pygettimeofday(tp, NULL, 0) < 0) {
102 /* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
103 assert(0);
104 tp->tv_sec = 0;
105 tp->tv_usec = 0;
106 }
Victor Stinnerec895392012-04-29 02:41:27 +0200107}
108
Victor Stinner00111242014-08-29 16:31:59 +0200109int
Victor Stinnerec895392012-04-29 02:41:27 +0200110_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
111{
Victor Stinner00111242014-08-29 16:31:59 +0200112 return pygettimeofday(tp, info, 1);
Victor Stinnerec895392012-04-29 02:41:27 +0200113}
114
Victor Stinner5d272cc2012-03-13 13:35:55 +0100115static void
116error_time_t_overflow(void)
Victor Stinner643cd682012-03-02 22:54:03 +0100117{
Victor Stinner5d272cc2012-03-13 13:35:55 +0100118 PyErr_SetString(PyExc_OverflowError,
119 "timestamp out of range for platform time_t");
120}
121
Larry Hastings76ad59b2012-05-03 00:30:07 -0700122time_t
Victor Stinner5d272cc2012-03-13 13:35:55 +0100123_PyLong_AsTime_t(PyObject *obj)
124{
125#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
126 PY_LONG_LONG val;
127 val = PyLong_AsLongLong(obj);
128#else
129 long val;
130 assert(sizeof(time_t) <= sizeof(long));
131 val = PyLong_AsLong(obj);
132#endif
133 if (val == -1 && PyErr_Occurred()) {
134 if (PyErr_ExceptionMatches(PyExc_OverflowError))
135 error_time_t_overflow();
136 return -1;
137 }
138 return (time_t)val;
139}
140
Larry Hastings6fe20b32012-04-19 15:07:49 -0700141PyObject *
142_PyLong_FromTime_t(time_t t)
143{
144#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
145 return PyLong_FromLongLong((PY_LONG_LONG)t);
146#else
147 assert(sizeof(time_t) <= sizeof(long));
148 return PyLong_FromLong((long)t);
149#endif
150}
151
Victor Stinner5d272cc2012-03-13 13:35:55 +0100152static int
153_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
Victor Stinner3c1b3792014-02-17 00:02:43 +0100154 double denominator, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100155{
156 assert(denominator <= LONG_MAX);
Victor Stinner643cd682012-03-02 22:54:03 +0100157 if (PyFloat_Check(obj)) {
Victor Stinnerbd273c12012-03-13 19:12:23 +0100158 double d, intpart, err;
159 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
160 volatile double floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100161
162 d = PyFloat_AsDouble(obj);
163 floatpart = modf(d, &intpart);
164 if (floatpart < 0) {
165 floatpart = 1.0 + floatpart;
166 intpart -= 1.0;
167 }
168
Victor Stinner3c1b3792014-02-17 00:02:43 +0100169 floatpart *= denominator;
170 if (round == _PyTime_ROUND_UP) {
171 if (intpart >= 0) {
172 floatpart = ceil(floatpart);
173 if (floatpart >= denominator) {
174 floatpart = 0.0;
175 intpart += 1.0;
176 }
177 }
178 else {
179 floatpart = floor(floatpart);
180 }
181 }
182
Victor Stinner643cd682012-03-02 22:54:03 +0100183 *sec = (time_t)intpart;
184 err = intpart - (double)*sec;
Victor Stinner5d272cc2012-03-13 13:35:55 +0100185 if (err <= -1.0 || err >= 1.0) {
186 error_time_t_overflow();
187 return -1;
188 }
Victor Stinner643cd682012-03-02 22:54:03 +0100189
Victor Stinner5d272cc2012-03-13 13:35:55 +0100190 *numerator = (long)floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100191 return 0;
192 }
193 else {
Victor Stinner5d272cc2012-03-13 13:35:55 +0100194 *sec = _PyLong_AsTime_t(obj);
195 if (*sec == (time_t)-1 && PyErr_Occurred())
196 return -1;
197 *numerator = 0;
Victor Stinner643cd682012-03-02 22:54:03 +0100198 return 0;
199 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100200}
Victor Stinner643cd682012-03-02 22:54:03 +0100201
Victor Stinner5d272cc2012-03-13 13:35:55 +0100202int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100203_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100204{
205 if (PyFloat_Check(obj)) {
206 double d, intpart, err;
207
Victor Stinner5d272cc2012-03-13 13:35:55 +0100208 d = PyFloat_AsDouble(obj);
Victor Stinner3c1b3792014-02-17 00:02:43 +0100209 if (round == _PyTime_ROUND_UP) {
210 if (d >= 0)
211 d = ceil(d);
212 else
213 d = floor(d);
214 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100215 (void)modf(d, &intpart);
216
217 *sec = (time_t)intpart;
218 err = intpart - (double)*sec;
219 if (err <= -1.0 || err >= 1.0) {
220 error_time_t_overflow();
221 return -1;
222 }
223 return 0;
224 }
225 else {
226 *sec = _PyLong_AsTime_t(obj);
227 if (*sec == (time_t)-1 && PyErr_Occurred())
228 return -1;
229 return 0;
230 }
231}
232
233int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100234_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
235 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100236{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100237 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
Victor Stinner5d272cc2012-03-13 13:35:55 +0100238}
239
240int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100241_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
242 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100243{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100244 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
Victor Stinner643cd682012-03-02 22:54:03 +0100245}
246
Victor Stinner00111242014-08-29 16:31:59 +0200247int
248_PyTime_Init(void)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000249{
Victor Stinner00111242014-08-29 16:31:59 +0200250 _PyTime_timeval tv;
251 /* ensure that the system clock works */
252 if (_PyTime_gettimeofday_info(&tv, NULL) < 0)
253 return -1;
254 return 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000255}