Python:获得所有月份的范围?

Ric*_*ard 15 python datetime

我想从现在到2010年8月之间获得所有月份,因为列表格式如下:

['2010-08-01', '2010-09-01', .... , '2016-02-01']
Run Code Online (Sandbox Code Playgroud)

现在这就是我所拥有的:

months = []
for y in range(2010, 2016):
    for m in range(1, 13):
        if (y == 2010) and m < 8:
            continue
        if (y == 2016) and m > 2:
            continue
        month = '%s-%s-01' % (y, ('0%s' % (m)) if m < 10 else m)
        months.append(month)
Run Code Online (Sandbox Code Playgroud)

什么是更好的方法来做到这一点?

Ani*_*Ani 20

dateutil.relativedelta 在这里很方便.

我把格式化作为练习.

from dateutil.relativedelta import relativedelta
import datetime

result = []

today = datetime.date.today()
current = datetime.date(2010, 8, 1)    

while current <= today:
    result.append(current)
    current += relativedelta(months=1)
Run Code Online (Sandbox Code Playgroud)


m.a*_*icz 6

使用datetimetimedelta标准Python的模块 - 无需安装任何新库

from datetime import datetime, timedelta

now = datetime(datetime.now().year, datetime.now().month, 1)
ctr = datetime(2010, 8, 1)
list = [ctr.strftime('%Y-%m-%d')]

while ctr <= now:
    ctr += timedelta(days=32)
    list.append( datetime(ctr.year, ctr.month, 1).strftime('%Y-%m-%d') )
Run Code Online (Sandbox Code Playgroud)

32每天都要加入新的月份(最长的月份有31几天)

  • 这是一个很好的解决方案,但你应该在`ctr = timedelta(days = 32)`之后添加`ctr = ctr.replace(day = 1)`,否则你将在更长的时间内跳过一个月.看看这个序列:[2018-10-28,2018-11-29,2018-12-31,2019-02-01,2019-03-05] - >这里已经跳过了1月.设置day = 1可以避免此问题. (3认同)

das*_*s-g 5

我看了一下dateutil文档.事实证明它提供了比使用更方便的方法dateutil.relativedelta:重复规则(示例)

对于手头的任务,它就像

from dateutil.rrule import *
from datetime import date

months = map(
    date.isoformat,
    rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())
)
Run Code Online (Sandbox Code Playgroud)

精美的印刷品

请注意,我们在这里作弊.元素dateutil.rrule.rrule产生的类型的datetime.datetime,即使我们通过dtstartuntil类型的datetime.date,如我们上面做.我让map他们喂dateisoformat功能,偏偏将它们转换为字符串,如果它只是日期没有时间的日的任何信息.

因此,看似相等的列表理解

[day.isoformat()
    for day in rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())]
Run Code Online (Sandbox Code Playgroud)

会返回一个列表

['2010-08-01T00:00:00',
 '2010-09-01T00:00:00',
 '2010-10-01T00:00:00',
 '2010-11-01T00:00:00',
 ?
 '2015-12-01T00:00:00',
 '2016-01-01T00:00:00',
 '2016-02-01T00:00:00']
Run Code Online (Sandbox Code Playgroud)

因此,如果我们想要使用列表理解而不是map,我们必须做类似的事情

[dt.date().isoformat()
    for dt in rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())]
Run Code Online (Sandbox Code Playgroud)