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