[Python-checkins] python/nondist/sandbox/datetime datetime.py,1.82,1.83 doc.txt,1.29,1.30 obj_datetime.c,1.38,1.39

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Sun, 08 Dec 2002 11:02:33 -0800


Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv10604

Modified Files:
	datetime.py doc.txt obj_datetime.c 
Log Message:
Use gettimeofday() for datetime.now() and datetime.utcnow(), on platforms
that have it.  NEEDS TESTING!  Windows doesn't have this function, so I
haven't even compiled the new code.  Somebody please try this on Linux.


Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.82
retrieving revision 1.83
diff -C2 -d -r1.82 -r1.83
*** datetime.py	7 Dec 2002 21:06:38 -0000	1.82
--- datetime.py	8 Dec 2002 19:02:29 -0000	1.83
***************
*** 1112,1115 ****
--- 1112,1120 ----
      fromtimestamp = classmethod(fromtimestamp)
  
+     # XXX This is supposed to do better than we *can* do by using time.time(),
+     # XXX if the platform supports a more accurate way.  The C implementation
+     # XXX uses gettimeofday on platforms that have it, but that isn't
+     # XXX available from Python.  So now() may return different results
+     # XXX across the implementations.
      def now(cls):
          "Construct a datetime from time.time()."

Index: doc.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/doc.txt,v
retrieving revision 1.29
retrieving revision 1.30
diff -C2 -d -r1.29 -r1.30
*** doc.txt	7 Dec 2002 21:06:38 -0000	1.29
--- doc.txt	8 Dec 2002 19:02:30 -0000	1.30
***************
*** 362,367 ****
      Return the current local datetime.  This is like today(), but, if
      possible, supplies more precision than can be gotten from going
!     through a time.time() timestamp.
!     XXX It currently doesn't.  To the contrary, it's currently worse.
      See also today(), utcnow().
  
--- 362,367 ----
      Return the current local datetime.  This is like today(), but, if
      possible, supplies more precision than can be gotten from going
!     through a time.time() timestamp (for example, this may be possible
!     on platforms that supply the C gettimeofday() function).
      See also today(), utcnow().
  

Index: obj_datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_datetime.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -C2 -d -r1.38 -r1.39
*** obj_datetime.c	7 Dec 2002 22:29:45 -0000	1.38
--- obj_datetime.c	8 Dec 2002 19:02:31 -0000	1.39
***************
*** 104,113 ****
  typedef struct tm *(*TM_FUNC)(const time_t *timer);
  
  static PyObject *
! datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
  {
  	struct tm *tm;
- 	time_t timet = (time_t)timestamp;
- 	long us = (long)((timestamp - (double)timet) * 1e6);
  	PyObject *result = NULL;
  
--- 104,115 ----
  typedef struct tm *(*TM_FUNC)(const time_t *timer);
  
+ /* Internal helper.
+  * Build datetime from a time_t and a distinct count of microseconds.
+  * Pass localtime or gmtime for f, to control the interpretation of timet.
+  */
  static PyObject *
! datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, long us)
  {
  	struct tm *tm;
  	PyObject *result = NULL;
  
***************
*** 129,132 ****
--- 131,195 ----
  }
  
+ /* Internal helper.
+  * Build datetime from a Python timestamp.  Pass localtime or gmtime for f,
+  * to control the interpretation of the timestamp.  Since a double doesn't
+  * have enough bits to cover a datetime's full range of precision, it's
+  * better to call datetime_from_timet_and_us provided you have a way
+  * to get that much precision (e.g., C time() isn't good enough).
+  */
+ static PyObject *
+ datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
+ {
+ 	time_t timet = (time_t)timestamp;
+ 	long us = (long)((timestamp - (double)timet) * 1e6);
+ 
+ 	return datetime_from_timet_and_us(cls, f, timet, us);
+ }
+ 
+ /* Internal helper.
+  * Build most accurate possible datetime for current time.  Pass localtime or
+  * gmtime for f as appropriate.
+  */
+ static PyObject *
+ datetime_best_possible(PyObject *cls, TM_FUNC f)
+ {
+ #ifdef HAVE_GETTIMEOFDAY
+ 	struct timeval t;
+ 
+ #ifdef GETTIMEOFDAY_NO_TZ
+ 	gettimeofday(&t);
+ #else
+ 	gettimeofday(&t, (struct timezone *)NULL);
+ #endif
+ 	return datetime_from_timet_and_us(cls, f, t.tv_sec, t.tv_usec);
+ 
+ #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_time;	/* time.time() */
+ 	double dtime;
+ 	PyObject *time = PyImport_ImportModule("time");
+ 
+ 	if (time == NULL)
+ 		return NULL;
+ 
+ 	time_time = PyObject_CallMethod(time, "time", "()");
+ 	Py_DECREF(time);
+     	if (time_time == NULL)
+     		return NULL;
+ 
+ 	dtime = PyFloat_AsDouble(time_time);
+ 	Py_DECREF(time_time);
+ 	if (dtime == -1.0 && PyErr_Occurred())
+ 		return NULL;
+ 	return datetime_from_timestamp(cls, f, dtime);
+ #endif	/* ! HAVE_GETTIMEOFDAY */
+ }
+ 
  /* Return new local datetime from timestamp (Python timestamp -- a double). */
  static PyObject *
