blob: 395a432da53b1989a13c92d6f71502279bb9dbca [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 Stinner09225b72012-02-07 23:41:01 +010040
Victor Stinner00111242014-08-29 16:31:59 +020041#else /* MS_WINDOWS */
Victor Stinnerec895392012-04-29 02:41:27 +020042 int err;
Victor Stinner7efb8332014-08-29 15:41:08 +020043#ifdef HAVE_CLOCK_GETTIME
44 struct timespec ts;
45#endif
Victor Stinner7efb8332014-08-29 15:41:08 +020046
Victor Stinner00111242014-08-29 16:31:59 +020047 assert(info == NULL || raise);
48
Victor Stinner7efb8332014-08-29 15:41:08 +020049#ifdef HAVE_CLOCK_GETTIME
Victor Stinner00111242014-08-29 16:31:59 +020050 err = clock_gettime(CLOCK_REALTIME, &ts);
51 if (err) {
52 if (raise)
53 PyErr_SetFromErrno(PyExc_OSError);
54 return -1;
Victor Stinner7efb8332014-08-29 15:41:08 +020055 }
Victor Stinner00111242014-08-29 16:31:59 +020056 tp->tv_sec = ts.tv_sec;
57 tp->tv_usec = ts.tv_nsec / 1000;
58
59 if (info) {
60 struct timespec res;
61 info->implementation = "clock_gettime(CLOCK_REALTIME)";
62 info->monotonic = 0;
63 info->adjustable = 1;
64 if (clock_getres(CLOCK_REALTIME, &res) == 0)
65 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
66 else
67 info->resolution = 1e-9;
68 }
Victor Stinner00111242014-08-29 16:31:59 +020069#else /* HAVE_CLOCK_GETTIME */
Victor Stinner7efb8332014-08-29 15:41:08 +020070
71 /* test gettimeofday() */
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000072#ifdef GETTIMEOFDAY_NO_TZ
Victor Stinnerec895392012-04-29 02:41:27 +020073 err = gettimeofday(tp);
74#else
75 err = gettimeofday(tp, (struct timezone *)NULL);
76#endif
Victor Stinner00111242014-08-29 16:31:59 +020077 if (err) {
78 if (raise)
79 PyErr_SetFromErrno(PyExc_OSError);
80 return -1;
Victor Stinnerec895392012-04-29 02:41:27 +020081 }
Victor Stinner00111242014-08-29 16:31:59 +020082
83 if (info) {
84 info->implementation = "gettimeofday()";
85 info->resolution = 1e-6;
86 info->monotonic = 0;
87 info->adjustable = 1;
88 }
Victor Stinner00111242014-08-29 16:31:59 +020089#endif /* !HAVE_CLOCK_GETTIME */
90#endif /* !MS_WINDOWS */
Victor Stinner9bb758c2014-09-02 23:01:40 +020091 assert(0 <= tp->tv_usec && tp->tv_usec < 1000 * 1000);
92 return 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000093}
94
Victor Stinnerec895392012-04-29 02:41:27 +020095void
96_PyTime_gettimeofday(_PyTime_timeval *tp)
97{
Victor Stinner00111242014-08-29 16:31:59 +020098 if (pygettimeofday(tp, NULL, 0) < 0) {
99 /* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
100 assert(0);
101 tp->tv_sec = 0;
102 tp->tv_usec = 0;
103 }
Victor Stinnerec895392012-04-29 02:41:27 +0200104}
105
Victor Stinner00111242014-08-29 16:31:59 +0200106int
Victor Stinnerec895392012-04-29 02:41:27 +0200107_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
108{
Victor Stinner00111242014-08-29 16:31:59 +0200109 return pygettimeofday(tp, info, 1);
Victor Stinnerec895392012-04-29 02:41:27 +0200110}
111
Victor Stinner5d272cc2012-03-13 13:35:55 +0100112static void
113error_time_t_overflow(void)
Victor Stinner643cd682012-03-02 22:54:03 +0100114{
Victor Stinner5d272cc2012-03-13 13:35:55 +0100115 PyErr_SetString(PyExc_OverflowError,
116 "timestamp out of range for platform time_t");
117}
118
Larry Hastings76ad59b2012-05-03 00:30:07 -0700119time_t
Victor Stinner5d272cc2012-03-13 13:35:55 +0100120_PyLong_AsTime_t(PyObject *obj)
121{
122#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
123 PY_LONG_LONG val;
124 val = PyLong_AsLongLong(obj);
125#else
126 long val;
127 assert(sizeof(time_t) <= sizeof(long));
128 val = PyLong_AsLong(obj);
129#endif
130 if (val == -1 && PyErr_Occurred()) {
131 if (PyErr_ExceptionMatches(PyExc_OverflowError))
132 error_time_t_overflow();
133 return -1;
134 }
135 return (time_t)val;
136}
137
Larry Hastings6fe20b32012-04-19 15:07:49 -0700138PyObject *
139_PyLong_FromTime_t(time_t t)
140{
141#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
142 return PyLong_FromLongLong((PY_LONG_LONG)t);
143#else
144 assert(sizeof(time_t) <= sizeof(long));
145 return PyLong_FromLong((long)t);
146#endif
147}
148
Victor Stinner5d272cc2012-03-13 13:35:55 +0100149static int
150_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
Victor Stinner3c1b3792014-02-17 00:02:43 +0100151 double denominator, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100152{
153 assert(denominator <= LONG_MAX);
Victor Stinner643cd682012-03-02 22:54:03 +0100154 if (PyFloat_Check(obj)) {
Victor Stinnerbd273c12012-03-13 19:12:23 +0100155 double d, intpart, err;
156 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
157 volatile double floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100158
159 d = PyFloat_AsDouble(obj);
160 floatpart = modf(d, &intpart);
161 if (floatpart < 0) {
162 floatpart = 1.0 + floatpart;
163 intpart -= 1.0;
164 }
165
Victor Stinner3c1b3792014-02-17 00:02:43 +0100166 floatpart *= denominator;
167 if (round == _PyTime_ROUND_UP) {
168 if (intpart >= 0) {
169 floatpart = ceil(floatpart);
170 if (floatpart >= denominator) {
171 floatpart = 0.0;
172 intpart += 1.0;
173 }
174 }
175 else {
176 floatpart = floor(floatpart);
177 }
178 }
179
Victor Stinner643cd682012-03-02 22:54:03 +0100180 *sec = (time_t)intpart;
181 err = intpart - (double)*sec;
Victor Stinner5d272cc2012-03-13 13:35:55 +0100182 if (err <= -1.0 || err >= 1.0) {
183 error_time_t_overflow();
184 return -1;
185 }
Victor Stinner643cd682012-03-02 22:54:03 +0100186
Victor Stinner5d272cc2012-03-13 13:35:55 +0100187 *numerator = (long)floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100188 return 0;
189 }
190 else {
Victor Stinner5d272cc2012-03-13 13:35:55 +0100191 *sec = _PyLong_AsTime_t(obj);
192 if (*sec == (time_t)-1 && PyErr_Occurred())
193 return -1;
194 *numerator = 0;
Victor Stinner643cd682012-03-02 22:54:03 +0100195 return 0;
196 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100197}
Victor Stinner643cd682012-03-02 22:54:03 +0100198
Victor Stinner5d272cc2012-03-13 13:35:55 +0100199int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100200_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100201{
202 if (PyFloat_Check(obj)) {
203 double d, intpart, err;
204
Victor Stinner5d272cc2012-03-13 13:35:55 +0100205 d = PyFloat_AsDouble(obj);
Victor Stinner3c1b3792014-02-17 00:02:43 +0100206 if (round == _PyTime_ROUND_UP) {
207 if (d >= 0)
208 d = ceil(d);
209 else
210 d = floor(d);
211 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100212 (void)modf(d, &intpart);
213
214 *sec = (time_t)intpart;
215 err = intpart - (double)*sec;
216 if (err <= -1.0 || err >= 1.0) {
217 error_time_t_overflow();
218 return -1;
219 }
220 return 0;
221 }
222 else {
223 *sec = _PyLong_AsTime_t(obj);
224 if (*sec == (time_t)-1 && PyErr_Occurred())
225 return -1;
226 return 0;
227 }
228}
229
230int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100231_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
232 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100233{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100234 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
Victor Stinner5d272cc2012-03-13 13:35:55 +0100235}
236
237int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100238_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
239 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100240{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100241 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
Victor Stinner643cd682012-03-02 22:54:03 +0100242}
243
Victor Stinner00111242014-08-29 16:31:59 +0200244int
245_PyTime_Init(void)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000246{
Victor Stinner00111242014-08-29 16:31:59 +0200247 _PyTime_timeval tv;
248 /* ensure that the system clock works */
249 if (_PyTime_gettimeofday_info(&tv, NULL) < 0)
250 return -1;
251 return 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000252}