对Python datetime对象进行按月为单位的增减

十月 11th, 2008 by Soloman | Print 对Python datetime对象进行按月为单位的增减 | 1,879 views

Python内置的datetime很好用,但也有一定的局限性。比如我们如果有个datetime对象,然后我想输出这个对象加上13个月后的时间对象怎么办呢?这里面除了要考虑月份的循环周期为12,同时还要考虑每个月的最后一天不尽相同,比如30天和31天的,还有2月的闰年与非闰年等等问题。

当然,我们可以使用其它第三方的Python时间库,但为了这么小个功能去增加一堆安装部署的麻烦实在是有点得不偿失。其实,一小段代码即可。

下面这段代码提供了一个函数用来对一个datetime对象进行增减(date对象参考修改就可以了),具体说明我已经写在了程序的注释里,这里就不多啰嗦了。

import datetime

# input datetime1, and an month offset
# return the result datetime
def datetime_offset_by_month(datetime1, n = 1):
    # create a shortcut object for one day
    one_day = datetime.timedelta(days = 1)

    # first use div and mod to determine year cycle
    q,r = divmod(datetime1.month + n, 12)

    # create a datetime2
    # to be the last day of the target month
    datetime2 = datetime.datetime(
        datetime1.year + q, r + 1, 1) - one_day

    # if input date is the last day of this month
    # then the output date should also be the last
    # day of the target month, although the day
    # may be different.
    # for example:
    # datetime1 = 8.31
    # datetime2 = 9.30
    if datetime1.month != (datetime1 + one_day).month:
        return datetime2

    # if datetime1 day is bigger than last day of
    # target month, then, use datetime2
    # for example:
    # datetime1 = 10.31
    # datetime2 = 11.30
    if datetime1.day >= datetime2.day:
        return datetime2

    # then, here, we just replace datetime2's day
    # with the same of datetime1, that's ok.
    return datetime2.replace(day = datetime1.day)

接下来,写点简单的测试:

# test
d1 = datetime.datetime(2008, 8, 17)
d2 = datetime_offset_by_month(d1, 13)
print '2008-8-17 + 13 month'
print d2
print

d1 = datetime.datetime(2008, 8, 31)
d2 = datetime_offset_by_month(d1, 13)
print '2008-8-31 + 13 month'
print d2
print

d1 = datetime.datetime(2007, 1, 30)
d2 = datetime_offset_by_month(d1, 13)
print '2007-1-30 + 13 month'
print d2
print

输出结果为:

2008-8-17 + 13 month
2009-09-17 00:00:00

2008-8-31 + 13 month
2009-09-30 00:00:00

2007-1-30 + 13 month
2008-02-29 00:00:00

, , ,

 

本文有13条评论

  1. cosbeta 说: [回复]

    欢迎你加入bloggermap.org,我们感谢你的支持

  2. 老所 说: [回复]

    @cosbeta

    你们的Idea很不错,祝你们越办越好,就是目前女性会员少了点:)

  3. Shawn 说: [回复]

    哈哈,一本正经的,就你一个人做的,你还来个我们。。。

  4. 老所 说: [回复]

    @Shawn

    哈哈,最近才开始接触博客的世界,蛮好玩的嘛,你们好像都认识,到处逛博客经常能发现认识的人的留言:)

  5. JoBru 说: [回复]

    厄,没看懂,但还是留个言~~

  6. Soloman 说: [回复]

    @JoBru

    留言是美德,回复也是,:)去踩踩你的博客~~

  7. 网友 说: [回复]

    我好像来过你的博客了。不过既然来了。给你留点东西吧 (*^__^*) 嘻嘻……

  8. 菜菜熊 说: [回复]

    生是做网站的人。死是做网站的鬼。我的网站什么时候才有你网站的那么成功啊。羡慕中~~~

  9. halida 说: [回复]

    datatime里面的timedelta可以达到一样的功能。
    我在网上找了半天终于找到了,文档看得不仔细呀。。。

  10. Soloman 说: [回复]

    @halida 嘿嘿,我后来也发现了:)

  11. halida 说: [回复]

    这就是编程界中的 太阳底下无新事
    只要是通用的问题都被解决过的
    烦的是客制化的玩意。

  12. Soloman 说: [回复]

    @halida 后来我发现在PHP中更方便,可以直接把 “+ 3 weeks” 这样的字符串转换为 DateTime 对象。话说时间处理,可以写好多东西了,包括不同语言的实现。

添加评论 (支持Gravatar头像)

注意: 评论者允许使用'@user空格'的方式将自己的评论通知另外评论者。例如, ABC是本文的评论者之一,则使用'@ABC '(不包括单引号)将会自动将您的评论发送给ABC。使用'@all ',将会将评论发送给之前所有其它评论者。请务必注意user必须和评论者名相匹配(大小写一致)。

实时评论预览