There are many tutorials and examples out there on how to perform date-arithmetic from Python. But I cannot find anything for the Python C API...
My C function, callable from Python, operates on two dates: start
and finish
. If start
is not explicitly specified, it must be understood as one day before the finish
.
How do I do this?
/* Attempt converting the finish-date, if not a date already */
if (!PyDate_Check(finishO)) {
o = PyDate_FromTimestamp(finishO);
if (o == NULL)
return PyErr_Format(PyExc_ValueError,
"%R is not a valid date", finishO);
finishO = o;
}
/* If start-date is not specified, assume one day prior the finish date */
if (startO == NULL) {
PyObject *oneDay = PyDelta_FromDSU(1, 0, 0);
/* Derive startO from finishO by applying the one-day delta somehow */
}
Once you have the timedelta
object returned from PyDelta_FromDSU
, use the PyNumber
API to compute the offset.
Functional Windows example below. I didn't write a whole Python C module, just the demonstration function called from ctypes
:
test.c - compiled with MSVC: cl /LD /W4 /Ic:\python313\include test.c -link /libpath:c:\python313\libs
#include <Python.h>
#include <datetime.h> // PyDateTime not included in Python.h
__declspec(dllexport)
PyObject* func(PyObject* start, PyObject* finish) {
PyDateTime_IMPORT; // required initialization
if(start == Py_None) {
PyObject *oneDay = PyDelta_FromDSU(1, 0, 0);
start = PyNumber_Subtract(finish, oneDay);
Py_XDECREF(oneDay);
}
return start;
}
test.py
import datetime as dt
import ctypes as ct
dll = ct.PyDLL('./test')
func = dll.func
func.argtypes = ct.py_object, ct.py_object
func.restype = ct.py_object
start = dt.datetime(2025, 8, 14)
finish = dt.datetime(2025, 8, 14, 1)
print(f'start = {start}')
print(f'finish = {finish}')
print(func(start, finish)) # returns start
print(func(None, finish)) # returns 1 day before finish
Output:
start = 2025-08-14 00:00:00
finish = 2025-08-14 01:00:00
2025-08-14 00:00:00
2025-08-13 01:00:00