You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Python C API中实现时间加减运算?

如何在Python C API中实现时间加减运算?

我太懂这种感受了——网上一搜Python日期运算全是上层代码,C API相关的资料少得可怜。不过别担心,针对你这个需求,我来帮你把代码补全,并且把关键步骤讲清楚:

首先你已经完成了把输入的finishO转换为PyDate对象的部分,这部分逻辑是对的。接下来处理startO未指定的情况,要得到finish前一天的日期,你已经创建了代表1天的PyDelta对象,接下来只需要用Python C API的数值减法接口来完成日期和时间增量的运算,同时还要注意引用计数管理(这可是C API里的经典坑点)。

补全后的完整代码片段如下:

/* Attempt converting the finish-date, if not a date already */
if (!PyDate_Check(finishO)) {
    PyObject *o = PyDate_FromTimestamp(finishO);
    if (o == NULL) {
        return PyErr_Format(PyExc_ValueError, "%R is not a valid date", finishO);
    }
    // 注意:如果finishO是函数传入的借用引用,替换时无需DECREF原对象;
    // 若为自行创建的拥有引用的对象,记得先DECREF再替换
    finishO = o;
}

/* If start-date is not specified, assume one day prior the finish date */
if (startO == NULL) {
    // 创建代表1天的时间增量对象(days, seconds, microseconds)
    PyObject *oneDay = PyDelta_FromDSU(1, 0, 0);
    if (oneDay == NULL) {
        // 处理创建失败的情况,比如内存不足
        return NULL;
    }
    // 用日期减去1天的增量,得到前一天的日期
    startO = PyNumber_Subtract(finishO, oneDay);
    // 释放oneDay的引用,避免内存泄漏
    Py_DECREF(oneDay);
    
    // 检查运算是否成功
    if (startO == NULL) {
        return PyErr_Format(PyExc_ValueError, "Failed to calculate previous day");
    }
}

我来给你划几个重点:

  • PyNumber_Subtract是Python C API中通用的减法接口,它支持PyDatePyDelta之间的运算,和你在Python代码里写finish - timedelta(days=1)是完全等价的。
  • 引用计数一定要盯紧:PyDelta_FromDSU创建的oneDay对象带有一个新的引用,用完之后必须调用Py_DECREF释放,否则会造成内存泄漏。
  • 每一步都要检查返回值是否为NULL,C API里容错性很低,哪怕是看似不会出错的日期运算,也得做好错误处理。

另外,还有一种更直接的方式,如果你只需要加减天数的话,可以用PyDate_AddDays函数,它接受一个PyDate对象和一个整数天数(负数就是往前减),代码会更简洁:

if (startO == NULL) {
    // 直接给日期加-1天,得到前一天的日期
    startO = PyDate_AddDays((PyDateObject *)finishO, -1);
    if (startO == NULL) {
        return PyErr_Format(PyExc_ValueError, "Failed to calculate previous day");
    }
}

这种方式不需要创建PyDelta对象,少了一个引用计数管理的步骤,效率也更高,特别适合这种只加减天数的场景。

内容来源于stack exchange

火山引擎 最新活动