3

我在日历地狱中,我希望那里有一个 Python 模块可以满足我的需求。

我正在制作一个处理订阅的 Python Web 应用程序。它在概念上类似于手机计划:您在某个日期(例如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。


我尝试对此进行编码,但它太复杂了。我正在寻找的是一个现成的、现有的模块来做这些事情。

看在上帝的份上,不要发布带有实施草图的答案!这对我没用。我感谢您的意图,但在日历地狱中,实现草图无济于事。我已经有了一个实现的草图,调试你的和调试我的一样长。

我只对使用处理此类日历任务的现有模块感兴趣。你认识一个吗?

4

3 回答 3

6

http://labix.org/python-dateutil

Ram 的编辑:这dateutil.rrule.rrule门课完全符合我的要求。

于 2011-11-03T18:40:27.943 回答
2

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

您可能会认为这并不复杂,但是您必须考虑到月份有不同的长度。处理此问题的规则是,如果您的订阅从任何月份的 30 日开始,则每个月的截止日期将为 min(30, n_days_in_that_month)。这也适用于 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's bill 收费。否则,您将计入下个月的账单(请记住,如果月份 = 12;您必须增加年份)。

所以现在计费周期永远是下个月的29号到28号。如果说 2011 年 2 月 29 日这样的日期不存在,就会出现复杂情况。例如,计费周期 start_date 应该是 2/29/2011(但它不存在);在这种情况下,您只需在下个月将其设为第一个即可。

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)
于 2011-11-03T19:04:26.440 回答
1

这个问题并不像你想象的那么难。您所要做的就是编写一个函数,给定一个开始日期(如 13 或 30),它返回两个日期对象,它们是当前财政月的开始和结束。您已经勾勒出问题中的所有细节。最好在函数中包含一个可选的 todayis 参数,以便您指定使用哪一天作为今天的参考。例如,如果今天是 2011 年 10 月 15 日,并且您指定 13,则该函数将假定您的意思是 2011 年 10 月 13 日。但如果您想重新运行 6 月的数据,您将指定 todayis=date(2011,06, 13)

返回值(开始和结束)允许您查明属于本财政月的日期。但是,如果日期在开始日期之前且距离开始日期不到 29 天,那么您也可以精确定位在上一个会计月份。下一个财政月也是如此。这很有用,因为在很多情况下您会在几天后处理数据,因此您将有两个会计月来处理。

于 2011-11-03T20:01:12.837 回答