[Python-checkins] r80979 - in python/branches/py3k: Doc/library/datetime.rst Lib/test/test_datetime.py Misc/NEWS Modules/datetimemodule.c
mark.dickinson
python-checkins at python.org
Sat May 8 16:35:02 CEST 2010
Author: mark.dickinson
Date: Sat May 8 16:35:02 2010
New Revision: 80979
Log:
Issue #8644: Improve accuracy of timedelta.total_seconds, by doing intermediate
computations with integer arithmetic instead of floating point.
td.total_seconds() now agrees with td / timedelta(seconds = 1).
Thanks Alexander Belopolsky for the patch.
Modified:
python/branches/py3k/Doc/library/datetime.rst
python/branches/py3k/Lib/test/test_datetime.py
python/branches/py3k/Misc/NEWS
python/branches/py3k/Modules/datetimemodule.c
Modified: python/branches/py3k/Doc/library/datetime.rst
==============================================================================
--- python/branches/py3k/Doc/library/datetime.rst (original)
+++ python/branches/py3k/Doc/library/datetime.rst Sat May 8 16:35:02 2010
@@ -287,7 +287,10 @@
.. method:: timedelta.total_seconds()
Return the total number of seconds contained in the duration. Equivalent to
- ``td.microseconds / 1000000 + td.seconds + td.days * 24 * 3600``.
+ ``td / timedelta(seconds=1)``.
+
+ Note that for very large time intervals (greater than 270 years on
+ most platforms) this method will lose microsecond accuracy.
.. versionadded:: 3.2
Modified: python/branches/py3k/Lib/test/test_datetime.py
==============================================================================
--- python/branches/py3k/Lib/test/test_datetime.py (original)
+++ python/branches/py3k/Lib/test/test_datetime.py Sat May 8 16:35:02 2010
@@ -264,6 +264,11 @@
for total_seconds in [123456.789012, -123456.789012, 0.123456, 0, 1e6]:
td = timedelta(seconds=total_seconds)
self.assertEqual(td.total_seconds(), total_seconds)
+ # Issue8644: Test that td.total_seconds() has the same
+ # accuracy as td / timedelta(seconds=1).
+ for ms in [-1, -2, -123]:
+ td = timedelta(microseconds=ms)
+ self.assertEqual(td.total_seconds(), td / timedelta(seconds=1))
def test_carries(self):
t1 = timedelta(days=100,
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Sat May 8 16:35:02 2010
@@ -1105,6 +1105,11 @@
Extension Modules
-----------------
+- Issue #8644: The accuracy of td.total_seconds() has been improved (by
+ calculating with integer arithmetic instead of float arithmetic internally):
+ the result is now always correctly rounded, and is equivalent to td /
+ timedelta(seconds=1).
+
- Issue #2706: Allow division of a timedelta by another timedelta:
timedelta / timedelta, timedelta % timedelta, timedelta // timedelta
and divmod(timedelta, timedelta) are all supported.
Modified: python/branches/py3k/Modules/datetimemodule.c
==============================================================================
--- python/branches/py3k/Modules/datetimemodule.c (original)
+++ python/branches/py3k/Modules/datetimemodule.c Sat May 8 16:35:02 2010
@@ -2211,9 +2211,25 @@
static PyObject *
delta_total_seconds(PyObject *self)
{
- return PyFloat_FromDouble(GET_TD_MICROSECONDS(self) / 1000000.0 +
- GET_TD_SECONDS(self) +
- GET_TD_DAYS(self) * 24.0 * 3600.0);
+ PyObject *total_seconds;
+ PyObject *total_microseconds;
+ PyObject *one_million;
+
+ total_microseconds = delta_to_microseconds((PyDateTime_Delta *)self);
+ if (total_microseconds == NULL)
+ return NULL;
+
+ one_million = PyLong_FromLong(1000000L);
+ if (one_million == NULL) {
+ Py_DECREF(total_microseconds);
+ return NULL;
+ }
+
+ total_seconds = PyNumber_TrueDivide(total_microseconds, one_million);
+
+ Py_DECREF(total_microseconds);
+ Py_DECREF(one_million);
+ return total_seconds;
}
static PyObject *
More information about the Python-checkins
mailing list