timemodule.c revision 1f41f846a3fc369c4d68eee962a059ca3a51ccf3
1/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5                        All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* Time module */
33
34#include "Python.h"
35
36#ifdef HAVE_SELECT
37#include "mymath.h"
38#endif
39
40#ifdef macintosh
41#include <time.h>
42#else
43#include <sys/types.h>
44#endif
45
46#ifdef QUICKWIN
47#include <io.h>
48#endif
49
50#ifdef HAVE_UNISTD_H
51#include <unistd.h>
52#endif
53
54#ifdef HAVE_SELECT
55#include "myselect.h"
56#else
57#include "mytime.h"
58#endif
59
60#ifdef HAVE_FTIME
61#include <sys/timeb.h>
62#if !defined(MS_WINDOWS) && !defined(PYOS_OS2)
63extern int ftime();
64#endif /* MS_WINDOWS */
65#endif /* HAVE_FTIME */
66
67#if defined(__WATCOMC__) && !defined(__QNX__)
68#include <i86.h>
69#else
70#ifdef MS_WINDOWS
71#include <windows.h>
72#ifdef MS_WIN16
73/* These overrides not needed for Win32 */
74#define timezone _timezone
75#define tzname _tzname
76#define daylight _daylight
77#define altzone _altzone
78#endif /* MS_WIN16 */
79#endif /* MS_WINDOWS */
80#endif /* !__WATCOMC__ || __QNX__ */
81
82#ifdef MS_WIN32
83/* Win32 has better clock replacement */
84#include <largeint.h>
85#undef HAVE_CLOCK /* We have our own version down below */
86#endif /* MS_WIN32 */
87
88#if defined(PYOS_OS2)
89#define  INCL_DOS
90#define  INCL_DOSERRORS
91#define  INCL_NOPMAPI
92#include <os2.h>
93#endif
94
95#if defined(PYCC_VACPP)
96#include <time.h>
97#define timezone _timezone
98#endif
99
100/* Forward declarations */
101static int floatsleep Py_PROTO((double));
102static double floattime Py_PROTO(());
103
104#ifdef macintosh
105/* Our own timezone. We have enough information to deduce whether
106** DST is on currently, but unfortunately we cannot put it to good
107** use because we don't know the rules (and that is needed to have
108** localtime() return correct tm_isdst values for times other than
109** the current time. So, we cop out and only tell the user the current
110** timezone.
111*/
112static long timezone;
113
114static void
115initmactimezone()
116{
117	MachineLocation	loc;
118	long		delta;
119
120	ReadLocation(&loc);
121
122	if (loc.latitude == 0 && loc.longitude == 0 && loc.u.gmtDelta == 0)
123		return;
124
125	delta = loc.u.gmtDelta & 0x00FFFFFF;
126
127	if (delta & 0x00800000)
128		delta |= 0xFF000000;
129
130	timezone = -delta;
131}
132#endif /* macintosh */
133
134
135static PyObject *
136time_time(self, args)
137	PyObject *self;
138	PyObject *args;
139{
140	double secs;
141	if (!PyArg_NoArgs(args))
142		return NULL;
143	secs = floattime();
144	if (secs == 0.0) {
145		PyErr_SetFromErrno(PyExc_IOError);
146		return NULL;
147	}
148	return PyFloat_FromDouble(secs);
149}
150
151#ifdef HAVE_CLOCK
152
153#ifndef CLOCKS_PER_SEC
154#ifdef CLK_TCK
155#define CLOCKS_PER_SEC CLK_TCK
156#else
157#define CLOCKS_PER_SEC 1000000
158#endif
159#endif
160
161static PyObject *
162time_clock(self, args)
163	PyObject *self;
164	PyObject *args;
165{
166	if (!PyArg_NoArgs(args))
167		return NULL;
168	return PyFloat_FromDouble(((double)clock()) / CLOCKS_PER_SEC);
169}
170#endif /* HAVE_CLOCK */
171
172#ifdef MS_WIN32
173/* Due to Mark Hammond */
174static PyObject *
175time_clock(self, args)
176	PyObject *self;
177	PyObject *args;
178{
179	static LARGE_INTEGER ctrStart;
180	static LARGE_INTEGER divisor = {0,0};
181	LARGE_INTEGER now, diff, rem;
182
183	if (!PyArg_NoArgs(args))
184		return NULL;
185
186	if (LargeIntegerEqualToZero(divisor)) {
187		QueryPerformanceCounter(&ctrStart);
188		if (!QueryPerformanceFrequency(&divisor) ||
189		    LargeIntegerEqualToZero(divisor)) {
190				/* Unlikely to happen -
191				   this works on all intel machines at least!
192				   Revert to clock() */
193			return PyFloat_FromDouble(clock());
194		}
195	}
196	QueryPerformanceCounter(&now);
197	diff = LargeIntegerSubtract(now, ctrStart);
198	diff = LargeIntegerDivide(diff, divisor, &rem);
199	/* XXX - we assume both divide results fit in 32 bits.  This is
200	   true on Intels.  First person who can afford a machine that
201	   doesnt deserves to fix it :-)
202	*/
203	return PyFloat_FromDouble((double)diff.LowPart +
204		              ((double)rem.LowPart / (double)divisor.LowPart));
205}
206#define HAVE_CLOCK /* So it gets included in the methods */
207#endif /* MS_WIN32 */
208
209static PyObject *
210time_sleep(self, args)
211	PyObject *self;
212	PyObject *args;
213{
214	double secs;
215	if (!PyArg_Parse(args, "d", &secs))
216		return NULL;
217	if (floatsleep(secs) != 0)
218		return NULL;
219	Py_INCREF(Py_None);
220	return Py_None;
221}
222
223static PyObject *
224time_convert(when, function)
225	time_t when;
226	struct tm * (*function) Py_PROTO((const time_t *));
227{
228	struct tm *p;
229	errno = 0;
230	p = function(&when);
231	if (p == NULL) {
232#ifdef EINVAL
233		if (errno == 0)
234			errno = EINVAL;
235#endif
236		return PyErr_SetFromErrno(PyExc_IOError);
237	}
238	return Py_BuildValue("(iiiiiiiii)",
239			     p->tm_year + 1900,
240			     p->tm_mon + 1,        /* Want January == 1 */
241			     p->tm_mday,
242			     p->tm_hour,
243			     p->tm_min,
244			     p->tm_sec,
245			     (p->tm_wday + 6) % 7, /* Want Monday == 0 */
246			     p->tm_yday + 1,       /* Want January, 1 == 1 */
247			     p->tm_isdst);
248}
249
250static PyObject *
251time_gmtime(self, args)
252	PyObject *self;
253	PyObject *args;
254{
255	double when;
256	if (!PyArg_Parse(args, "d", &when))
257		return NULL;
258	return time_convert((time_t)when, gmtime);
259}
260
261static PyObject *
262time_localtime(self, args)
263	PyObject *self;
264	PyObject *args;
265{
266	double when;
267	if (!PyArg_Parse(args, "d", &when))
268		return NULL;
269	return time_convert((time_t)when, localtime);
270}
271
272static int
273gettmarg(args, p)
274	PyObject *args;
275	struct tm *p;
276{
277	if (!PyArg_Parse(args, "(iiiiiiiii)",
278			 &p->tm_year,
279			 &p->tm_mon,
280			 &p->tm_mday,
281			 &p->tm_hour,
282			 &p->tm_min,
283			 &p->tm_sec,
284			 &p->tm_wday,
285			 &p->tm_yday,
286			 &p->tm_isdst))
287		return 0;
288	if (p->tm_year >= 1900)
289		p->tm_year -= 1900;
290	p->tm_mon--;
291	p->tm_wday = (p->tm_wday + 1) % 7;
292	p->tm_yday--;
293	return 1;
294}
295
296#ifdef HAVE_STRFTIME
297static PyObject *
298time_strftime(self, args)
299	PyObject *self;
300	PyObject *args;
301{
302	struct tm buf;
303	const char *fmt;
304	char *outbuf = 0;
305	int i;
306
307	memset((ANY *) &buf, '\0', sizeof(buf));
308
309	if (!PyArg_ParseTuple(args, "s(iiiiiiiii)",
310			      &fmt,
311			      &(buf.tm_year),
312			      &(buf.tm_mon),
313			      &(buf.tm_mday),
314			      &(buf.tm_hour),
315			      &(buf.tm_min),
316			      &(buf.tm_sec),
317			      &(buf.tm_wday),
318			      &(buf.tm_yday),
319			      &(buf.tm_isdst)))
320		return NULL;
321	if (buf.tm_year >= 1900)
322		buf.tm_year -= 1900;
323	buf.tm_mon--;
324	buf.tm_wday = (buf.tm_wday + 1) % 7;
325	buf.tm_yday--;
326	/* I hate these functions that presume you know how big the output
327	 * will be ahead of time...
328	 */
329	for (i = 1024 ; i <= 8192 ; i += 1024) {
330		outbuf = malloc(i);
331		if (outbuf == NULL) {
332			return PyErr_NoMemory();
333		}
334		if (strftime(outbuf, i-1, fmt, &buf) != 0) {
335			PyObject *ret;
336			ret = PyString_FromString(outbuf);
337			free(outbuf);
338			return ret;
339		}
340		free(outbuf);
341	}
342	PyErr_SetString(PyExc_ValueError,
343			"bad strftime format or result too big");
344	return NULL;
345}
346#endif /* HAVE_STRFTIME */
347
348static PyObject *
349time_asctime(self, args)
350	PyObject *self;
351	PyObject *args;
352{
353	struct tm buf;
354	char *p;
355	if (!gettmarg(args, &buf))
356		return NULL;
357	p = asctime(&buf);
358	if (p[24] == '\n')
359		p[24] = '\0';
360	return PyString_FromString(p);
361}
362
363static PyObject *
364time_ctime(self, args)
365	PyObject *self;
366	PyObject *args;
367{
368	double dt;
369	time_t tt;
370	char *p;
371	if (!PyArg_Parse(args, "d", &dt))
372		return NULL;
373	tt = (time_t)dt;
374	p = ctime(&tt);
375	if (p == NULL) {
376		PyErr_SetString(PyExc_ValueError, "unconvertible time");
377		return NULL;
378	}
379	if (p[24] == '\n')
380		p[24] = '\0';
381	return PyString_FromString(p);
382}
383
384#ifdef HAVE_MKTIME
385static PyObject *
386time_mktime(self, args)
387	PyObject *self;
388	PyObject *args;
389{
390	struct tm buf;
391	time_t tt;
392	tt = time(&tt);
393	buf = *localtime(&tt);
394	if (!gettmarg(args, &buf))
395		return NULL;
396	tt = mktime(&buf);
397	if (tt == (time_t)(-1)) {
398		PyErr_SetString(PyExc_OverflowError,
399                                "mktime argument out of range");
400		return NULL;
401	}
402	return PyFloat_FromDouble((double)tt);
403}
404#endif /* HAVE_MKTIME */
405
406static PyMethodDef time_methods[] = {
407	{"time",	time_time},
408#ifdef HAVE_CLOCK
409	{"clock",	time_clock},
410#endif
411	{"sleep",	time_sleep},
412	{"gmtime",	time_gmtime},
413	{"localtime",	time_localtime},
414	{"asctime",	time_asctime},
415	{"ctime",	time_ctime},
416#ifdef HAVE_MKTIME
417	{"mktime",	time_mktime},
418#endif
419#ifdef HAVE_STRFTIME
420	{"strftime",	time_strftime, 1},
421#endif
422	{NULL,		NULL}		/* sentinel */
423};
424
425static void
426ins(d, name, v)
427	PyObject *d;
428	char *name;
429	PyObject *v;
430{
431	if (v == NULL)
432		Py_FatalError("Can't initialize time module -- NULL value");
433	if (PyDict_SetItemString(d, name, v) != 0)
434		Py_FatalError(
435		"Can't initialize time module -- PyDict_SetItemString failed");
436	Py_DECREF(v);
437}
438
439void
440inittime()
441{
442	PyObject *m, *d;
443	m = Py_InitModule("time", time_methods);
444	d = PyModule_GetDict(m);
445#ifdef HAVE_TZNAME
446	tzset();
447	ins(d, "timezone", PyInt_FromLong((long)timezone));
448#ifdef HAVE_ALTZONE
449	ins(d, "altzone", PyInt_FromLong((long)altzone));
450#else
451	ins(d, "altzone", PyInt_FromLong((long)timezone-3600));
452#endif
453	ins(d, "daylight", PyInt_FromLong((long)daylight));
454	ins(d, "tzname", Py_BuildValue("(zz)", tzname[0], tzname[1]));
455#else /* !HAVE_TZNAME */
456#if HAVE_TM_ZONE
457	{
458#define YEAR ((time_t)((365 * 24 + 6) * 3600))
459		time_t t;
460		struct tm *p;
461		long winterzone, summerzone;
462		char wintername[10], summername[10];
463		/* XXX This won't work on the southern hemisphere.
464		  XXX Anybody got a better idea? */
465		t = (time((time_t *)0) / YEAR) * YEAR;
466		p = localtime(&t);
467		winterzone = -p->tm_gmtoff;
468		strncpy(wintername, p->tm_zone ? p->tm_zone : "   ", 9);
469		wintername[9] = '\0';
470		t += YEAR/2;
471		p = localtime(&t);
472		summerzone = -p->tm_gmtoff;
473		strncpy(summername, p->tm_zone ? p->tm_zone : "   ", 9);
474		summername[9] = '\0';
475		ins(d, "timezone", PyInt_FromLong(winterzone));
476		ins(d, "altzone", PyInt_FromLong(summerzone));
477		ins(d, "daylight",
478                    PyInt_FromLong((long)(winterzone != summerzone)));
479		ins(d, "tzname",
480                    Py_BuildValue("(zz)", wintername, summername));
481	}
482#else
483#ifdef macintosh
484	/* The only thing we can obtain is the current timezone
485	** (and whether dst is currently _active_, but that is not what
486	** we're looking for:-( )
487	*/
488	initmactimezone();
489	ins(d, "timezone", PyInt_FromLong(timezone));
490	ins(d, "altzone", PyInt_FromLong(timezone));
491	ins(d, "daylight", PyInt_FromLong((long)0));
492	ins(d, "tzname", Py_BuildValue("(zz)", "", ""));
493#endif /* macintosh */
494#endif /* HAVE_TM_ZONE */
495#endif /* !HAVE_TZNAME */
496	if (PyErr_Occurred())
497		Py_FatalError("Can't initialize time module");
498}
499
500
501/* Implement floattime() for various platforms */
502
503static double
504floattime()
505{
506	/* There are three ways to get the time:
507	  (1) gettimeofday() -- resolution in microseconds
508	  (2) ftime() -- resolution in milliseconds
509	  (3) time() -- resolution in seconds
510	  In all cases the return value is a float in seconds.
511	  Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
512	  fail, so we fall back on ftime() or time().
513	  Note: clock resolution does not imply clock accuracy! */
514#ifdef HAVE_GETTIMEOFDAY
515	{
516		struct timeval t;
517#ifdef GETTIMEOFDAY_NO_TZ
518		if (gettimeofday(&t) == 0)
519			return (double)t.tv_sec + t.tv_usec*0.000001;
520#else /* !GETTIMEOFDAY_NO_TZ */
521		if (gettimeofday(&t, (struct timezone *)NULL) == 0)
522			return (double)t.tv_sec + t.tv_usec*0.000001;
523#endif /* !GETTIMEOFDAY_NO_TZ */
524	}
525#endif /* !HAVE_GETTIMEOFDAY */
526	{
527#ifdef HAVE_FTIME
528		struct timeb t;
529		ftime(&t);
530		return (double)t.time + (double)t.millitm * (double)0.001;
531#else /* !HAVE_FTIME */
532		time_t secs;
533		time(&secs);
534		return (double)secs;
535#endif /* !HAVE_FTIME */
536	}
537}
538
539
540/* Implement floatsleep() for various platforms.
541   When interrupted (or when another error occurs), return -1 and
542   set an exception; else return 0. */
543
544static int
545#ifdef MPW
546floatsleep(double secs)
547#else
548	floatsleep(secs)
549	double secs;
550#endif /* MPW */
551{
552/* XXX Should test for MS_WIN32 first! */
553#ifdef HAVE_SELECT
554	struct timeval t;
555	double frac;
556	frac = fmod(secs, 1.0);
557	secs = floor(secs);
558	t.tv_sec = (long)secs;
559	t.tv_usec = (long)(frac*1000000.0);
560	Py_BEGIN_ALLOW_THREADS
561	if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) {
562		Py_BLOCK_THREADS
563		PyErr_SetFromErrno(PyExc_IOError);
564		return -1;
565	}
566	Py_END_ALLOW_THREADS
567#else /* !HAVE_SELECT */
568#ifdef macintosh
569#define MacTicks	(* (long *)0x16A)
570	long deadline;
571	deadline = MacTicks + (long)(secs * 60.0);
572	while (MacTicks < deadline) {
573		/* XXX Should call some yielding function here */
574		if (PyErr_CheckSignals())
575			return -1;
576	}
577#else /* !macintosh */
578#if defined(__WATCOMC__) && !defined(__QNX__)
579	/* XXX Can't interrupt this sleep */
580	Py_BEGIN_ALLOW_THREADS
581	delay((int)(secs * 1000 + 0.5));  /* delay() uses milliseconds */
582	Py_END_ALLOW_THREADS
583#else /* !__WATCOMC__ || __QNX__ */
584#ifdef MSDOS
585	struct timeb t1, t2;
586	double frac;
587	extern double fmod Py_PROTO((double, double));
588	extern double floor Py_PROTO((double));
589	if (secs <= 0.0)
590		return;
591	frac = fmod(secs, 1.0);
592	secs = floor(secs);
593	ftime(&t1);
594	t2.time = t1.time + (int)secs;
595	t2.millitm = t1.millitm + (int)(frac*1000.0);
596	while (t2.millitm >= 1000) {
597		t2.time++;
598		t2.millitm -= 1000;
599	}
600	for (;;) {
601#ifdef QUICKWIN
602		Py_BEGIN_ALLOW_THREADS
603		_wyield();
604		Py_END_ALLOW_THREADS
605#endif
606		if (PyErr_CheckSignals())
607			return -1;
608		ftime(&t1);
609		if (t1.time > t2.time ||
610		    t1.time == t2.time && t1.millitm >= t2.millitm)
611			break;
612	}
613#else /* !MSDOS */
614#ifdef MS_WIN32
615	/* XXX Can't interrupt this sleep */
616	Py_BEGIN_ALLOW_THREADS
617	Sleep((int)(secs*1000));
618	Py_END_ALLOW_THREADS
619#else /* !MS_WIN32 */
620#ifdef PYOS_OS2
621	/* This Sleep *IS* Interruptable by Exceptions */
622	Py_BEGIN_ALLOW_THREADS
623	if (DosSleep(secs * 1000) != NO_ERROR) {
624		Py_BLOCK_THREADS
625		PyErr_SetFromErrno(PyExc_IOError);
626		return -1;
627	}
628	Py_END_ALLOW_THREADS
629#else /* !PYOS_OS2 */
630	/* XXX Can't interrupt this sleep */
631	Py_BEGIN_ALLOW_THREADS
632	sleep((int)secs);
633	Py_END_ALLOW_THREADS
634#endif /* !PYOS_OS2 */
635#endif /* !MS_WIN32 */
636#endif /* !MSDOS */
637#endif /* !__WATCOMC__ || __QNX__ */
638#endif /* !macintosh */
639#endif /* !HAVE_SELECT */
640	return 0;
641}
642