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