blob: ee3fb8db983c5584696b6683829dd31cecd44242 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00004
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 not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* Time module */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000028#include "modsupport.h"
Guido van Rossumff4949e1992-08-05 19:58:53 +000029#include "ceval.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000030
Guido van Rossum6d946f91992-08-14 13:49:30 +000031#ifdef macintosh
Guido van Rossumb6775db1994-08-01 11:34:53 +000032#include <time.h>
33#else
34#include <sys/types.h>
Guido van Rossum6d946f91992-08-14 13:49:30 +000035#endif
36
Guido van Rossumb6775db1994-08-01 11:34:53 +000037#ifdef QUICKWIN
38#include <io.h>
39#endif
40
41#ifdef HAVE_UNISTD_H
Guido van Rossum2762f251992-03-27 17:22:13 +000042#include <unistd.h>
43#endif
44
Guido van Rossumb6775db1994-08-01 11:34:53 +000045#ifdef HAVE_SELECT
46#include "myselect.h"
47#else
48#include "mytime.h"
49#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000050
Guido van Rossumb6775db1994-08-01 11:34:53 +000051#ifdef HAVE_FTIME
52#include <sys/timeb.h>
53#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000054
Guido van Rossumb6775db1994-08-01 11:34:53 +000055#ifdef _M_IX86
56#include <windows.h>
57#define timezone _timezone
Guido van Rossumcc081121995-03-14 15:05:41 +000058#define tzname _tzname
59#define daylight _daylight
60#define altzone _altzone
Guido van Rossumb376a4a1993-11-23 17:53:17 +000061#endif
Guido van Rossum234f9421993-06-17 12:35:49 +000062
63/* Forward declarations */
Guido van Rossumb6775db1994-08-01 11:34:53 +000064static int floatsleep PROTO((double));
65static double floattime PROTO(());
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000066
67static object *
68time_time(self, args)
69 object *self;
70 object *args;
71{
Guido van Rossumb6775db1994-08-01 11:34:53 +000072 double secs;
Guido van Rossuma2b7f401993-01-04 09:09:59 +000073 if (!getnoarg(args))
74 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +000075 secs = floattime();
76 if (secs == 0.0) {
Guido van Rossuma2b7f401993-01-04 09:09:59 +000077 err_errno(IOError);
78 return NULL;
79 }
Guido van Rossumb6775db1994-08-01 11:34:53 +000080 return newfloatobject(secs);
81}
82
83#ifdef HAVE_CLOCK
84
85#ifndef CLOCKS_PER_SEC
Guido van Rossum1b66a4f1996-02-25 04:50:33 +000086#ifdef CLK_TCK
87#define CLOCKS_PER_SEC CLK_TCK
88#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000089#define CLOCKS_PER_SEC 1000000
90#endif
Guido van Rossum1b66a4f1996-02-25 04:50:33 +000091#endif
Guido van Rossumb6775db1994-08-01 11:34:53 +000092
93static object *
94time_clock(self, args)
95 object *self;
96 object *args;
97{
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000098 if (!getnoarg(args))
99 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000100 return newfloatobject(((double)clock()) / CLOCKS_PER_SEC);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000101}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000102#endif /* HAVE_CLOCK */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000103
104static object *
105time_sleep(self, args)
106 object *self;
107 object *args;
108{
Guido van Rossum775f4da1993-01-09 17:18:52 +0000109 double secs;
Guido van Rossum775f4da1993-01-09 17:18:52 +0000110 if (!getargs(args, "d", &secs))
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000111 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000112 BGN_SAVE
Guido van Rossumb6775db1994-08-01 11:34:53 +0000113 if (floatsleep(secs) != 0) {
Guido van Rossumff4949e1992-08-05 19:58:53 +0000114 RET_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000115 return NULL;
116 }
Guido van Rossumff4949e1992-08-05 19:58:53 +0000117 END_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000118 INCREF(None);
119 return None;
120}
121
Guido van Rossum234f9421993-06-17 12:35:49 +0000122static object *
123time_convert(when, function)
124 time_t when;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000125 struct tm * (*function) PROTO((const time_t *));
Guido van Rossum234f9421993-06-17 12:35:49 +0000126{
127 struct tm *p = function(&when);
128 return mkvalue("(iiiiiiiii)",
129 p->tm_year + 1900,
130 p->tm_mon + 1, /* Want January == 1 */
131 p->tm_mday,
132 p->tm_hour,
133 p->tm_min,
134 p->tm_sec,
135 (p->tm_wday + 6) % 7, /* Want Monday == 0 */
Guido van Rossum9e90a671993-06-24 11:10:19 +0000136 p->tm_yday + 1, /* Want January, 1 == 1 */
Guido van Rossum234f9421993-06-17 12:35:49 +0000137 p->tm_isdst);
138}
139
140static object *
141time_gmtime(self, args)
142 object *self;
143 object *args;
144{
145 double when;
146 if (!getargs(args, "d", &when))
147 return NULL;
148 return time_convert((time_t)when, gmtime);
149}
150
151static object *
152time_localtime(self, args)
153 object *self;
154 object *args;
155{
156 double when;
157 if (!getargs(args, "d", &when))
158 return NULL;
159 return time_convert((time_t)when, localtime);
160}
161
Guido van Rossum9e90a671993-06-24 11:10:19 +0000162static int
163gettmarg(args, p)
164 object *args;
165 struct tm *p;
166{
167 if (!getargs(args, "(iiiiiiiii)",
168 &p->tm_year,
169 &p->tm_mon,
170 &p->tm_mday,
171 &p->tm_hour,
172 &p->tm_min,
173 &p->tm_sec,
174 &p->tm_wday,
175 &p->tm_yday,
176 &p->tm_isdst))
177 return 0;
178 if (p->tm_year >= 1900)
179 p->tm_year -= 1900;
180 p->tm_mon--;
181 p->tm_wday = (p->tm_wday + 1) % 7;
182 p->tm_yday--;
183 return 1;
184}
185
Guido van Rossum8d8c1ee1995-09-13 17:38:35 +0000186#ifdef HAVE_STRFTIME
187static object *
188time_strftime(self, args)
189 object *self;
190 object *args;
191{
192 struct tm buf;
193 const char *fmt;
194 char *outbuf = 0;
195 int i;
196
197 if (!PyArg_ParseTuple(args, "s(iiiiiiiii)",
198 &fmt,
199 &(buf.tm_year),
200 &(buf.tm_mon),
201 &(buf.tm_mday),
202 &(buf.tm_hour),
203 &(buf.tm_min),
204 &(buf.tm_sec),
205 &(buf.tm_wday),
206 &(buf.tm_yday),
207 &(buf.tm_isdst)))
208 return NULL;
209 if (buf.tm_year >= 1900)
210 buf.tm_year -= 1900;
211 buf.tm_mon--;
212 buf.tm_wday = (buf.tm_wday + 1) % 7;
213 buf.tm_yday--;
214 /* I hate these functions that presume you know how big the output */
215 /* will be ahead of time... */
216 for (i = 1024 ; i < 8192 ; i += 1024) {
217 outbuf = malloc(i);
218 if (outbuf == NULL) {
219 return err_nomem();
220 }
221 if (strftime(outbuf, i-1, fmt, &buf) != 0) {
222 object *ret;
223 ret = newstringobject(outbuf);
224 free(outbuf);
225 return ret;
226 }
227 free(outbuf);
228 }
229 return err_nomem();
230}
231#endif /* HAVE_STRFTIME */
232
Guido van Rossum9e90a671993-06-24 11:10:19 +0000233static object *
234time_asctime(self, args)
235 object *self;
236 object *args;
237{
238 struct tm buf;
239 char *p;
240 if (!gettmarg(args, &buf))
241 return NULL;
242 p = asctime(&buf);
243 if (p[24] == '\n')
244 p[24] = '\0';
245 return newstringobject(p);
246}
247
248static object *
249time_ctime(self, args)
250 object *self;
251 object *args;
252{
253 double dt;
254 time_t tt;
255 char *p;
256 if (!getargs(args, "d", &dt))
257 return NULL;
258 tt = dt;
259 p = ctime(&tt);
260 if (p[24] == '\n')
261 p[24] = '\0';
262 return newstringobject(p);
263}
264
Guido van Rossum234f9421993-06-17 12:35:49 +0000265static object *
266time_mktime(self, args)
267 object *self;
268 object *args;
269{
270 struct tm buf;
Guido van Rossum9e90a671993-06-24 11:10:19 +0000271 if (!gettmarg(args, &buf))
Guido van Rossum234f9421993-06-17 12:35:49 +0000272 return NULL;
Guido van Rossum234f9421993-06-17 12:35:49 +0000273 return newintobject((long)mktime(&buf));
274}
275
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000276static struct methodlist time_methods[] = {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000277 {"time", time_time},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000278#ifdef HAVE_CLOCK
279 {"clock", time_clock},
280#endif
281 {"sleep", time_sleep},
Guido van Rossum234f9421993-06-17 12:35:49 +0000282 {"gmtime", time_gmtime},
283 {"localtime", time_localtime},
Guido van Rossum9e90a671993-06-24 11:10:19 +0000284 {"asctime", time_asctime},
285 {"ctime", time_ctime},
Guido van Rossum234f9421993-06-17 12:35:49 +0000286 {"mktime", time_mktime},
Guido van Rossum8d8c1ee1995-09-13 17:38:35 +0000287#ifdef HAVE_STRFTIME
Guido van Rossum5416e201996-02-13 00:14:09 +0000288 {"strftime", time_strftime, 1},
Guido van Rossum8d8c1ee1995-09-13 17:38:35 +0000289#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000290 {NULL, NULL} /* sentinel */
291};
292
Guido van Rossum8239f0f1995-01-22 00:49:01 +0000293static void
294ins(d, name, v)
295 object *d;
296 char *name;
297 object *v;
298{
299 if (v == NULL)
300 fatal("Can't initialize time module -- NULL value");
301 if (dictinsert(d, name, v) != 0)
302 fatal("Can't initialize time module -- dictinsert failed");
303 DECREF(v);
304}
305
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000306void
307inittime()
308{
Jack Jansen8ccfc931995-10-03 14:39:44 +0000309 object *m, *d;
Guido van Rossum234f9421993-06-17 12:35:49 +0000310 m = initmodule("time", time_methods);
311 d = getmoduledict(m);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000312#ifdef HAVE_TZNAME
Guido van Rossum234f9421993-06-17 12:35:49 +0000313 tzset();
Guido van Rossum8239f0f1995-01-22 00:49:01 +0000314 ins(d, "timezone", newintobject((long)timezone));
Guido van Rossumb6775db1994-08-01 11:34:53 +0000315#ifdef HAVE_ALTZONE
Guido van Rossum8239f0f1995-01-22 00:49:01 +0000316 ins(d, "altzone", newintobject((long)altzone));
Guido van Rossumb6775db1994-08-01 11:34:53 +0000317#else
Guido van Rossum8239f0f1995-01-22 00:49:01 +0000318 ins(d, "altzone", newintobject((long)timezone-3600));
Guido van Rossumb6775db1994-08-01 11:34:53 +0000319#endif
Guido van Rossum8239f0f1995-01-22 00:49:01 +0000320 ins(d, "daylight", newintobject((long)daylight));
321 ins(d, "tzname", mkvalue("(zz)", tzname[0], tzname[1]));
Guido van Rossumb6775db1994-08-01 11:34:53 +0000322#else /* !HAVE_TZNAME */
323#if HAVE_TM_ZONE
Guido van Rossum234f9421993-06-17 12:35:49 +0000324 {
325#define YEAR ((time_t)((365 * 24 + 6) * 3600))
326 time_t t;
327 struct tm *p;
328 long winterzone, summerzone;
329 char wintername[10], summername[10];
Guido van Rossumb6775db1994-08-01 11:34:53 +0000330 /* XXX This won't work on the southern hemisphere.
331 XXX Anybody got a better idea? */
Guido van Rossum234f9421993-06-17 12:35:49 +0000332 t = (time((time_t *)0) / YEAR) * YEAR;
333 p = localtime(&t);
334 winterzone = -p->tm_gmtoff;
335 strncpy(wintername, p->tm_zone ? p->tm_zone : " ", 9);
336 wintername[9] = '\0';
337 t += YEAR/2;
338 p = localtime(&t);
339 summerzone = -p->tm_gmtoff;
340 strncpy(summername, p->tm_zone ? p->tm_zone : " ", 9);
341 summername[9] = '\0';
Guido van Rossum8239f0f1995-01-22 00:49:01 +0000342 ins(d, "timezone", newintobject(winterzone));
343 ins(d, "altzone", newintobject(summerzone));
344 ins(d, "daylight", newintobject((long)(winterzone != summerzone)));
345 ins(d, "tzname", mkvalue("(zz)", wintername, summername));
Guido van Rossum234f9421993-06-17 12:35:49 +0000346 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000347#endif /* HAVE_TM_ZONE */
348#endif /* !HAVE_TZNAME */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000349}
350
351
Guido van Rossumb6775db1994-08-01 11:34:53 +0000352/* Implement floattime() for various platforms */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000353
Guido van Rossumb6775db1994-08-01 11:34:53 +0000354static double
355floattime()
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000356{
Guido van Rossumb6775db1994-08-01 11:34:53 +0000357 /* There are three ways to get the time:
358 (1) gettimeofday() -- resolution in microseconds
359 (2) ftime() -- resolution in milliseconds
360 (3) time() -- resolution in seconds
361 In all cases the return value is a float in seconds.
362 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
363 fail, so we fall back on ftime() or time().
364 Note: clock resolution does not imply clock accuracy! */
365#ifdef HAVE_GETTIMEOFDAY
366 {
Guido van Rossum426035c1991-02-19 12:27:35 +0000367 struct timeval t;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000368#ifdef GETTIMEOFDAY_NO_TZ
369 if (gettimeofday(&t) == 0)
370 return (double)t.tv_sec + t.tv_usec*0.000001;
371#else /* !GETTIMEOFDAY_NO_TZ */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000372 if (gettimeofday(&t, (struct timezone *)NULL) == 0)
373 return (double)t.tv_sec + t.tv_usec*0.000001;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000374#endif /* !GETTIMEOFDAY_NO_TZ */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000375 }
376#endif /* !HAVE_GETTIMEOFDAY */
377 {
378#ifdef HAVE_FTIME
379 struct timeb t;
380 ftime(&t);
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000381 return (double)t.time + (double)t.millitm * (double)0.001;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000382#else /* !HAVE_FTIME */
383 time_t secs;
384 time(&secs);
385 return (double)secs;
386#endif /* !HAVE_FTIME */
387 }
Guido van Rossum426035c1991-02-19 12:27:35 +0000388}
389
Guido van Rossumb6775db1994-08-01 11:34:53 +0000390
391/* Implement floatsleep() for various platforms.
392 When interrupted (or when another error occurs), return -1 and
393 set an exception; else return 0. */
394
395static int
Guido van Rossuma320fd31995-03-09 12:14:15 +0000396#ifdef MPW
397floatsleep(double secs)
398#else
Guido van Rossum775f4da1993-01-09 17:18:52 +0000399floatsleep(secs)
400 double secs;
Guido van Rossuma320fd31995-03-09 12:14:15 +0000401#endif /* MPW */
Guido van Rossum426035c1991-02-19 12:27:35 +0000402{
Guido van Rossumb6775db1994-08-01 11:34:53 +0000403#ifdef HAVE_SELECT
Guido van Rossum426035c1991-02-19 12:27:35 +0000404 struct timeval t;
Guido van Rossum775f4da1993-01-09 17:18:52 +0000405 double frac;
406 extern double fmod PROTO((double, double));
407 extern double floor PROTO((double));
408 frac = fmod(secs, 1.0);
409 secs = floor(secs);
410 t.tv_sec = (long)secs;
411 t.tv_usec = (long)(frac*1000000.0);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000412 if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) {
413 err_errno(IOError);
414 return -1;
415 }
416#else /* !HAVE_SELECT */
417#ifdef macintosh
418#define MacTicks (* (long *)0x16A)
419 long deadline;
420 deadline = MacTicks + (long)(secs * 60.0);
421 while (MacTicks < deadline) {
422 if (sigcheck())
423 return -1;
424 }
425#else /* !macintosh */
Guido van Rossume22e6441993-07-09 10:51:31 +0000426#ifdef MSDOS
Guido van Rossumb6775db1994-08-01 11:34:53 +0000427 struct timeb t1, t2;
428 double frac;
429 extern double fmod PROTO((double, double));
430 extern double floor PROTO((double));
431 if (secs <= 0.0)
432 return;
433 frac = fmod(secs, 1.0);
434 secs = floor(secs);
435 ftime(&t1);
436 t2.time = t1.time + (int)secs;
437 t2.millitm = t1.millitm + (int)(frac*1000.0);
438 while (t2.millitm >= 1000) {
439 t2.time++;
440 t2.millitm -= 1000;
441 }
442 for (;;) {
443#ifdef QUICKWIN
444 _wyield();
Guido van Rossum80c9d881991-04-16 08:47:51 +0000445#endif
Guido van Rossumb6775db1994-08-01 11:34:53 +0000446 if (sigcheck())
447 return -1;
448 ftime(&t1);
449 if (t1.time > t2.time ||
450 t1.time == t2.time && t1.millitm >= t2.millitm)
451 break;
452 }
453#else /* !MSDOS */
454#ifdef _M_IX86
455 /* XXX Can't interrupt this sleep */
456 Sleep((int)(secs*1000));
457#else /* _M_IX86 */
458 /* XXX Can't interrupt this sleep */
459 sleep((int)secs);
460#endif /* _M_IX86 */
461#endif /* !MSDOS */
462#endif /* !macintosh */
463#endif /* !HAVE_SELECT */
464 return 0;
Guido van Rossum80c9d881991-04-16 08:47:51 +0000465}