寻找*现有*的Python模块来确定财政月份

3 投票
3 回答
1782 浏览
提问于 2025-04-17 05:35

我现在在处理日历问题,真希望能找到一个合适的Python模块来解决我的需求。

我正在开发一个处理订阅的Python网页应用,概念上有点像手机套餐:你在某个日期开始订阅(比如说1.13.2011),然后每个月的账单周期里,你会有一些“通话记录”(就像打电话),这些是需要收费的。

我们需要做到:

  1. 知道每个通话记录属于哪个账单周期。
  2. 知道每个账单周期的开始时间和结束时间。

举个例子,如果你在1.13.2011注册,然后在1.20.2011打了个电话,这个电话就算在你的第一个账单周期里。同样,2.10.2011的电话也是。但如果你在2.15.2011打电话,那就算在你的第二个账单周期了。

关于开始和结束日期:如果今天是2.15.2011,那么当前月份的开始日期是2.13.2011,结束日期是3.13.2011

你可能觉得这没什么复杂的,但要考虑到每个月的天数是不一样的。处理这个问题的规则是,如果你的订阅是在某个月的30号开始的,那么每个月的截止日期就是min(30, n_days_in_that_month)。这个规则同样适用于29、30和31号。


我尝试自己编写代码,但变得太复杂了。我现在希望能找到一个现成的模块来完成这些任务。

求你们不要发一些实现的草图给我!这对我没有帮助。我很感激你们的好意,但在处理日历问题时,草图并不能解决我的问题。我已经有了一个实现的草图,调试你们的代码和调试我的代码一样麻烦。

我只想使用一个现成的模块来处理这些日历任务。你知道有这样的模块吗?

3 个回答

1

这个问题并没有你想的那么复杂。你只需要写一个函数,给定一个开始的日期(比如13号或30号),它就能返回两个日期对象,分别表示当前财务月份的开始和结束。你在问题中已经把所有细节都提到过了。最好在函数中加一个可选的参数todayis,这样你可以指定用哪个日期作为今天的参考。例如,如果今天是2011年10月15号,而你指定的是13,那么函数就会认为你指的是2011年10月13号。但如果你想重新处理6月份的数据,你可以指定todayis=date(2011,06,13)。

返回的值(开始和结束日期)可以帮助你确定哪些日期属于这个财务月份。不过,如果某个日期在开始日期之前,并且距离开始日期少于29天,那么你也可以确定它属于上一个财务月份。下一个财务月份也是一样。这很有用,因为在处理数据时,常常会遇到几天后的情况,这样你就会有两个财务月份的数据需要处理。

2

关于开始和结束日期:如果今天是2011年2月15日,那么这个月的开始日期是2011年2月13日,结束日期是2011年3月13日。

你可能觉得这没什么复杂的,但要考虑到每个月的天数是不一样的。处理这个问题的规则是,如果你的订阅是在某个月的30号开始的,那么每个月的截止日期就是30和那个个月的天数中的较小值。这同样适用于29、30和31号。

这其实还是挺基础的。可以使用datetime模块来存储日期和时间,这样你就能轻松提取出日期的天数(比如,如果dt是一个日期,那么dt.day就是它的天数)。假设一个账单周期是从29号开始(这是最复杂的情况)。设定billing_cycle_day=29。假设有一个可计费的事件发生在event_day=10, event_month=5。因为event_day < billing_cycle_day,所以你会把账单算在event_month的账单里。否则,你就把账单算在下一个月的账单里(记得如果月份是12,你要把年份加1)。

所以现在账单周期总是从29号到下个月的28号。问题在于,如果出现像2011年2月29日这样的日期,它其实是不存在的。例如,账单周期的开始日期应该是2月29日(但它不存在);在这种情况下,你就把它设为下个月的1号。

billing_cycle_day = 29
year, month = 2011, 2
import datetime
def create_date_or_first_of_next_month(year, month, day):
    try:
        return datetime.date(year, month, day)
    except ValueError:
        year_n, month_n = (year, month+1) if month != 12 else (year+1, 1)
        return datetime.date(year_n, month_n, 1)
6

http://labix.org/python-dateutil

Ram的补充:dateutil.rrule.rrule这个类正好实现了我想要的功能。

撰写回答