Index: Python/pytime.c =================================================================== --- Python/pytime.c (revision 0) +++ Python/pytime.c (revision 0) @@ -0,0 +1,54 @@ +#include "Python.h" + +#ifdef __APPLE__ +#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) + /* + * _PyTime_gettimeofday falls back to ftime when getttimeofday fails because the latter + * might fail on some platforms. This fallback is unwanted on MacOSX because + * that makes it impossible to use a binary build on OSX 10.4 on earlier + * releases of the OS. Therefore claim we don't support ftime. + */ +# undef HAVE_FTIME +#endif +#endif + +#ifdef HAVE_FTIME +#include +#if !defined(MS_WINDOWS) && !defined(PYOS_OS2) +extern int ftime(struct timeb *); +#endif /* MS_WINDOWS */ +#endif /* HAVE_FTIME */ + +void +_PyTime_gettimeofday(struct timeval *tp) +{ + /* There are three ways to get the time: + (1) gettimeofday() -- resolution in microseconds + (2) ftime() -- resolution in milliseconds + (3) time() -- resolution in seconds + In all cases the return value in a timeval struct. + Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may + fail, so we fall back on ftime() or time(). + Note: clock resolution does not imply clock accuracy! */ +#ifdef HAVE_GETTIMEOFDAY +#ifdef GETTIMEOFDAY_NO_TZ + if (gettimeofday(tp) == 0) + return; +#else /* !GETTIMEOFDAY_NO_TZ */ + if (gettimeofday(tp, (struct timezone *)NULL) == 0) + return; +#endif /* !GETTIMEOFDAY_NO_TZ */ +#endif /* !HAVE_GETTIMEOFDAY */ +#if defined(HAVE_FTIME) + { + struct timeb t; + ftime(&t); + tp->tv_sec = t.time; + tp->tv_usec = t.millitm * 1000; + } +#else /* !HAVE_FTIME */ + tp->tv_sec = time(NULL); + tp->tv_usec = 0; +#endif /* !HAVE_FTIME */ + return; +} Index: Include/Python.h =================================================================== --- Include/Python.h (revision 82921) +++ Include/Python.h (working copy) @@ -61,6 +61,7 @@ #error "PYMALLOC_DEBUG requires WITH_PYMALLOC" #endif #include "pymath.h" +#include "pytime.h" #include "pymem.h" #include "object.h" Index: Include/pytime.h =================================================================== --- Include/pytime.h (revision 0) +++ Include/pytime.h (revision 0) @@ -0,0 +1,30 @@ +#ifndef Py_PYTIME_H +#define Py_PYTIME_H + +#include "pyconfig.h" /* include for defines */ + +/************************************************************************** +Symbols and macros to supply platform-independent interfaces to time related +functions and constants +**************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HAVE_GETTIMEOFDAY +struct timeval { + time_t tv_sec; /* seconds since Jan. 1, 1970 */ + long tv_usec; /* and microseconds */ +}; +#endif + +/* Similar to POSIX gettimeofday but cannot fail. If system gettimeofday + * fails or is not available, fall back to lower resolution clocks. + */ +PyAPI_FUNC(void) _PyTime_gettimeofday(struct timeval *tp); + +#ifdef __cplusplus +} +#endif + +#endif /* Py_PYTIME_H */ Index: Doc/library/datetime.rst =================================================================== --- Doc/library/datetime.rst (revision 82921) +++ Doc/library/datetime.rst (working copy) @@ -649,9 +649,10 @@ .. classmethod:: datetime.today() - Return the current local datetime, with :attr:`tzinfo` ``None``. This is - equivalent to ``datetime.fromtimestamp(time.time())``. See also :meth:`now`, - :meth:`fromtimestamp`. + Return the current local datetime, with :attr:`tzinfo` + ``None``. This is equivalent to + ``datetime.fromtimestamp(time.gettimeofday()[0])``. See also + :meth:`now`, :meth:`fromtimestamp`. .. classmethod:: datetime.now(tz=None) Index: Doc/library/time.rst =================================================================== --- Doc/library/time.rst (revision 82921) +++ Doc/library/time.rst (working copy) @@ -397,14 +397,19 @@ .. function:: time() - Return the time as a floating point number expressed in seconds since the epoch, - in UTC. Note that even though the time is always returned as a floating point - number, not all systems provide time with a better precision than 1 second. - While this function normally returns non-decreasing values, it can return a - lower value than a previous call if the system clock has been set back between - the two calls. + Return the time as a floating point number expressed in seconds + since the epoch. Note that even though the time is always returned + as a floating point number, not all systems provide time with a + better precision than 1 second. While this function normally + returns non-decreasing values, it can return a lower value than a + previous call if the system clock has been set back between the two + calls. +.. function:: gettimeofday() + Similar to :func:`time`, but returns the time as a tuple two + integers representing seconds and microseconds since the epoch. + .. data:: timezone The offset of the local (non-DST) timezone, in seconds west of UTC (negative in Index: Lib/test/test_time.py =================================================================== --- Lib/test/test_time.py (revision 82921) +++ Lib/test/test_time.py (working copy) @@ -17,6 +17,13 @@ def test_clock(self): time.clock() + def test_gettimeofday(self): + sec, usec = time.gettimeofday() + self.assertIs(type(sec), int) + self.assertIs(type(usec), int) + self.assertLess(usec, 1000000) + self.assertGreaterEqual(usec, 0) + def test_conversions(self): self.assertTrue(time.ctime(self.t) == time.asctime(time.localtime(self.t))) Index: Makefile.pre.in =================================================================== --- Makefile.pre.in (revision 82921) +++ Makefile.pre.in (working copy) @@ -314,6 +314,7 @@ Python/pymath.o \ Python/pystate.o \ Python/pythonrun.o \ + Python/pytime.o \ Python/structmember.o \ Python/symtable.o \ Python/sysmodule.o \ @@ -698,6 +699,7 @@ Include/pystrtod.h \ Include/pythonrun.h \ Include/pythread.h \ + Include/pytime.h \ Include/rangeobject.h \ Include/setobject.h \ Include/sliceobject.h \ Index: Modules/datetimemodule.c =================================================================== --- Modules/datetimemodule.c (revision 82921) +++ Modules/datetimemodule.c (working copy) @@ -8,7 +8,7 @@ #include -#include "timefuncs.h" +#include "_time.h" /* Differentiate between building the core module and building extension * modules. @@ -1329,20 +1329,6 @@ * from C. Perhaps they should be. */ -/* Call time.time() and return its result (a Python float). */ -static PyObject * -time_time(void) -{ - PyObject *result = NULL; - PyObject *time = PyImport_ImportModuleNoBlock("time"); - - if (time != NULL) { - result = PyObject_CallMethod(time, "time", "()"); - Py_DECREF(time); - } - return result; -} - /* Build a time.struct_time. The weekday and day number are automatically * computed from the y,m,d args. */ @@ -2458,15 +2444,11 @@ /* Return new date from localtime(t). */ static PyObject * -date_local_from_time_t(PyObject *cls, double ts) +date_local_from_time_t(PyObject *cls, time_t t) { struct tm *tm; - time_t t; PyObject *result = NULL; - t = _PyTime_DoubleToTimet(ts); - if (t == (time_t)-1 && PyErr_Occurred()) - return NULL; tm = localtime(&t); if (tm) result = PyObject_CallFunction(cls, "iii", @@ -2481,29 +2463,13 @@ } /* Return new date from current time. - * We say this is equivalent to fromtimestamp(time.time()), and the - * only way to be sure of that is to *call* time.time(). That's not - * generally the same as calling C's time. */ static PyObject * date_today(PyObject *cls, PyObject *dummy) { - PyObject *time; - PyObject *result; - - time = time_time(); - if (time == NULL) - return NULL; - - /* Note well: today() is a class method, so this may not call - * date.fromtimestamp. For example, it may call - * datetime.fromtimestamp. That's why we need all the accuracy - * time.time() delivers; if someone were gonzo about optimization, - * date.today() could get away with plain C time(). - */ - result = PyObject_CallMethod(cls, "fromtimestamp", "O", time); - Py_DECREF(time); - return result; + struct timeval tv; + _PyTime_gettimeofday(&tv); + return date_local_from_time_t(cls, tv.tv_sec); } /* Return new date from given timestamp (Python timestamp -- a double). */ @@ -4166,37 +4132,10 @@ static PyObject * datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo) { -#ifdef HAVE_GETTIMEOFDAY struct timeval t; - -#ifdef GETTIMEOFDAY_NO_TZ - gettimeofday(&t); -#else - gettimeofday(&t, (struct timezone *)NULL); -#endif + _PyTime_gettimeofday(&t); return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec, tzinfo); - -#else /* ! HAVE_GETTIMEOFDAY */ - /* No flavor of gettimeofday exists on this platform. Python's - * time.time() does a lot of other platform tricks to get the - * best time it can on the platform, and we're not going to do - * better than that (if we could, the better code would belong - * in time.time()!) We're limited by the precision of a double, - * though. - */ - PyObject *time; - double dtime; - - time = time_time(); - if (time == NULL) - return NULL; - dtime = PyFloat_AsDouble(time); - Py_DECREF(time); - if (dtime == -1.0 && PyErr_Occurred()) - return NULL; - return datetime_from_timestamp(cls, f, dtime, tzinfo); -#endif /* ! HAVE_GETTIMEOFDAY */ } /* Return best possible local time -- this isn't constrained by the Index: Modules/timemodule.c =================================================================== --- Modules/timemodule.c (revision 82921) +++ Modules/timemodule.c (working copy) @@ -3,22 +3,10 @@ #include "Python.h" #include "structseq.h" -#include "timefuncs.h" +#include "_time.h" #define TZNAME_ENCODING "utf-8" -#ifdef __APPLE__ -#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) - /* - * floattime falls back to ftime when getttimeofday fails because the latter - * might fail on some platforms. This fallback is unwanted on MacOSX because - * that makes it impossible to use a binary build on OSX 10.4 on earlier - * releases of the OS. Therefore claim we don't support ftime. - */ -# undef HAVE_FTIME -#endif -#endif - #include #ifdef HAVE_SYS_TYPES_H @@ -29,13 +17,6 @@ #include #endif -#ifdef HAVE_FTIME -#include -#if !defined(MS_WINDOWS) && !defined(PYOS_OS2) -extern int ftime(struct timeb *); -#endif /* MS_WINDOWS */ -#endif /* HAVE_FTIME */ - #if defined(__WATCOMC__) && !defined(__QNX__) #include #else @@ -108,6 +89,27 @@ Return the current time in seconds since the Epoch.\n\ Fractions of a second may be present if the system clock provides them."); +static PyObject * +time_gettimeofday(PyObject *self, PyObject *unused) +{ + struct timeval tv; +/* XXX: Let's hope that if we don't have long long time_t fits in long. */ +#ifdef HAVE_LONG_LONG +#define TVCAST (PY_LONG_LONG) +#define TVTUPLE "(LL)" +#else +#define TVCAST (long) +#define TVTUPLE "(ll)" +#endif + _PyTime_gettimeofday(&tv); + return Py_BuildValue(TVTUPLE, TVCAST tv.tv_sec, TVCAST tv.tv_usec); +} + +PyDoc_STRVAR(gettimeofday_doc, +"gettimeofday() -> (sec, usec)\n\ +\n\ +Return the current time in seconds and microseconds since the Epoch."); + #ifdef HAVE_CLOCK #ifndef CLOCKS_PER_SEC @@ -827,6 +829,7 @@ static PyMethodDef time_methods[] = { {"time", time_time, METH_NOARGS, time_doc}, + {"gettimeofday", time_gettimeofday, METH_NOARGS, gettimeofday_doc}, #ifdef HAVE_CLOCK {"clock", time_clock, METH_NOARGS, clock_doc}, #endif @@ -946,44 +949,12 @@ return m; } - -/* Implement floattime() for various platforms */ - static double floattime(void) { - /* There are three ways to get the time: - (1) gettimeofday() -- resolution in microseconds - (2) ftime() -- resolution in milliseconds - (3) time() -- resolution in seconds - In all cases the return value is a float in seconds. - Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may - fail, so we fall back on ftime() or time(). - Note: clock resolution does not imply clock accuracy! */ -#ifdef HAVE_GETTIMEOFDAY - { - struct timeval t; -#ifdef GETTIMEOFDAY_NO_TZ - if (gettimeofday(&t) == 0) - return (double)t.tv_sec + t.tv_usec*0.000001; -#else /* !GETTIMEOFDAY_NO_TZ */ - if (gettimeofday(&t, (struct timezone *)NULL) == 0) - return (double)t.tv_sec + t.tv_usec*0.000001; -#endif /* !GETTIMEOFDAY_NO_TZ */ - } - -#endif /* !HAVE_GETTIMEOFDAY */ - { -#if defined(HAVE_FTIME) - struct timeb t; - ftime(&t); - return (double)t.time + (double)t.millitm * (double)0.001; -#else /* !HAVE_FTIME */ - time_t secs; - time(&secs); - return (double)secs; -#endif /* !HAVE_FTIME */ - } + struct timeval t; + _PyTime_gettimeofday(&t); + return (double)t.tv_sec + t.tv_usec*0.000001; }