timemodule.c revision b3cfc1d7eab506cbdd6c579b12e0f2f265f5f2c5
1
2/* Time module */
3
4#include "Python.h"
5#include "structseq.h"
6
7#include <ctype.h>
8
9#ifdef macintosh
10#include <time.h>
11#include <OSUtils.h>
12#ifdef USE_GUSI211
13/* GUSI, the I/O library which has the time() function and such uses the
14** Mac epoch of 1904. MSL, the C library which has localtime() and so uses
15** the ANSI epoch of 1900.
16*/
17#define GUSI_TO_MSL_EPOCH (4*365*24*60*60)
18#endif /* USE_GUSI2 */
19#else
20#include <sys/types.h>
21#endif
22
23#ifdef QUICKWIN
24#include <io.h>
25#endif
26
27#ifdef HAVE_UNISTD_H
28#include <unistd.h>
29#endif
30
31#ifdef HAVE_FTIME
32#include <sys/timeb.h>
33#if !defined(MS_WINDOWS) && !defined(PYOS_OS2)
34extern int ftime(struct timeb *);
35#endif /* MS_WINDOWS */
36#endif /* HAVE_FTIME */
37
38#if defined(__WATCOMC__) && !defined(__QNX__)
39#include <i86.h>
40#else
41#ifdef MS_WINDOWS
42#include <windows.h>
43#if defined(MS_WIN16) || defined(__BORLANDC__)
44/* These overrides not needed for Win32 */
45#define timezone _timezone
46#define tzname _tzname
47#define daylight _daylight
48#endif /* MS_WIN16 || __BORLANDC__ */
49#ifdef MS_WIN16
50#define altzone _altzone
51#endif /* MS_WIN16 */
52#endif /* MS_WINDOWS */
53#endif /* !__WATCOMC__ || __QNX__ */
54
55#if defined(MS_WIN32) && !defined(MS_WIN64) && !defined(__BORLANDC__)
56/* Win32 has better clock replacement
57   XXX Win64 does not yet, but might when the platform matures. */
58#include <largeint.h>
59#undef HAVE_CLOCK /* We have our own version down below */
60#endif /* MS_WIN32 && !MS_WIN64 */
61
62#if defined(PYCC_VACPP)
63#include <sys/time.h>
64#endif
65
66#ifdef __BEOS__
67#include <time.h>
68/* For bigtime_t, snooze(). - [cjh] */
69#include <support/SupportDefs.h>
70#include <kernel/OS.h>
71#endif
72
73/* Forward declarations */
74static int floatsleep(double);
75static double floattime(void);
76
77/* For Y2K check */
78static PyObject *moddict;
79
80#ifdef macintosh
81/* Our own timezone. We have enough information to deduce whether
82** DST is on currently, but unfortunately we cannot put it to good
83** use because we don't know the rules (and that is needed to have
84** localtime() return correct tm_isdst values for times other than
85** the current time. So, we cop out and only tell the user the current
86** timezone.
87*/
88static long timezone;
89
90static void
91initmactimezone(void)
92{
93	MachineLocation	loc;
94	long		delta;
95
96	ReadLocation(&loc);
97
98	if (loc.latitude == 0 && loc.longitude == 0 && loc.u.gmtDelta == 0)
99		return;
100
101	delta = loc.u.gmtDelta & 0x00FFFFFF;
102
103	if (delta & 0x00800000)
104		delta |= 0xFF000000;
105
106	timezone = -delta;
107}
108#endif /* macintosh */
109
110
111static PyObject *
112time_time(PyObject *self, PyObject *args)
113{
114	double secs;
115	if (!PyArg_ParseTuple(args, ":time"))
116		return NULL;
117	secs = floattime();
118	if (secs == 0.0) {
119		PyErr_SetFromErrno(PyExc_IOError);
120		return NULL;
121	}
122	return PyFloat_FromDouble(secs);
123}
124
125static char time_doc[] =
126"time() -> floating point number\n\
127\n\
128Return the current time in seconds since the Epoch.\n\
129Fractions of a second may be present if the system clock provides them.";
130
131#ifdef HAVE_CLOCK
132
133#ifndef CLOCKS_PER_SEC
134#ifdef CLK_TCK
135#define CLOCKS_PER_SEC CLK_TCK
136#else
137#define CLOCKS_PER_SEC 1000000
138#endif
139#endif
140
141static PyObject *
142time_clock(PyObject *self, PyObject *args)
143{
144	if (!PyArg_ParseTuple(args, ":clock"))
145		return NULL;
146	return PyFloat_FromDouble(((double)clock()) / CLOCKS_PER_SEC);
147}
148#endif /* HAVE_CLOCK */
149
150#if defined(MS_WIN32) && !defined(MS_WIN64) && !defined(__BORLANDC__)
151/* Due to Mark Hammond */
152static PyObject *
153time_clock(PyObject *self, PyObject *args)
154{
155	static LARGE_INTEGER ctrStart;
156	static LARGE_INTEGER divisor = {0,0};
157	LARGE_INTEGER now, diff, rem;
158
159	if (!PyArg_ParseTuple(args, ":clock"))
160		return NULL;
161
162	if (LargeIntegerEqualToZero(divisor)) {
163		QueryPerformanceCounter(&ctrStart);
164		if (!QueryPerformanceFrequency(&divisor) ||
165		    LargeIntegerEqualToZero(divisor)) {
166				/* Unlikely to happen -
167				   this works on all intel machines at least!
168				   Revert to clock() */
169			return PyFloat_FromDouble(clock());
170		}
171	}
172	QueryPerformanceCounter(&now);
173	diff = LargeIntegerSubtract(now, ctrStart);
174	diff = LargeIntegerDivide(diff, divisor, &rem);
175	/* XXX - we assume both divide results fit in 32 bits.  This is
176	   true on Intels.  First person who can afford a machine that
177	   doesnt deserves to fix it :-)
178	*/
179	return PyFloat_FromDouble((double)diff.LowPart +
180		              ((double)rem.LowPart / (double)divisor.LowPart));
181}
182
183#define HAVE_CLOCK /* So it gets included in the methods */
184#endif /* MS_WIN32 && !MS_WIN64 */
185
186#ifdef HAVE_CLOCK
187static char clock_doc[] =
188"clock() -> floating point number\n\
189\n\
190Return the CPU time or real time since the start of the process or since\n\
191the first call to clock().  This has as much precision as the system records.";
192#endif
193
194static PyObject *
195time_sleep(PyObject *self, PyObject *args)
196{
197	double secs;
198	if (!PyArg_ParseTuple(args, "d:sleep", &secs))
199		return NULL;
200	if (floatsleep(secs) != 0)
201		return NULL;
202	Py_INCREF(Py_None);
203	return Py_None;
204}
205
206static char sleep_doc[] =
207"sleep(seconds)\n\
208\n\
209Delay execution for a given number of seconds.  The argument may be\n\
210a floating point number for subsecond precision.";
211
212static PyStructSequence_Field struct_time_type_fields[] = {
213	{"tm_year", NULL},
214	{"tm_mon", NULL},
215	{"tm_mday", NULL},
216	{"tm_hour", NULL},
217	{"tm_min", NULL},
218	{"tm_sec", NULL},
219	{"tm_wday", NULL},
220	{"tm_yday", NULL},
221	{"tm_isdst", NULL},
222	{0}
223};
224
225static PyStructSequence_Desc struct_time_type_desc = {
226	"struct_time",
227	NULL,
228	struct_time_type_fields,
229	9,
230};
231
232static PyTypeObject StructTimeType;
233
234static PyObject *
235tmtotuple(struct tm *p)
236{
237	PyObject *v = PyStructSequence_New(&StructTimeType);
238	if (v == NULL)
239		return NULL;
240
241#define SET(i,val) PyStructSequence_SET_ITEM(v, i, PyInt_FromLong((long) val))
242
243	SET(0, p->tm_year + 1900);
244	SET(1, p->tm_mon + 1);	   /* Want January == 1 */
245	SET(2, p->tm_mday);
246	SET(3, p->tm_hour);
247	SET(4, p->tm_min);
248	SET(5, p->tm_sec);
249	SET(6, (p->tm_wday + 6) % 7); /* Want Monday == 0 */
250	SET(7, p->tm_yday + 1);	   /* Want January, 1 == 1 */
251	SET(8, p->tm_isdst);
252#undef SET
253	if (PyErr_Occurred()) {
254		Py_XDECREF(v);
255		return NULL;
256	}
257
258	return v;
259}
260
261static PyObject *
262time_convert(time_t when, struct tm * (*function)(const time_t *))
263{
264	struct tm *p;
265	errno = 0;
266#if defined(macintosh) && defined(USE_GUSI204)
267	when = when + GUSI_TO_MSL_EPOCH;
268#endif
269	p = function(&when);
270	if (p == NULL) {
271#ifdef EINVAL
272		if (errno == 0)
273			errno = EINVAL;
274#endif
275		return PyErr_SetFromErrno(PyExc_IOError);
276	}
277	return tmtotuple(p);
278}
279
280static PyObject *
281time_gmtime(PyObject *self, PyObject *args)
282{
283	double when;
284	if (PyTuple_Size(args) == 0)
285		when = floattime();
286	if (!PyArg_ParseTuple(args, "|d:gmtime", &when))
287		return NULL;
288	return time_convert((time_t)when, gmtime);
289}
290
291static char gmtime_doc[] =
292"gmtime([seconds]) -> (year,month,day,hour,minute,second,weekday,dayofyear,dst)\n\
293\n\
294Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\
295GMT).  When 'seconds' is not passed in, convert the current time instead.";
296
297static PyObject *
298time_localtime(PyObject *self, PyObject *args)
299{
300	double when;
301	if (PyTuple_Size(args) == 0)
302		when = floattime();
303	if (!PyArg_ParseTuple(args, "|d:localtime", &when))
304		return NULL;
305	return time_convert((time_t)when, localtime);
306}
307
308static char localtime_doc[] =
309"localtime([seconds]) -> (year,month,day,hour,minute,second,weekday,dayofyear,dst)\n\
310\n\
311Convert seconds since the Epoch to a time tuple expressing local time.\n\
312When 'seconds' is not passed in, convert the current time instead.";
313
314static int
315gettmarg(PyObject *args, struct tm *p)
316{
317	int y;
318	memset((void *) p, '\0', sizeof(struct tm));
319
320	if (!PyArg_Parse(args, "(iiiiiiiii)",
321			 &y,
322			 &p->tm_mon,
323			 &p->tm_mday,
324			 &p->tm_hour,
325			 &p->tm_min,
326			 &p->tm_sec,
327			 &p->tm_wday,
328			 &p->tm_yday,
329			 &p->tm_isdst))
330		return 0;
331	if (y < 1900) {
332		PyObject *accept = PyDict_GetItemString(moddict,
333							"accept2dyear");
334		if (accept == NULL || !PyInt_Check(accept) ||
335		    PyInt_AsLong(accept) == 0) {
336			PyErr_SetString(PyExc_ValueError,
337					"year >= 1900 required");
338			return 0;
339		}
340		if (69 <= y && y <= 99)
341			y += 1900;
342		else if (0 <= y && y <= 68)
343			y += 2000;
344		else {
345			PyErr_SetString(PyExc_ValueError,
346					"year out of range");
347			return 0;
348		}
349	}
350	p->tm_year = y - 1900;
351	p->tm_mon--;
352	p->tm_wday = (p->tm_wday + 1) % 7;
353	p->tm_yday--;
354	return 1;
355}
356
357#ifdef HAVE_STRFTIME
358static PyObject *
359time_strftime(PyObject *self, PyObject *args)
360{
361	PyObject *tup = NULL;
362	struct tm buf;
363	const char *fmt;
364	size_t fmtlen, buflen;
365	char *outbuf = 0;
366	size_t i;
367
368	memset((void *) &buf, '\0', sizeof(buf));
369
370	if (!PyArg_ParseTuple(args, "s|O:strftime", &fmt, &tup))
371		return NULL;
372
373	if (tup == NULL) {
374		time_t tt = time(NULL);
375		buf = *localtime(&tt);
376	} else if (!gettmarg(tup, &buf))
377		return NULL;
378
379	fmtlen = strlen(fmt);
380
381	/* I hate these functions that presume you know how big the output
382	 * will be ahead of time...
383	 */
384	for (i = 1024; ; i += i) {
385		outbuf = malloc(i);
386		if (outbuf == NULL) {
387			return PyErr_NoMemory();
388		}
389		buflen = strftime(outbuf, i, fmt, &buf);
390		if (buflen > 0 || i >= 256 * fmtlen) {
391			/* If the buffer is 256 times as long as the format,
392			   it's probably not failing for lack of room!
393			   More likely, the format yields an empty result,
394			   e.g. an empty format, or %Z when the timezone
395			   is unknown. */
396			PyObject *ret;
397			ret = PyString_FromStringAndSize(outbuf, buflen);
398			free(outbuf);
399			return ret;
400		}
401		free(outbuf);
402	}
403}
404
405static char strftime_doc[] =
406"strftime(format[, tuple]) -> string\n\
407\n\
408Convert a time tuple to a string according to a format specification.\n\
409See the library reference manual for formatting codes. When the time tuple\n\
410is not present, current time as returned by localtime() is used.";
411#endif /* HAVE_STRFTIME */
412
413#ifdef HAVE_STRPTIME
414
415#if 0
416/* Enable this if it's not declared in <time.h> */
417extern char *strptime(const char *, const char *, struct tm *);
418#endif
419
420static PyObject *
421time_strptime(PyObject *self, PyObject *args)
422{
423	struct tm tm;
424	char *fmt = "%a %b %d %H:%M:%S %Y";
425	char *buf;
426	char *s;
427
428	if (!PyArg_ParseTuple(args, "s|s:strptime", &buf, &fmt))
429	        return NULL;
430	memset((void *) &tm, '\0', sizeof(tm));
431	s = strptime(buf, fmt, &tm);
432	if (s == NULL) {
433		PyErr_SetString(PyExc_ValueError, "format mismatch");
434		return NULL;
435	}
436	while (*s && isspace(Py_CHARMASK(*s)))
437		s++;
438	if (*s) {
439		PyErr_Format(PyExc_ValueError,
440			     "unconverted data remains: '%.400s'", s);
441		return NULL;
442	}
443	return tmtotuple(&tm);
444}
445
446static char strptime_doc[] =
447"strptime(string, format) -> tuple\n\
448\n\
449Parse a string to a time tuple according to a format specification.\n\
450See the library reference manual for formatting codes (same as strftime()).";
451#endif /* HAVE_STRPTIME */
452
453static PyObject *
454time_asctime(PyObject *self, PyObject *args)
455{
456	PyObject *tup = NULL;
457	struct tm buf;
458	char *p;
459	if (!PyArg_ParseTuple(args, "|O:asctime", &tup))
460		return NULL;
461	if (tup == NULL) {
462		time_t tt = time(NULL);
463		buf = *localtime(&tt);
464	} else if (!gettmarg(tup, &buf))
465		return NULL;
466	p = asctime(&buf);
467	if (p[24] == '\n')
468		p[24] = '\0';
469	return PyString_FromString(p);
470}
471
472static char asctime_doc[] =
473"asctime([tuple]) -> string\n\
474\n\
475Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'.\n\
476When the time tuple is not present, current time as returned by localtime()\n\
477is used.";
478
479static PyObject *
480time_ctime(PyObject *self, PyObject *args)
481{
482	double dt;
483	time_t tt;
484	char *p;
485
486	if (PyTuple_Size(args) == 0)
487		tt = time(NULL);
488	else {
489		if (!PyArg_ParseTuple(args, "|d:ctime", &dt))
490			return NULL;
491		tt = (time_t)dt;
492	}
493#if defined(macintosh) && defined(USE_GUSI204)
494	tt = tt + GUSI_TO_MSL_EPOCH;
495#endif
496	p = ctime(&tt);
497	if (p == NULL) {
498		PyErr_SetString(PyExc_ValueError, "unconvertible time");
499		return NULL;
500	}
501	if (p[24] == '\n')
502		p[24] = '\0';
503	return PyString_FromString(p);
504}
505
506static char ctime_doc[] =
507"ctime(seconds) -> string\n\
508\n\
509Convert a time in seconds since the Epoch to a string in local time.\n\
510This is equivalent to asctime(localtime(seconds)). When the time tuple is\n\
511not present, current time as returned by localtime() is used.";
512
513#ifdef HAVE_MKTIME
514static PyObject *
515time_mktime(PyObject *self, PyObject *args)
516{
517	PyObject *tup;
518	struct tm buf;
519	time_t tt;
520	if (!PyArg_ParseTuple(args, "O:mktime", &tup))
521		return NULL;
522	tt = time(&tt);
523	buf = *localtime(&tt);
524	if (!gettmarg(tup, &buf))
525		return NULL;
526	tt = mktime(&buf);
527	if (tt == (time_t)(-1)) {
528		PyErr_SetString(PyExc_OverflowError,
529				"mktime argument out of range");
530		return NULL;
531	}
532#if defined(macintosh) && defined(USE_GUSI211)
533	tt = tt - GUSI_TO_MSL_EPOCH;
534#endif
535	return PyFloat_FromDouble((double)tt);
536}
537
538static char mktime_doc[] =
539"mktime(tuple) -> floating point number\n\
540\n\
541Convert a time tuple in local time to seconds since the Epoch.";
542#endif /* HAVE_MKTIME */
543
544static PyMethodDef time_methods[] = {
545	{"time",	time_time, METH_VARARGS, time_doc},
546#ifdef HAVE_CLOCK
547	{"clock",	time_clock, METH_VARARGS, clock_doc},
548#endif
549	{"sleep",	time_sleep, METH_VARARGS, sleep_doc},
550	{"gmtime",	time_gmtime, METH_VARARGS, gmtime_doc},
551	{"localtime",	time_localtime, METH_VARARGS, localtime_doc},
552	{"asctime",	time_asctime, METH_VARARGS, asctime_doc},
553	{"ctime",	time_ctime, METH_VARARGS, ctime_doc},
554#ifdef HAVE_MKTIME
555	{"mktime",	time_mktime, METH_VARARGS, mktime_doc},
556#endif
557#ifdef HAVE_STRFTIME
558	{"strftime",	time_strftime, METH_VARARGS, strftime_doc},
559#endif
560#ifdef HAVE_STRPTIME
561	{"strptime",	time_strptime, METH_VARARGS, strptime_doc},
562#endif
563	{NULL,		NULL}		/* sentinel */
564};
565
566static void
567ins(PyObject *d, char *name, PyObject *v)
568{
569	/* Don't worry too much about errors, they'll be caught by the
570	 * caller of inittime().
571	 */
572	if (v)
573		PyDict_SetItemString(d, name, v);
574	Py_XDECREF(v);
575}
576
577
578static char module_doc[] =
579"This module provides various functions to manipulate time values.\n\
580\n\
581There are two standard representations of time.  One is the number\n\
582of seconds since the Epoch, in UTC (a.k.a. GMT).  It may be an integer\n\
583or a floating point number (to represent fractions of seconds).\n\
584The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
585The actual value can be retrieved by calling gmtime(0).\n\
586\n\
587The other representation is a tuple of 9 integers giving local time.\n\
588The tuple items are:\n\
589  year (four digits, e.g. 1998)\n\
590  month (1-12)\n\
591  day (1-31)\n\
592  hours (0-23)\n\
593  minutes (0-59)\n\
594  seconds (0-59)\n\
595  weekday (0-6, Monday is 0)\n\
596  Julian day (day in the year, 1-366)\n\
597  DST (Daylight Savings Time) flag (-1, 0 or 1)\n\
598If the DST flag is 0, the time is given in the regular time zone;\n\
599if it is 1, the time is given in the DST time zone;\n\
600if it is -1, mktime() should guess based on the date and time.\n\
601\n\
602Variables:\n\
603\n\
604timezone -- difference in seconds between UTC and local standard time\n\
605altzone -- difference in  seconds between UTC and local DST time\n\
606daylight -- whether local time should reflect DST\n\
607tzname -- tuple of (standard time zone name, DST time zone name)\n\
608\n\
609Functions:\n\
610\n\
611time() -- return current time in seconds since the Epoch as a float\n\
612clock() -- return CPU time since process start as a float\n\
613sleep() -- delay for a number of seconds given as a float\n\
614gmtime() -- convert seconds since Epoch to UTC tuple\n\
615localtime() -- convert seconds since Epoch to local time tuple\n\
616asctime() -- convert time tuple to string\n\
617ctime() -- convert time in seconds to string\n\
618mktime() -- convert local time tuple to seconds since Epoch\n\
619strftime() -- convert time tuple to string according to format specification\n\
620strptime() -- parse string to time tuple according to format specification\n\
621";
622
623
624DL_EXPORT(void)
625inittime(void)
626{
627	PyObject *m, *d;
628	char *p;
629	m = Py_InitModule3("time", time_methods, module_doc);
630	d = PyModule_GetDict(m);
631	/* Accept 2-digit dates unless PYTHONY2K is set and non-empty */
632	p = Py_GETENV("PYTHONY2K");
633	ins(d, "accept2dyear", PyInt_FromLong((long) (!p || !*p)));
634	/* Squirrel away the module's dictionary for the y2k check */
635	Py_INCREF(d);
636	moddict = d;
637#if defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__)
638	tzset();
639#ifdef PYOS_OS2
640	ins(d, "timezone", PyInt_FromLong((long)_timezone));
641#else /* !PYOS_OS2 */
642	ins(d, "timezone", PyInt_FromLong((long)timezone));
643#endif /* PYOS_OS2 */
644#ifdef HAVE_ALTZONE
645	ins(d, "altzone", PyInt_FromLong((long)altzone));
646#else
647#ifdef PYOS_OS2
648	ins(d, "altzone", PyInt_FromLong((long)_timezone-3600));
649#else /* !PYOS_OS2 */
650	ins(d, "altzone", PyInt_FromLong((long)timezone-3600));
651#endif /* PYOS_OS2 */
652#endif
653	ins(d, "daylight", PyInt_FromLong((long)daylight));
654	ins(d, "tzname", Py_BuildValue("(zz)", tzname[0], tzname[1]));
655#else /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
656#ifdef HAVE_TM_ZONE
657	{
658#define YEAR ((time_t)((365 * 24 + 6) * 3600))
659		time_t t;
660		struct tm *p;
661		long janzone, julyzone;
662		char janname[10], julyname[10];
663		t = (time((time_t *)0) / YEAR) * YEAR;
664		p = localtime(&t);
665		janzone = -p->tm_gmtoff;
666		strncpy(janname, p->tm_zone ? p->tm_zone : "   ", 9);
667		janname[9] = '\0';
668		t += YEAR/2;
669		p = localtime(&t);
670		julyzone = -p->tm_gmtoff;
671		strncpy(julyname, p->tm_zone ? p->tm_zone : "   ", 9);
672		julyname[9] = '\0';
673
674		if( janzone < julyzone ) {
675			/* DST is reversed in the southern hemisphere */
676			ins(d, "timezone", PyInt_FromLong(julyzone));
677			ins(d, "altzone", PyInt_FromLong(janzone));
678			ins(d, "daylight",
679			    PyInt_FromLong((long)(janzone != julyzone)));
680			ins(d, "tzname",
681			    Py_BuildValue("(zz)", julyname, janname));
682		} else {
683			ins(d, "timezone", PyInt_FromLong(janzone));
684			ins(d, "altzone", PyInt_FromLong(julyzone));
685			ins(d, "daylight",
686			    PyInt_FromLong((long)(janzone != julyzone)));
687			ins(d, "tzname",
688			    Py_BuildValue("(zz)", janname, julyname));
689		}
690	}
691#else
692#ifdef macintosh
693	/* The only thing we can obtain is the current timezone
694	** (and whether dst is currently _active_, but that is not what
695	** we're looking for:-( )
696	*/
697	initmactimezone();
698	ins(d, "timezone", PyInt_FromLong(timezone));
699	ins(d, "altzone", PyInt_FromLong(timezone));
700	ins(d, "daylight", PyInt_FromLong((long)0));
701	ins(d, "tzname", Py_BuildValue("(zz)", "", ""));
702#endif /* macintosh */
703#endif /* HAVE_TM_ZONE */
704#ifdef __CYGWIN__
705	tzset();
706	ins(d, "timezone", PyInt_FromLong(_timezone));
707	ins(d, "altzone", PyInt_FromLong(_timezone));
708	ins(d, "daylight", PyInt_FromLong(_daylight));
709	ins(d, "tzname", Py_BuildValue("(zz)", _tzname[0], _tzname[1]));
710#endif /* __CYGWIN__ */
711#endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
712
713        PyStructSequence_InitType(&StructTimeType, &struct_time_type_desc);
714	PyDict_SetItemString(d, "struct_time", (PyObject*) &StructTimeType);
715}
716
717
718/* Implement floattime() for various platforms */
719
720static double
721floattime(void)
722{
723	/* There are three ways to get the time:
724	  (1) gettimeofday() -- resolution in microseconds
725	  (2) ftime() -- resolution in milliseconds
726	  (3) time() -- resolution in seconds
727	  In all cases the return value is a float in seconds.
728	  Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
729	  fail, so we fall back on ftime() or time().
730	  Note: clock resolution does not imply clock accuracy! */
731#ifdef HAVE_GETTIMEOFDAY
732	{
733		struct timeval t;
734#ifdef GETTIMEOFDAY_NO_TZ
735		if (gettimeofday(&t) == 0)
736			return (double)t.tv_sec + t.tv_usec*0.000001;
737#else /* !GETTIMEOFDAY_NO_TZ */
738		if (gettimeofday(&t, (struct timezone *)NULL) == 0)
739			return (double)t.tv_sec + t.tv_usec*0.000001;
740#endif /* !GETTIMEOFDAY_NO_TZ */
741	}
742#endif /* !HAVE_GETTIMEOFDAY */
743	{
744#if defined(HAVE_FTIME)
745		struct timeb t;
746		ftime(&t);
747		return (double)t.time + (double)t.millitm * (double)0.001;
748#else /* !HAVE_FTIME */
749		time_t secs;
750		time(&secs);
751		return (double)secs;
752#endif /* !HAVE_FTIME */
753	}
754}
755
756
757/* Implement floatsleep() for various platforms.
758   When interrupted (or when another error occurs), return -1 and
759   set an exception; else return 0. */
760
761static int
762floatsleep(double secs)
763{
764/* XXX Should test for MS_WIN32 first! */
765#if defined(HAVE_SELECT) && !defined(__BEOS__)
766	struct timeval t;
767	double frac;
768	frac = fmod(secs, 1.0);
769	secs = floor(secs);
770	t.tv_sec = (long)secs;
771	t.tv_usec = (long)(frac*1000000.0);
772	Py_BEGIN_ALLOW_THREADS
773	if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) {
774#ifdef EINTR
775		if (errno != EINTR) {
776#else
777		if (1) {
778#endif
779			Py_BLOCK_THREADS
780			PyErr_SetFromErrno(PyExc_IOError);
781			return -1;
782		}
783	}
784	Py_END_ALLOW_THREADS
785#else /* !HAVE_SELECT || __BEOS__ */
786#ifdef macintosh
787#define MacTicks	(* (long *)0x16A)
788	long deadline;
789	deadline = MacTicks + (long)(secs * 60.0);
790	while (MacTicks < deadline) {
791		/* XXX Should call some yielding function here */
792		if (PyErr_CheckSignals())
793			return -1;
794	}
795#else /* !macintosh */
796#if defined(__WATCOMC__) && !defined(__QNX__)
797	/* XXX Can't interrupt this sleep */
798	Py_BEGIN_ALLOW_THREADS
799	delay((int)(secs * 1000 + 0.5));  /* delay() uses milliseconds */
800	Py_END_ALLOW_THREADS
801#else /* !__WATCOMC__ || __QNX__ */
802#ifdef MSDOS
803	struct timeb t1, t2;
804	double frac;
805	extern double fmod(double, double);
806	extern double floor(double);
807	if (secs <= 0.0)
808		return;
809	frac = fmod(secs, 1.0);
810	secs = floor(secs);
811	ftime(&t1);
812	t2.time = t1.time + (int)secs;
813	t2.millitm = t1.millitm + (int)(frac*1000.0);
814	while (t2.millitm >= 1000) {
815		t2.time++;
816		t2.millitm -= 1000;
817	}
818	for (;;) {
819#ifdef QUICKWIN
820		Py_BEGIN_ALLOW_THREADS
821		_wyield();
822		Py_END_ALLOW_THREADS
823#endif
824		if (PyErr_CheckSignals())
825			return -1;
826		ftime(&t1);
827		if (t1.time > t2.time ||
828		    t1.time == t2.time && t1.millitm >= t2.millitm)
829			break;
830	}
831#else /* !MSDOS */
832#ifdef MS_WIN32
833	{
834		double millisecs = secs * 1000.0;
835		if (millisecs > (double)ULONG_MAX) {
836			PyErr_SetString(PyExc_OverflowError, "sleep length is too large");
837			return -1;
838		}
839		/* XXX Can't interrupt this sleep */
840		Py_BEGIN_ALLOW_THREADS
841		Sleep((unsigned long)millisecs);
842		Py_END_ALLOW_THREADS
843	}
844#else /* !MS_WIN32 */
845#ifdef PYOS_OS2
846	/* This Sleep *IS* Interruptable by Exceptions */
847	Py_BEGIN_ALLOW_THREADS
848	if (DosSleep(secs * 1000) != NO_ERROR) {
849		Py_BLOCK_THREADS
850		PyErr_SetFromErrno(PyExc_IOError);
851		return -1;
852	}
853	Py_END_ALLOW_THREADS
854#else /* !PYOS_OS2 */
855#ifdef __BEOS__
856	/* This sleep *CAN BE* interrupted. */
857	{
858		if( secs <= 0.0 ) {
859			return;
860		}
861
862		Py_BEGIN_ALLOW_THREADS
863		/* BeOS snooze() is in microseconds... */
864		if( snooze( (bigtime_t)( secs * 1000.0 * 1000.0 ) ) == B_INTERRUPTED ) {
865			Py_BLOCK_THREADS
866			PyErr_SetFromErrno( PyExc_IOError );
867			return -1;
868		}
869		Py_END_ALLOW_THREADS
870	}
871#else /* !__BEOS__ */
872#ifdef RISCOS
873	if (secs <= 0.0)
874		return 0;
875	Py_BEGIN_ALLOW_THREADS
876	/* This sleep *CAN BE* interrupted. */
877	if ( sleep(secs) )
878		return -1;
879	Py_END_ALLOW_THREADS
880#else /* !RISCOS */
881	/* XXX Can't interrupt this sleep */
882	Py_BEGIN_ALLOW_THREADS
883	sleep((int)secs);
884	Py_END_ALLOW_THREADS
885#endif /* !RISCOS */
886#endif /* !__BEOS__ */
887#endif /* !PYOS_OS2 */
888#endif /* !MS_WIN32 */
889#endif /* !MSDOS */
890#endif /* !__WATCOMC__ || __QNX__ */
891#endif /* !macintosh */
892#endif /* !HAVE_SELECT */
893
894	return 0;
895}
896