blob: db3f6830648a9626b83b2a98219466fb9f60562a [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
21void
Victor Stinner4195b5c2012-02-08 23:03:19 +010022_PyTime_gettimeofday(_PyTime_timeval *tp)
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 Stinner09225b72012-02-07 23:41:01 +010038#else
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000039 /* There are three ways to get the time:
40 (1) gettimeofday() -- resolution in microseconds
41 (2) ftime() -- resolution in milliseconds
42 (3) time() -- resolution in seconds
43 In all cases the return value in a timeval struct.
44 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
45 fail, so we fall back on ftime() or time().
46 Note: clock resolution does not imply clock accuracy! */
Victor Stinner09225b72012-02-07 23:41:01 +010047
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000048#ifdef HAVE_GETTIMEOFDAY
49#ifdef GETTIMEOFDAY_NO_TZ
Victor Stinner4195b5c2012-02-08 23:03:19 +010050 if (gettimeofday(tp) == 0)
Victor Stinnerccd57152012-02-08 14:31:50 +010051 return;
Victor Stinner4195b5c2012-02-08 23:03:19 +010052#else /* !GETTIMEOFDAY_NO_TZ */
53 if (gettimeofday(tp, (struct timezone *)NULL) == 0)
54 return;
55#endif /* !GETTIMEOFDAY_NO_TZ */
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000056#endif /* !HAVE_GETTIMEOFDAY */
Victor Stinner09225b72012-02-07 23:41:01 +010057
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000058#if defined(HAVE_FTIME)
Victor Stinner4195b5c2012-02-08 23:03:19 +010059 {
60 struct timeb t;
61 ftime(&t);
62 tp->tv_sec = t.time;
63 tp->tv_usec = t.millitm * 1000;
64 }
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000065#else /* !HAVE_FTIME */
Victor Stinner4195b5c2012-02-08 23:03:19 +010066 tp->tv_sec = time(NULL);
67 tp->tv_usec = 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000068#endif /* !HAVE_FTIME */
Victor Stinner09225b72012-02-07 23:41:01 +010069
70#endif /* MS_WINDOWS */
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000071}
72
Victor Stinner5d272cc2012-03-13 13:35:55 +010073static void
74error_time_t_overflow(void)
Victor Stinner643cd682012-03-02 22:54:03 +010075{
Victor Stinner5d272cc2012-03-13 13:35:55 +010076 PyErr_SetString(PyExc_OverflowError,
77 "timestamp out of range for platform time_t");
78}
79
80static time_t
81_PyLong_AsTime_t(PyObject *obj)
82{
83#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
84 PY_LONG_LONG val;
85 val = PyLong_AsLongLong(obj);
86#else
87 long val;
88 assert(sizeof(time_t) <= sizeof(long));
89 val = PyLong_AsLong(obj);
90#endif
91 if (val == -1 && PyErr_Occurred()) {
92 if (PyErr_ExceptionMatches(PyExc_OverflowError))
93 error_time_t_overflow();
94 return -1;
95 }
96 return (time_t)val;
97}
98
Larry Hastings6fe20b32012-04-19 15:07:49 -070099PyObject *
100_PyLong_FromTime_t(time_t t)
101{
102#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
103 return PyLong_FromLongLong((PY_LONG_LONG)t);
104#else
105 assert(sizeof(time_t) <= sizeof(long));
106 return PyLong_FromLong((long)t);
107#endif
108}
109
Victor Stinner5d272cc2012-03-13 13:35:55 +0100110static int
111_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
112 double denominator)
113{
114 assert(denominator <= LONG_MAX);
Victor Stinner643cd682012-03-02 22:54:03 +0100115 if (PyFloat_Check(obj)) {
Victor Stinnerbd273c12012-03-13 19:12:23 +0100116 double d, intpart, err;
117 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
118 volatile double floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100119
120 d = PyFloat_AsDouble(obj);
121 floatpart = modf(d, &intpart);
122 if (floatpart < 0) {
123 floatpart = 1.0 + floatpart;
124 intpart -= 1.0;
125 }
126
127 *sec = (time_t)intpart;
128 err = intpart - (double)*sec;
Victor Stinner5d272cc2012-03-13 13:35:55 +0100129 if (err <= -1.0 || err >= 1.0) {
130 error_time_t_overflow();
131 return -1;
132 }
Victor Stinner643cd682012-03-02 22:54:03 +0100133
Victor Stinner5d272cc2012-03-13 13:35:55 +0100134 floatpart *= denominator;
135 *numerator = (long)floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100136 return 0;
137 }
138 else {
Victor Stinner5d272cc2012-03-13 13:35:55 +0100139 *sec = _PyLong_AsTime_t(obj);
140 if (*sec == (time_t)-1 && PyErr_Occurred())
141 return -1;
142 *numerator = 0;
Victor Stinner643cd682012-03-02 22:54:03 +0100143 return 0;
144 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100145}
Victor Stinner643cd682012-03-02 22:54:03 +0100146
Victor Stinner5d272cc2012-03-13 13:35:55 +0100147int
148_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec)
149{
150 if (PyFloat_Check(obj)) {
151 double d, intpart, err;
152
Victor Stinner5d272cc2012-03-13 13:35:55 +0100153 d = PyFloat_AsDouble(obj);
154 (void)modf(d, &intpart);
155
156 *sec = (time_t)intpart;
157 err = intpart - (double)*sec;
158 if (err <= -1.0 || err >= 1.0) {
159 error_time_t_overflow();
160 return -1;
161 }
162 return 0;
163 }
164 else {
165 *sec = _PyLong_AsTime_t(obj);
166 if (*sec == (time_t)-1 && PyErr_Occurred())
167 return -1;
168 return 0;
169 }
170}
171
172int
173_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
174{
175 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9);
176}
177
178int
179_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec)
180{
181 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6);
Victor Stinner643cd682012-03-02 22:54:03 +0100182}
183
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000184void
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000185_PyTime_Init()
186{
187 /* Do nothing. Needed to force linking. */
188}