summaryrefslogtreecommitdiffstats
path: root/Modules/datetimemodule.c
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2003-01-02 16:32:54 (GMT)
committerTim Peters <tim.peters@gmail.com>2003-01-02 16:32:54 (GMT)
commit5d644dd25ac3100d0e8bc795ae57a6b8061fefd4 (patch)
treecad48fa944d2b18ca8f6b582dbf70451bb4333b3 /Modules/datetimemodule.c
parente55534665f95a2cf8c866803e847573607d44798 (diff)
downloadcpython-5d644dd25ac3100d0e8bc795ae57a6b8061fefd4.zip
cpython-5d644dd25ac3100d0e8bc795ae57a6b8061fefd4.tar.gz
cpython-5d644dd25ac3100d0e8bc795ae57a6b8061fefd4.tar.bz2
SF bug 661086: datetime.today() truncates microseconds.
On Windows, it was very common to get microsecond values (out of .today() and .now()) of the form 480999, i.e. with three trailing nines. The platform precision is .001 seconds, and fp rounding errors account for the rest. Under the covers, that 480999 started life as the fractional part of a timestamp, like .4809999978. Rounding that times 1e6 cures the irritation. Confession: the platform precision isn't really .001 seconds. It's usually worse. What actually happens is that MS rounds a cruder value to a multiple of .001, and that suffers its own rounding errors. A tiny bit of refactoring added a new internal utility to round doubles.
Diffstat (limited to 'Modules/datetimemodule.c')
-rw-r--r--Modules/datetimemodule.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index 2755f72..a64365a 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -120,6 +120,19 @@ divmod(int x, int y, int *r)
return quo;
}
+/* Round a double to the nearest long. |x| must be small enough to fit
+ * in a C long; this is not checked.
+ */
+static long
+round_to_long(double x)
+{
+ if (x >= 0.0)
+ x = floor(x + 0.5);
+ else
+ x = ceil(x - 0.5);
+ return (long)x;
+}
+
/* ---------------------------------------------------------------------------
* General calendrical helper functions
*/
@@ -1905,12 +1918,7 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
}
if (leftover_us) {
/* Round to nearest whole # of us, and add into x. */
- PyObject *temp;
- if (leftover_us >= 0.0)
- leftover_us = floor(leftover_us + 0.5);
- else
- leftover_us = ceil(leftover_us - 0.5);
- temp = PyLong_FromDouble(leftover_us);
+ PyObject *temp = PyLong_FromLong(round_to_long(leftover_us));
if (temp == NULL) {
Py_DECREF(x);
goto Done;
@@ -2858,7 +2866,8 @@ static PyObject *
datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
{
time_t timet = (time_t)timestamp;
- int us = (int)((timestamp - (double)timet) * 1e6);
+ double fraction = timestamp - (double)timet;
+ int us = (int)round_to_long(fraction * 1e6);
return datetime_from_timet_and_us(cls, f, timet, us);
}