***************
*** 155,199 ****
  }
  
  static PyObject *
  datetime_now(PyObject *self, PyObject *cls)
  {
! 	/* XXX MAJOR:  This needs to get some notion of current time
! 	 * XXX to better than 1-second resolution.  Doing this in a x-
! 	 * XXX platform way is mondo painful.  Maybe floattime() from
! 	 * XXX timemodule.c is good enough?  We're running out of bits
! 	 * XXX in a typical time_t, though, and gettimeofday() should do
! 	 * XXX better than floattime() -- but gettimeofday isn't portable.
! 	 */
! #if 0
! 	/* XXX need to create the instance by calling cls(y,mon,d,h,min,s,u) */
! 	struct timeval t;
! 	struct tm *tm;
! 	time_t timet;
! 
! #ifdef GETTIMEOFDAY_NO_TZ
! 	gettimeofday(&t);
! #else /* !GETTIMEOFDAY_NO_TZ */
! 	gettimeofday(&t, (struct timezone *)NULL);
! #endif /* !GETTIMEOFDAY_NO_TZ */
! 	timet = t.tv_sec;
! 	tm = localtime(&timet);
! 
! 	return PyObject_CallFunction(cls, "iiiiiil",
! 				     tm->tm_year + 1900, tm->tm_mon + 1,
! 				     tm->tm_mday, tm->tm_hour, tm->tm_min,
! 				     tm->tm_sec, t.tv_usec);
! #else
! 	/* XXX need to create the instance by calling cls(y,mon,d,h,min,s,u) */
! 	struct tm *tm;
! 	time_t timet;
! 
!  	time(&timet);
! 	tm = localtime(&timet);
  
! 	return PyObject_CallFunction(cls, "iiiiii",
! 				     tm->tm_year + 1900, tm->tm_mon + 1,
! 				     tm->tm_mday, tm->tm_hour, tm->tm_min,
! 				     tm->tm_sec);
! #endif
  }
  
--- 218,237 ----
  }
  
+ /* Return best possible local time -- this isn't constrained by the
+  * precision of a timestamp.
+  */
  static PyObject *
  datetime_now(PyObject *self, PyObject *cls)
  {
! 	return datetime_best_possible(cls, localtime);
! }
  
! /* Return best possible UTC time -- this isn't constrained by the
!  * precision of a timestamp.
!  */
! static PyObject *
! datetime_utcnow(PyObject *self, PyObject *cls)
! {
! 	return datetime_best_possible(cls, gmtime);
  }
  
***************
*** 226,247 ****
  				    		TIME_GET_MICROSECOND(time));
  	return result;
- }
- 
- static PyObject *
- datetime_utcnow(PyObject *self, PyObject *cls)
- {
- 	/* XXX Like datetime_now, this would like to do better than
- 	 * XXX 1-second resolution.
- 	 */
- 	struct tm *tm;
- 	time_t timet;
- 
-  	time(&timet);
- 	tm = gmtime(&timet);
- 
- 	return PyObject_CallFunction(cls, "iiiiii",
- 				     tm->tm_year + 1900, tm->tm_mon + 1,
- 				     tm->tm_mday, tm->tm_hour, tm->tm_min,
- 				     tm->tm_sec);
  }
  
--- 264,267 ----