You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用datetime.timedelta生成预算重复日期CSV并修正日期偏移

问题原因

pandas 周期频率默认带固定锚点规则,和自定义起始日期冲突是日期偏移的核心原因:

  • W(周频)默认锚定每周日,传入2022-06-03(周五)作为起始点时,pandas会自动选取时间范围内第一个周日(2022-06-05)作为首条记录日期
  • M(月频)默认锚定每月最后一天,Q(季频)默认锚定每季度最后一天,同理不会以传入的自定义日期作为首个周期节点

不需要硬写循环套datetime.timedelta算日期,pandas原生支持固定间隔频率和自定义偏移,少量修改代码即可解决问题。

优化方案

1. 修改CashFlow类的频率映射逻辑

修改cashflow.py中的generate_series方法,替换默认带锚点的频率为固定间隔规则,原有业务调用逻辑不需要改动:

import datetime
import pandas as pd
import csv
import os


class CashFlow(object):

    def __init__(self, name='cashflow'):
        self.name = name
        self.columns = ['date_of_activity', 'description', 'amount']
        self.series = pd.DataFrame(columns=self.columns)

    def generate_series(self, description, amount, frequency='MS',
                        start=datetime.date(datetime.date.today().year, 1, 1),
                        end=datetime.date(datetime.date.today().year, 12, 31)):
        """Generate a new data series and append it to the existing data"""
        # 替换默认带锚点的频率为固定间隔规则,对齐自定义起始日
        freq_mapping = {
            'W': '7D',  # 周度改为从起始日开始每7天一笔,不对齐周日
            'M': pd.DateOffset(months=1),  # 月度改为从起始日开始每1个月一笔
            'Q': pd.DateOffset(months=3)   # 季度改为从起始日开始每3个月一笔
        }
        # 已定义的特殊频率走映射,其余频率(如日频'D'、月初'MS')保留原有逻辑
        actual_freq = freq_mapping.get(frequency, frequency)
        data = [(date_of_activity, description, amount)
                for date_of_activity in pd.date_range(start, end, freq=actual_freq)]
        self.series = pd.concat(
            [self.series, pd.DataFrame(data, columns=self.columns)])

    def add_event(self, description, amount, date_of_activity):
        """Add a single event"""
        self.generate_series(description, amount, frequency='D',
                             start=date_of_activity, end=date_of_activity),

    def export_to_csv(self, dirpath, filename):
        """ Export the data to a csv file."""
        """ Sort data by 1) date_of_activity ascending and 2) amount ascending before the export."""

        path = os.path.join(dirpath, filename)
        with open(path, 'w') as csvfile:
            csv_writer = csv.writer(csvfile, delimiter=',')
            csv_writer.writerow(self.columns)
            self.series.sort_values(by=['date_of_activity', 'amount'], ascending=[
                                    True, True], inplace=True)
            for index, record in self.series.iterrows():
                csv_writer.writerow(record)

2. (可选)使用datetime.timedelta实现自定义间隔

如果需要设置非标准周期(比如每10天一笔、每20天一笔的收支),可以直接传入datetime.timedelta对象作为frequency参数,pd.date_range原生支持该类型参数,示例:

# 每10天一笔交通支出,从2022-06-03开始计算
cf.generate_series('Traffic', -30, 
                   frequency=datetime.timedelta(days=10),
                   start=datetime.date(2022, 6, 3), 
                   end=datetime.date(2022, 12, 29))
效果验证

修改后运行原有balance.py脚本,输出结果会完全匹配配置的起始日期:

  • Food条目首条记录为2022-06-03,之后每7天生成一条
  • Rent条目首条记录为2022-06-03,之后每月3号生成一条
  • subscription条目首条记录为2022-06-15,之后每3个月15号生成一条

内容的提问来源于stack exchange,提问作者usrxxx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 04:15:41