diff options
author | Alexander Belopolsky <alexander.belopolsky@gmail.com> | 2010-05-31 17:33:47 (GMT) |
---|---|---|
committer | Alexander Belopolsky <alexander.belopolsky@gmail.com> | 2010-05-31 17:33:47 (GMT) |
commit | 1790bc43bf8430b219116f4af0423c3a732c9eb8 (patch) | |
tree | 57771b07db60bebd3fb1d038fb7c5c541f3dcb6e /Modules/datetimemodule.c | |
parent | 9103597ee7e318f5c7183a1b1c97e5322f1f77aa (diff) | |
download | cpython-1790bc43bf8430b219116f4af0423c3a732c9eb8.zip cpython-1790bc43bf8430b219116f4af0423c3a732c9eb8.tar.gz cpython-1790bc43bf8430b219116f4af0423c3a732c9eb8.tar.bz2 |
Issue #1289118: datetime.timedelta objects can now be multiplied by float
and divided by float and int objects.
Diffstat (limited to 'Modules/datetimemodule.c')
-rw-r--r-- | Modules/datetimemodule.c | 113 |
1 files changed, 112 insertions, 1 deletions
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c index 0f6b68f..8d7c5d1 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -152,6 +152,25 @@ round_to_long(double x) return (long)x; } +/* Nearest integer to m / n for integers m and n. Half-integer results + * are rounded to even. + */ +static PyObject * +divide_nearest(PyObject *m, PyObject *n) +{ + PyObject *result; + PyObject *temp; + + temp = _PyLong_Divmod_Near(m, n); + if (temp == NULL) + return NULL; + result = PyTuple_GET_ITEM(temp, 0); + Py_INCREF(result); + Py_DECREF(temp); + + return result; +} + /* --------------------------------------------------------------------------- * General calendrical helper functions */ @@ -1648,6 +1667,37 @@ multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta) } static PyObject * +multiply_float_timedelta(PyObject *floatobj, PyDateTime_Delta *delta) +{ + PyObject *result = NULL; + PyObject *pyus_in = NULL, *temp, *pyus_out; + PyObject *ratio = NULL; + + pyus_in = delta_to_microseconds(delta); + if (pyus_in == NULL) + return NULL; + ratio = PyObject_CallMethod(floatobj, "as_integer_ratio", NULL); + if (ratio == NULL) + goto error; + temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 0)); + Py_DECREF(pyus_in); + pyus_in = NULL; + if (temp == NULL) + goto error; + pyus_out = divide_nearest(temp, PyTuple_GET_ITEM(ratio, 1)); + Py_DECREF(temp); + if (pyus_out == NULL) + goto error; + result = microseconds_to_delta(pyus_out); + Py_DECREF(pyus_out); + error: + Py_XDECREF(pyus_in); + Py_XDECREF(ratio); + + return result; +} + +static PyObject * divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj) { PyObject *pyus_in; @@ -1715,6 +1765,55 @@ truedivide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right) } static PyObject * +truedivide_timedelta_float(PyDateTime_Delta *delta, PyObject *f) +{ + PyObject *result = NULL; + PyObject *pyus_in = NULL, *temp, *pyus_out; + PyObject *ratio = NULL; + + pyus_in = delta_to_microseconds(delta); + if (pyus_in == NULL) + return NULL; + ratio = PyObject_CallMethod(f, "as_integer_ratio", NULL); + if (ratio == NULL) + goto error; + temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 1)); + Py_DECREF(pyus_in); + pyus_in = NULL; + if (temp == NULL) + goto error; + pyus_out = divide_nearest(temp, PyTuple_GET_ITEM(ratio, 0)); + Py_DECREF(temp); + if (pyus_out == NULL) + goto error; + result = microseconds_to_delta(pyus_out); + Py_DECREF(pyus_out); + error: + Py_XDECREF(pyus_in); + Py_XDECREF(ratio); + + return result; +} + +static PyObject * +truedivide_timedelta_int(PyDateTime_Delta *delta, PyObject *i) +{ + PyObject *result; + PyObject *pyus_in, *pyus_out; + pyus_in = delta_to_microseconds(delta); + if (pyus_in == NULL) + return NULL; + pyus_out = divide_nearest(pyus_in, i); + Py_DECREF(pyus_in); + if (pyus_out == NULL) + return NULL; + result = microseconds_to_delta(pyus_out); + Py_DECREF(pyus_out); + + return result; +} + +static PyObject * delta_add(PyObject *left, PyObject *right) { PyObject *result = Py_NotImplemented; @@ -1838,10 +1937,16 @@ delta_multiply(PyObject *left, PyObject *right) if (PyLong_Check(right)) result = multiply_int_timedelta(right, (PyDateTime_Delta *) left); + else if (PyFloat_Check(right)) + result = multiply_float_timedelta(right, + (PyDateTime_Delta *) left); } else if (PyLong_Check(left)) result = multiply_int_timedelta(left, - (PyDateTime_Delta *) right); + (PyDateTime_Delta *) right); + else if (PyFloat_Check(left)) + result = multiply_float_timedelta(left, + (PyDateTime_Delta *) right); if (result == Py_NotImplemented) Py_INCREF(result); @@ -1880,6 +1985,12 @@ delta_truedivide(PyObject *left, PyObject *right) result = truedivide_timedelta_timedelta( (PyDateTime_Delta *)left, (PyDateTime_Delta *)right); + else if (PyFloat_Check(right)) + result = truedivide_timedelta_float( + (PyDateTime_Delta *)left, right); + else if (PyLong_Check(right)) + result = truedivide_timedelta_int( + (PyDateTime_Delta *)left, right); } if (result == Py_NotImplemented) |