summaryrefslogtreecommitdiffstats
path: root/Modules/datetimemodule.c
diff options
context:
space:
mode:
authorAlexander Belopolsky <alexander.belopolsky@gmail.com>2010-05-31 17:33:47 (GMT)
committerAlexander Belopolsky <alexander.belopolsky@gmail.com>2010-05-31 17:33:47 (GMT)
commit1790bc43bf8430b219116f4af0423c3a732c9eb8 (patch)
tree57771b07db60bebd3fb1d038fb7c5c541f3dcb6e /Modules/datetimemodule.c
parent9103597ee7e318f5c7183a1b1c97e5322f1f77aa (diff)
downloadcpython-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.c113
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)