blob: 0ffe799b32a22cf2e9f44ac20f24b0a3174ada15 [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;
47 if (isTimeAdjustmentDisabled)
Benjamin Peterson49a69e42012-05-01 09:38:34 -040048 info->adjusted = 0;
Victor Stinnerec895392012-04-29 02:41:27 +020049 else
Benjamin Peterson49a69e42012-05-01 09:38:34 -040050 info->adjusted = 1;
Victor Stinnerec895392012-04-29 02:41:27 +020051 }
Victor Stinner09225b72012-02-07 23:41:01 +010052#else
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000053 /* There are three ways to get the time:
54 (1) gettimeofday() -- resolution in microseconds
55 (2) ftime() -- resolution in milliseconds
56 (3) time() -- resolution in seconds
57 In all cases the return value in a timeval struct.
58 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
59 fail, so we fall back on ftime() or time().
60 Note: clock resolution does not imply clock accuracy! */
Victor Stinner09225b72012-02-07 23:41:01 +010061
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000062#ifdef HAVE_GETTIMEOFDAY
Victor Stinnerec895392012-04-29 02:41:27 +020063 int err;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000064#ifdef GETTIMEOFDAY_NO_TZ
Victor Stinnerec895392012-04-29 02:41:27 +020065 err = gettimeofday(tp);
66#else
67 err = gettimeofday(tp, (struct timezone *)NULL);
68#endif
69 if (err == 0) {
70 if (info) {
71 info->implementation = "gettimeofday()";
72 info->resolution = 1e-6;
Benjamin Peterson49a69e42012-05-01 09:38:34 -040073 info->monotonic = 0;
74 info->adjusted = 1;
Victor Stinnerec895392012-04-29 02:41:27 +020075 }
Victor Stinnerccd57152012-02-08 14:31:50 +010076 return;
Victor Stinnerec895392012-04-29 02:41:27 +020077 }
78#endif /* HAVE_GETTIMEOFDAY */
Victor Stinner09225b72012-02-07 23:41:01 +010079
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000080#if defined(HAVE_FTIME)
Victor Stinner4195b5c2012-02-08 23:03:19 +010081 {
82 struct timeb t;
83 ftime(&t);
84 tp->tv_sec = t.time;
85 tp->tv_usec = t.millitm * 1000;
Victor Stinnerec895392012-04-29 02:41:27 +020086 if (info) {
87 info->implementation = "ftime()";
88 info->resolution = 1e-3;
Benjamin Peterson49a69e42012-05-01 09:38:34 -040089 info->monotonic = 0;
90 info->adjusted = 1;
Victor Stinnerec895392012-04-29 02:41:27 +020091 }
Victor Stinner4195b5c2012-02-08 23:03:19 +010092 }
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000093#else /* !HAVE_FTIME */
Victor Stinner4195b5c2012-02-08 23:03:19 +010094 tp->tv_sec = time(NULL);
95 tp->tv_usec = 0;
Victor Stinnerec895392012-04-29 02:41:27 +020096 if (info) {
97 info->implementation = "time()";
98 info->resolution = 1.0;
Benjamin Peterson49a69e42012-05-01 09:38:34 -040099 info->monotonic = 0;
100 info->adjusted = 1;
Victor Stinnerec895392012-04-29 02:41:27 +0200101 }
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000102#endif /* !HAVE_FTIME */
Victor Stinner09225b72012-02-07 23:41:01 +0100103
104#endif /* MS_WINDOWS */
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000105}
106
Victor Stinnerec895392012-04-29 02:41:27 +0200107void
108_PyTime_gettimeofday(_PyTime_timeval *tp)
109{
110 pygettimeofday(tp, NULL);
111}
112
113void
114_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
115{
116 pygettimeofday(tp, info);
117}
118
Victor Stinner5d272cc2012-03-13 13:35:55 +0100119static void
120error_time_t_overflow(void)
Victor Stinner643cd682012-03-02 22:54:03 +0100121{
Victor Stinner5d272cc2012-03-13 13:35:55 +0100122 PyErr_SetString(PyExc_OverflowError,
123 "timestamp out of range for platform time_t");
124}
125
126static time_t
127_PyLong_AsTime_t(PyObject *obj)
128{
129#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
130 PY_LONG_LONG val;
131 val = PyLong_AsLongLong(obj);
132#else
133 long val;
134 assert(sizeof(time_t) <= sizeof(long));
135 val = PyLong_AsLong(obj);
136#endif
137 if (val == -1 && PyErr_Occurred()) {
138 if (PyErr_ExceptionMatches(PyExc_OverflowError))
139 error_time_t_overflow();
140 return -1;
141 }
142 return (time_t)val;
143}
144
Larry Hastings6fe20b32012-04-19 15:07:49 -0700145PyObject *
146_PyLong_FromTime_t(time_t t)
147{
148#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
149 return PyLong_FromLongLong((PY_LONG_LONG)t);
150#else
151 assert(sizeof(time_t) <= sizeof(long));
152 return PyLong_FromLong((long)t);
153#endif
154}
155
Victor Stinner5d272cc2012-03-13 13:35:55 +0100156static int
157_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
158 double denominator)
159{
160 assert(denominator <= LONG_MAX);
Victor Stinner643cd682012-03-02 22:54:03 +0100161 if (PyFloat_Check(obj)) {
Victor Stinnerbd273c12012-03-13 19:12:23 +0100162 double d, intpart, err;
163 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
164 volatile double floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100165
166 d = PyFloat_AsDouble(obj);
167 floatpart = modf(d, &intpart);
168 if (floatpart < 0) {
169 floatpart = 1.0 + floatpart;
170 intpart -= 1.0;
171 }
172
173 *sec = (time_t)intpart;
174 err = intpart - (double)*sec;
Victor Stinner5d272cc2012-03-13 13:35:55 +0100175 if (err <= -1.0 || err >= 1.0) {
176 error_time_t_overflow();
177 return -1;
178 }
Victor Stinner643cd682012-03-02 22:54:03 +0100179
Victor Stinner5d272cc2012-03-13 13:35:55 +0100180 floatpart *= denominator;
181 *numerator = (long)floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100182 return 0;
183 }
184 else {
Victor Stinner5d272cc2012-03-13 13:35:55 +0100185 *sec = _PyLong_AsTime_t(obj);
186 if (*sec == (time_t)-1 && PyErr_Occurred())
187 return -1;
188 *numerator = 0;
Victor Stinner643cd682012-03-02 22:54:03 +0100189 return 0;
190 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100191}
Victor Stinner643cd682012-03-02 22:54:03 +0100192
Victor Stinner5d272cc2012-03-13 13:35:55 +0100193int
194_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec)
195{
196 if (PyFloat_Check(obj)) {
197 double d, intpart, err;
198
Victor Stinner5d272cc2012-03-13 13:35:55 +0100199 d = PyFloat_AsDouble(obj);
200 (void)modf(d, &intpart);
201
202 *sec = (time_t)intpart;
203 err = intpart - (double)*sec;
204 if (err <= -1.0 || err >= 1.0) {
205 error_time_t_overflow();
206 return -1;
207 }
208 return 0;
209 }
210 else {
211 *sec = _PyLong_AsTime_t(obj);
212 if (*sec == (time_t)-1 && PyErr_Occurred())
213 return -1;
214 return 0;
215 }
216}
217
218int
219_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
220{
221 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9);
222}
223
224int
225_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec)
226{
227 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6);
Victor Stinner643cd682012-03-02 22:54:03 +0100228}
229
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000230void
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000231_PyTime_Init()
232{
233 /* Do nothing. Needed to force linking. */
234}