生成给定期间按月细分的日期范围 [英] Generate date ranges broken by month for a given period

查看:101
本文介绍了生成给定期间按月细分的日期范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在努力写一个pythonic,清洁的生成器方法,给定一个日期期间,如 ['2014-01-15','2015-02-03] ,会给我这个:

I'm struggling with writing a pythonic, clean generator method that, given a date period, like ['2014-01-15', '2015-02-03], will give me this:

['2014-01-15', '2014-01-31']
['2014-02-01', '2014-02-28']
...
['2015-02-01', '2015-02-03']

这是我想出来的:

from datetime import datetime
import calendar

def genDatePeriods(startDate, endDate, format='%Y-%m-%d'):
    dt1 = datetime.strptime(startDate, format)
    dt2 = datetime.strptime(endDate, format)

    for year in range(dt1.year, dt2.year + 1):
        for month in range(1, 13):
            day0 = dt1.day if month == dt1.month and year == dt1.year else 1
            day1 = dt2.day if month == dt2.month and year == dt2.year else calendar.monthrange(year, month)[1]
            if (year == dt1.year and month < dt1.month) or (year == dt2.year and month > dt2.month):
                continue
            else:
                d0 = (year, month, day0)
                d1 = (year, month, day1)
                yield [datetime(*d).strftime(format) for d in [d0, d1]]

我觉得有更多的pythonic /整洁/高效的方式来做到这一点。任何想法?

It works, however I feel like there is a more pythonic/tidy/efficient way to do this. Any ideas?

推荐答案

以下是更简洁,使用 datetime.date c $ c>对象,每次查找下一个月的第一天,直到到达结束日期:

The following is much more concise, using datetime.date() objects to find the first day of the next month each time, until you reach the end date:

from datetime import datetime, timedelta

def genDatePeriods(startDate, endDate, format='%Y-%m-%d'):
    curr = datetime.strptime(startDate, format).date()
    end = datetime.strptime(endDate, format).date()

    while curr <= end:
        # first day of the next month, using modular arithmetic
        next_month = curr.replace(
            month=curr.month % 12 + 1, year=curr.year + curr.month // 12,
            day=1)
        curr_formatted = curr.strftime(format)
        # end date is next month's first day, minus one day,
        # or the given endDate, whichever comes first
        end_formatted = min(next_month - timedelta(days=1), end).strftime(format)
        yield [curr_formatted, end_formatted]
        curr = next_month


b $ b

演示:

Demo:

>>> for res in genDatePeriods('2014-01-15', '2015-02-03'):
...     print res
... 
['2014-01-15', '2014-01-31']
['2014-02-01', '2014-02-28']
['2014-03-01', '2014-03-31']
['2014-04-01', '2014-04-30']
['2014-05-01', '2014-05-31']
['2014-06-01', '2014-06-30']
['2014-07-01', '2014-07-31']
['2014-08-01', '2014-08-31']
['2014-09-01', '2014-09-30']
['2014-10-01', '2014-10-31']
['2014-11-01', '2014-11-30']
['2014-12-01', '2014-12-31']
['2015-01-01', '2015-01-31']
['2015-02-01', '2015-02-03']

这篇关于生成给定期间按月细分的日期范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