summaryrefslogtreecommitdiffstats
path: root/Modules/datetimemodule.c
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2010-04-20 22:32:49 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2010-04-20 22:32:49 (GMT)
commit7c186e2a18bf174afd5cccc8c35b7167d05f7e2a (patch)
tree1ba75e9cb85d4ab1e0320d3636c1db90d5c8f97e /Modules/datetimemodule.c
parent50eb60e6bfedbdad2dda30fa5ce7fe3ce83f7748 (diff)
downloadcpython-7c186e2a18bf174afd5cccc8c35b7167d05f7e2a.zip
cpython-7c186e2a18bf174afd5cccc8c35b7167d05f7e2a.tar.gz
cpython-7c186e2a18bf174afd5cccc8c35b7167d05f7e2a.tar.bz2
Issue #2706: Add support for dividing a timedelta by another timedelta.
Adds support for the three division operations: - timedelta / timedelta -> float - timedelta // timedelta -> int - timedelta % timedelta -> timedelta also adds support for divmod(timedelta, timedelta). Patch by Victor Stinner, adapted for py3k and extended by Alexander Belopolsky.
Diffstat (limited to 'Modules/datetimemodule.c')
-rw-r--r--Modules/datetimemodule.c150
1 files changed, 147 insertions, 3 deletions
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index c6efee0..2896486 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -1666,6 +1666,52 @@ divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
}
static PyObject *
+divide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right)
+{
+ PyObject *pyus_left;
+ PyObject *pyus_right;
+ PyObject *result;
+
+ pyus_left = delta_to_microseconds(left);
+ if (pyus_left == NULL)
+ return NULL;
+
+ pyus_right = delta_to_microseconds(right);
+ if (pyus_right == NULL) {
+ Py_DECREF(pyus_left);
+ return NULL;
+ }
+
+ result = PyNumber_FloorDivide(pyus_left, pyus_right);
+ Py_DECREF(pyus_left);
+ Py_DECREF(pyus_right);
+ return result;
+}
+
+static PyObject *
+truedivide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right)
+{
+ PyObject *pyus_left;
+ PyObject *pyus_right;
+ PyObject *result;
+
+ pyus_left = delta_to_microseconds(left);
+ if (pyus_left == NULL)
+ return NULL;
+
+ pyus_right = delta_to_microseconds(right);
+ if (pyus_right == NULL) {
+ Py_DECREF(pyus_left);
+ return NULL;
+ }
+
+ result = PyNumber_TrueDivide(pyus_left, pyus_right);
+ Py_DECREF(pyus_left);
+ Py_DECREF(pyus_right);
+ return result;
+}
+
+static PyObject *
delta_add(PyObject *left, PyObject *right)
{
PyObject *result = Py_NotImplemented;
@@ -1810,6 +1856,27 @@ delta_divide(PyObject *left, PyObject *right)
result = divide_timedelta_int(
(PyDateTime_Delta *)left,
right);
+ else if (PyDelta_Check(right))
+ result = divide_timedelta_timedelta(
+ (PyDateTime_Delta *)left,
+ (PyDateTime_Delta *)right);
+ }
+
+ if (result == Py_NotImplemented)
+ Py_INCREF(result);
+ return result;
+}
+
+static PyObject *
+delta_truedivide(PyObject *left, PyObject *right)
+{
+ PyObject *result = Py_NotImplemented;
+
+ if (PyDelta_Check(left)) {
+ if (PyDelta_Check(right))
+ result = truedivide_timedelta_timedelta(
+ (PyDateTime_Delta *)left,
+ (PyDateTime_Delta *)right);
}
if (result == Py_NotImplemented)
@@ -1817,6 +1884,83 @@ delta_divide(PyObject *left, PyObject *right)
return result;
}
+static PyObject *
+delta_remainder(PyObject *left, PyObject *right)
+{
+ PyObject *pyus_left;
+ PyObject *pyus_right;
+ PyObject *pyus_remainder;
+ PyObject *remainder;
+
+ if (!PyDelta_Check(left) || !PyDelta_Check(right)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ pyus_left = delta_to_microseconds((PyDateTime_Delta *)left);
+ if (pyus_left == NULL)
+ return NULL;
+
+ pyus_right = delta_to_microseconds((PyDateTime_Delta *)right);
+ if (pyus_right == NULL) {
+ Py_DECREF(pyus_left);
+ return NULL;
+ }
+
+ pyus_remainder = PyNumber_Remainder(pyus_left, pyus_right);
+ Py_DECREF(pyus_left);
+ Py_DECREF(pyus_right);
+ if (pyus_remainder == NULL)
+ return NULL;
+
+ remainder = microseconds_to_delta(pyus_remainder);
+ if (remainder == NULL) {
+ Py_DECREF(divmod);
+ return NULL;
+ }
+
+ return remainder;
+}
+
+static PyObject *
+delta_divmod(PyObject *left, PyObject *right)
+{
+ PyObject *pyus_left;
+ PyObject *pyus_right;
+ PyObject *divmod;
+ PyObject *microseconds, *delta;
+
+ if (!PyDelta_Check(left) || !PyDelta_Check(right)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ pyus_left = delta_to_microseconds((PyDateTime_Delta *)left);
+ if (pyus_left == NULL)
+ return NULL;
+
+ pyus_right = delta_to_microseconds((PyDateTime_Delta *)right);
+ if (pyus_right == NULL) {
+ Py_DECREF(pyus_left);
+ return NULL;
+ }
+
+ divmod = PyNumber_Divmod(pyus_left, pyus_right);
+ Py_DECREF(pyus_left);
+ Py_DECREF(pyus_right);
+ if (divmod == NULL)
+ return NULL;
+
+ microseconds = PyTuple_GetItem(divmod, 1);
+ delta = microseconds_to_delta(microseconds);
+ if (delta == NULL) {
+ Py_DECREF(divmod);
+ return NULL;
+ }
+ PyTuple_SetItem(divmod, 1, delta);
+ return divmod;
+}
+
/* Fold in the value of the tag ("seconds", "weeks", etc) component of a
* timedelta constructor. sofar is the # of microseconds accounted for
* so far, and there are factor microseconds per current unit, the number
@@ -2108,8 +2252,8 @@ static PyNumberMethods delta_as_number = {
delta_add, /* nb_add */
delta_subtract, /* nb_subtract */
delta_multiply, /* nb_multiply */
- 0, /* nb_remainder */
- 0, /* nb_divmod */
+ delta_remainder, /* nb_remainder */
+ delta_divmod, /* nb_divmod */
0, /* nb_power */
(unaryfunc)delta_negative, /* nb_negative */
(unaryfunc)delta_positive, /* nb_positive */
@@ -2135,7 +2279,7 @@ static PyNumberMethods delta_as_number = {
0, /*nb_inplace_xor*/
0, /*nb_inplace_or*/
delta_divide, /* nb_floor_divide */
- 0, /* nb_true_divide */
+ delta_truedivide, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
};