blob: 1f3fafb228a10a28e41c99f8b041af508dd30876 [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 Stinner09225b72012-02-07 23:41:01 +01006#if defined(__APPLE__) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +00007 /*
8 * _PyTime_gettimeofday falls back to ftime when getttimeofday fails because the latter
9 * might fail on some platforms. This fallback is unwanted on MacOSX because
10 * that makes it impossible to use a binary build on OSX 10.4 on earlier
11 * releases of the OS. Therefore claim we don't support ftime.
12 */
13# undef HAVE_FTIME
14#endif
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000015
Victor Stinner09225b72012-02-07 23:41:01 +010016#if defined(HAVE_FTIME) && !defined(MS_WINDOWS)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000017#include <sys/timeb.h>
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000018extern int ftime(struct timeb *);
Victor Stinner09225b72012-02-07 23:41:01 +010019#endif
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000020
Victor Stinnerec895392012-04-29 02:41:27 +020021static void
22pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000023{
Victor Stinner09225b72012-02-07 23:41:01 +010024#ifdef MS_WINDOWS
25 FILETIME system_time;
26 ULARGE_INTEGER large;
Victor Stinner4195b5c2012-02-08 23:03:19 +010027 ULONGLONG microseconds;
Victor Stinner09225b72012-02-07 23:41:01 +010028
29 GetSystemTimeAsFileTime(&system_time);
30 large.u.LowPart = system_time.dwLowDateTime;
31 large.u.HighPart = system_time.dwHighDateTime;
Victor Stinner4195b5c2012-02-08 23:03:19 +010032 /* 11,644,473,600,000,000: number of microseconds between
Victor Stinner09225b72012-02-07 23:41:01 +010033 the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
34 days). */
Victor Stinner4195b5c2012-02-08 23:03:19 +010035 microseconds = large.QuadPart / 10 - 11644473600000000;
36 tp->tv_sec = microseconds / 1000000;
37 tp->tv_usec = microseconds % 1000000;
Victor Stinnerec895392012-04-29 02:41:27 +020038 if (info) {
39 DWORD timeAdjustment, timeIncrement;
40 BOOL isTimeAdjustmentDisabled;
41
42 info->implementation = "GetSystemTimeAsFileTime()";
Benjamin Peterson49a69e42012-05-01 09:38:34 -040043 info->monotonic = 0;
Victor Stinnerec895392012-04-29 02:41:27 +020044 (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
45 &isTimeAdjustmentDisabled);
46 info->resolution = timeIncrement * 1e-7;
Victor Stinner2b89fdf2012-06-12 22:46:37 +020047 info->adjustable = 1;
Victor Stinnerec895392012-04-29 02:41:27 +020048 }
Victor Stinner09225b72012-02-07 23:41:01 +010049#else
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000050 /* There are three ways to get the time:
51 (1) gettimeofday() -- resolution in microseconds
52 (2) ftime() -- resolution in milliseconds
53 (3) time() -- resolution in seconds
54 In all cases the return value in a timeval struct.
55 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
56 fail, so we fall back on ftime() or time().
57 Note: clock resolution does not imply clock accuracy! */
Victor Stinner09225b72012-02-07 23:41:01 +010058
Victor Stinner7efb8332014-08-29 15:41:08 +020059#if (defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETTIMEOFDAY) \
60 || defined(HAVE_FTIME))
Victor Stinnerec895392012-04-29 02:41:27 +020061 int err;
Victor Stinner7efb8332014-08-29 15:41:08 +020062#endif
63#ifdef HAVE_CLOCK_GETTIME
64 struct timespec ts;
65#endif
66#ifdef HAVE_FTIME
67 struct timeb t;
68#endif
69
70 /* test clock_gettime(CLOCK_REALTIME) */
71#ifdef HAVE_CLOCK_GETTIME
72 err = clock_gettime(CLOCK_REALTIME, &ts);
73 if (err == 0) {
74 if (info) {
75 struct timespec res;
76 info->implementation = "clock_gettime(CLOCK_REALTIME)";
77 info->monotonic = 0;
78 info->adjustable = 1;
79 if (clock_getres(CLOCK_REALTIME, &res) == 0)
80 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
81 else
82 info->resolution = 1e-9;
83 }
84 tp->tv_sec = ts.tv_sec;
85 tp->tv_usec = ts.tv_nsec / 1000;
86 return;
87 }
88#endif
89
90 /* test gettimeofday() */
91#ifdef HAVE_GETTIMEOFDAY
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000092#ifdef GETTIMEOFDAY_NO_TZ
Victor Stinnerec895392012-04-29 02:41:27 +020093 err = gettimeofday(tp);
94#else
95 err = gettimeofday(tp, (struct timezone *)NULL);
96#endif
97 if (err == 0) {
98 if (info) {
99 info->implementation = "gettimeofday()";
100 info->resolution = 1e-6;
Benjamin Peterson49a69e42012-05-01 09:38:34 -0400101 info->monotonic = 0;
Victor Stinner2b89fdf2012-06-12 22:46:37 +0200102 info->adjustable = 1;
Victor Stinnerec895392012-04-29 02:41:27 +0200103 }
Victor Stinnerccd57152012-02-08 14:31:50 +0100104 return;
Victor Stinnerec895392012-04-29 02:41:27 +0200105 }
106#endif /* HAVE_GETTIMEOFDAY */
Victor Stinner09225b72012-02-07 23:41:01 +0100107
Victor Stinner7efb8332014-08-29 15:41:08 +0200108#ifdef HAVE_FTIME
109 ftime(&t);
110 tp->tv_sec = t.time;
111 tp->tv_usec = t.millitm * 1000;
112 if (info) {
113 info->implementation = "ftime()";
114 info->resolution = 1e-3;
115 info->monotonic = 0;
116 info->adjustable = 1;
Victor Stinner4195b5c2012-02-08 23:03:19 +0100117 }
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000118#else /* !HAVE_FTIME */
Victor Stinner4195b5c2012-02-08 23:03:19 +0100119 tp->tv_sec = time(NULL);
120 tp->tv_usec = 0;
Victor Stinnerec895392012-04-29 02:41:27 +0200121 if (info) {
122 info->implementation = "time()";
123 info->resolution = 1.0;
Benjamin Peterson49a69e42012-05-01 09:38:34 -0400124 info->monotonic = 0;
Victor Stinner2b89fdf2012-06-12 22:46:37 +0200125 info->adjustable = 1;
Victor Stinnerec895392012-04-29 02:41:27 +0200126 }
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000127#endif /* !HAVE_FTIME */
Victor Stinner09225b72012-02-07 23:41:01 +0100128
129#endif /* MS_WINDOWS */
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000130}
131
Victor Stinnerec895392012-04-29 02:41:27 +0200132void
133_PyTime_gettimeofday(_PyTime_timeval *tp)
134{
135 pygettimeofday(tp, NULL);
136}
137
138void
139_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
140{
141 pygettimeofday(tp, info);
142}
143
Victor Stinner5d272cc2012-03-13 13:35:55 +0100144static void
145error_time_t_overflow(void)
Victor Stinner643cd682012-03-02 22:54:03 +0100146{
Victor Stinner5d272cc2012-03-13 13:35:55 +0100147 PyErr_SetString(PyExc_OverflowError,
148 "timestamp out of range for platform time_t");
149}
150
Larry Hastings76ad59b2012-05-03 00:30:07 -0700151time_t
Victor Stinner5d272cc2012-03-13 13:35:55 +0100152_PyLong_AsTime_t(PyObject *obj)
153{
154#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
155 PY_LONG_LONG val;
156 val = PyLong_AsLongLong(obj);
157#else
158 long val;
159 assert(sizeof(time_t) <= sizeof(long));
160 val = PyLong_AsLong(obj);
161#endif
162 if (val == -1 && PyErr_Occurred()) {
163 if (PyErr_ExceptionMatches(PyExc_OverflowError))
164 error_time_t_overflow();
165 return -1;
166 }
167 return (time_t)val;
168}
169
Larry Hastings6fe20b32012-04-19 15:07:49 -0700170PyObject *
171_PyLong_FromTime_t(time_t t)
172{
173#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
174 return PyLong_FromLongLong((PY_LONG_LONG)t);
175#else
176 assert(sizeof(time_t) <= sizeof(long));
177 return PyLong_FromLong((long)t);
178#endif
179}
180
Victor Stinner5d272cc2012-03-13 13:35:55 +0100181static int
182_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
Victor Stinner3c1b3792014-02-17 00:02:43 +0100183 double denominator, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100184{
185 assert(denominator <= LONG_MAX);
Victor Stinner643cd682012-03-02 22:54:03 +0100186 if (PyFloat_Check(obj)) {
Victor Stinnerbd273c12012-03-13 19:12:23 +0100187 double d, intpart, err;
188 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
189 volatile double floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100190
191 d = PyFloat_AsDouble(obj);
192 floatpart = modf(d, &intpart);
193 if (floatpart < 0) {
194 floatpart = 1.0 + floatpart;
195 intpart -= 1.0;
196 }
197
Victor Stinner3c1b3792014-02-17 00:02:43 +0100198 floatpart *= denominator;
199 if (round == _PyTime_ROUND_UP) {
200 if (intpart >= 0) {
201 floatpart = ceil(floatpart);
202 if (floatpart >= denominator) {
203 floatpart = 0.0;
204 intpart += 1.0;
205 }
206 }
207 else {
208 floatpart = floor(floatpart);
209 }
210 }
211
Victor Stinner643cd682012-03-02 22:54:03 +0100212 *sec = (time_t)intpart;
213 err = intpart - (double)*sec;
Victor Stinner5d272cc2012-03-13 13:35:55 +0100214 if (err <= -1.0 || err >= 1.0) {
215 error_time_t_overflow();
216 return -1;
217 }
Victor Stinner643cd682012-03-02 22:54:03 +0100218
Victor Stinner5d272cc2012-03-13 13:35:55 +0100219 *numerator = (long)floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100220 return 0;
221 }
222 else {
Victor Stinner5d272cc2012-03-13 13:35:55 +0100223 *sec = _PyLong_AsTime_t(obj);
224 if (*sec == (time_t)-1 && PyErr_Occurred())
225 return -1;
226 *numerator = 0;
Victor Stinner643cd682012-03-02 22:54:03 +0100227 return 0;
228 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100229}
Victor Stinner643cd682012-03-02 22:54:03 +0100230
Victor Stinner5d272cc2012-03-13 13:35:55 +0100231int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100232_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100233{
234 if (PyFloat_Check(obj)) {
235 double d, intpart, err;
236
Victor Stinner5d272cc2012-03-13 13:35:55 +0100237 d = PyFloat_AsDouble(obj);
Victor Stinner3c1b3792014-02-17 00:02:43 +0100238 if (round == _PyTime_ROUND_UP) {
239 if (d >= 0)
240 d = ceil(d);
241 else
242 d = floor(d);
243 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100244 (void)modf(d, &intpart);
245
246 *sec = (time_t)intpart;
247 err = intpart - (double)*sec;
248 if (err <= -1.0 || err >= 1.0) {
249 error_time_t_overflow();
250 return -1;
251 }
252 return 0;
253 }
254 else {
255 *sec = _PyLong_AsTime_t(obj);
256 if (*sec == (time_t)-1 && PyErr_Occurred())
257 return -1;
258 return 0;
259 }
260}
261
262int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100263_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
264 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100265{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100266 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
Victor Stinner5d272cc2012-03-13 13:35:55 +0100267}
268
269int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100270_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
271 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100272{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100273 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
Victor Stinner643cd682012-03-02 22:54:03 +0100274}
275
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000276void
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000277_PyTime_Init()
278{
279 /* Do nothing. Needed to force linking. */
280}