1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
27 #include "allobjects.h"
28 #include "modsupport.h"
34 #include <sys/types.h>
52 #include <sys/timeb.h>
57 #define timezone _timezone
58 #define tzname _tzname
59 #define daylight _daylight
60 #define altzone _altzone
63 /* Forward declarations */
64 static int floatsleep
PROTO((double));
65 static double floattime
PROTO(());
80 return newfloatobject(secs
);
85 #ifndef CLOCKS_PER_SEC
86 #define CLOCKS_PER_SEC 1000000
90 time_clock(self
, args
)
96 return newfloatobject(((double)clock()) / CLOCKS_PER_SEC
);
98 #endif /* HAVE_CLOCK */
101 time_sleep(self
, args
)
106 if (!getargs(args
, "d", &secs
))
109 if (floatsleep(secs
) != 0) {
119 time_convert(when
, function
)
121 struct tm
* (*function
) PROTO((const time_t *));
123 struct tm
*p
= function(&when
);
124 return mkvalue("(iiiiiiiii)",
126 p
->tm_mon
+ 1, /* Want January == 1 */
131 (p
->tm_wday
+ 6) % 7, /* Want Monday == 0 */
132 p
->tm_yday
+ 1, /* Want January, 1 == 1 */
137 time_gmtime(self
, args
)
142 if (!getargs(args
, "d", &when
))
144 return time_convert((time_t)when
, gmtime
);
148 time_localtime(self
, args
)
153 if (!getargs(args
, "d", &when
))
155 return time_convert((time_t)when
, localtime
);
163 if (!getargs(args
, "(iiiiiiiii)",
174 if (p
->tm_year
>= 1900)
177 p
->tm_wday
= (p
->tm_wday
+ 1) % 7;
183 time_asctime(self
, args
)
189 if (!gettmarg(args
, &buf
))
194 return newstringobject(p
);
198 time_ctime(self
, args
)
205 if (!getargs(args
, "d", &dt
))
211 return newstringobject(p
);
215 time_mktime(self
, args
)
220 if (!gettmarg(args
, &buf
))
222 return newintobject((long)mktime(&buf
));
225 static struct methodlist time_methods
[] = {
228 {"clock", time_clock
},
230 {"sleep", time_sleep
},
231 {"gmtime", time_gmtime
},
232 {"localtime", time_localtime
},
233 {"asctime", time_asctime
},
234 {"ctime", time_ctime
},
235 {"mktime", time_mktime
},
236 {NULL
, NULL
} /* sentinel */
246 fatal("Can't initialize time module -- NULL value");
247 if (dictinsert(d
, name
, v
) != 0)
248 fatal("Can't initialize time module -- dictinsert failed");
256 m
= initmodule("time", time_methods
);
257 d
= getmoduledict(m
);
260 ins(d
, "timezone", newintobject((long)timezone
));
262 ins(d
, "altzone", newintobject((long)altzone
));
264 ins(d
, "altzone", newintobject((long)timezone
-3600));
266 ins(d
, "daylight", newintobject((long)daylight
));
267 ins(d
, "tzname", mkvalue("(zz)", tzname
[0], tzname
[1]));
268 #else /* !HAVE_TZNAME */
271 #define YEAR ((time_t)((365 * 24 + 6) * 3600))
274 long winterzone
, summerzone
;
275 char wintername
[10], summername
[10];
276 /* XXX This won't work on the southern hemisphere.
277 XXX Anybody got a better idea? */
278 t
= (time((time_t *)0) / YEAR
) * YEAR
;
280 winterzone
= -p
->tm_gmtoff
;
281 strncpy(wintername
, p
->tm_zone
? p
->tm_zone
: " ", 9);
282 wintername
[9] = '\0';
285 summerzone
= -p
->tm_gmtoff
;
286 strncpy(summername
, p
->tm_zone
? p
->tm_zone
: " ", 9);
287 summername
[9] = '\0';
288 ins(d
, "timezone", newintobject(winterzone
));
289 ins(d
, "altzone", newintobject(summerzone
));
290 ins(d
, "daylight", newintobject((long)(winterzone
!= summerzone
)));
291 ins(d
, "tzname", mkvalue("(zz)", wintername
, summername
));
293 #endif /* HAVE_TM_ZONE */
294 #endif /* !HAVE_TZNAME */
298 /* Implement floattime() for various platforms */
303 /* There are three ways to get the time:
304 (1) gettimeofday() -- resolution in microseconds
305 (2) ftime() -- resolution in milliseconds
306 (3) time() -- resolution in seconds
307 In all cases the return value is a float in seconds.
308 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
309 fail, so we fall back on ftime() or time().
310 Note: clock resolution does not imply clock accuracy! */
311 #ifdef HAVE_GETTIMEOFDAY
314 #ifdef GETTIMEOFDAY_NO_TZ
315 if (gettimeofday(&t
) == 0)
316 return (double)t
.tv_sec
+ t
.tv_usec
*0.000001;
317 #else /* !GETTIMEOFDAY_NO_TZ */
318 if (gettimeofday(&t
, (struct timezone
*)NULL
) == 0)
319 return (double)t
.tv_sec
+ t
.tv_usec
*0.000001;
320 #endif /* !GETTIMEOFDAY_NO_TZ */
322 #endif /* !HAVE_GETTIMEOFDAY */
327 return (double)t
.time
+ (double)t
.millitm
* (double)0.001;
328 #else /* !HAVE_FTIME */
332 #endif /* !HAVE_FTIME */
337 /* Implement floatsleep() for various platforms.
338 When interrupted (or when another error occurs), return -1 and
339 set an exception; else return 0. */
343 floatsleep(double secs
)
352 extern double fmod
PROTO((double, double));
353 extern double floor
PROTO((double));
354 frac
= fmod(secs
, 1.0);
356 t
.tv_sec
= (long)secs
;
357 t
.tv_usec
= (long)(frac
*1000000.0);
358 if (select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
) != 0) {
362 #else /* !HAVE_SELECT */
364 #define MacTicks (* (long *)0x16A)
366 deadline
= MacTicks
+ (long)(secs
* 60.0);
367 while (MacTicks
< deadline
) {
371 #else /* !macintosh */
375 extern double fmod
PROTO((double, double));
376 extern double floor
PROTO((double));
379 frac
= fmod(secs
, 1.0);
382 t2
.time
= t1
.time
+ (int)secs
;
383 t2
.millitm
= t1
.millitm
+ (int)(frac
*1000.0);
384 while (t2
.millitm
>= 1000) {
395 if (t1
.time
> t2
.time
||
396 t1
.time
== t2
.time
&& t1
.millitm
>= t2
.millitm
)
401 /* XXX Can't interrupt this sleep */
402 Sleep((int)(secs
*1000));
404 /* XXX Can't interrupt this sleep */
408 #endif /* !macintosh */
409 #endif /* !HAVE_SELECT */