Python:迭代一个月中的所有日期

4

有没有一种简单的方法来迭代给定月份中的所有日期?

我想要一个方法,通过它我可以迭代具有日期作为datetime.date对象的对象。我已经找到了calendar模块及其Calendar类和相应方法itermonthdates(year, month)

我的问题是,由于需要完整的周,itermonthdates()方法返回包含“填充”日期的迭代器。例如,2019年7月以星期三(31号)结束。因此,这一周是不完整的,itermonthdates()添加了8月1日至4日的日期。

我不想要这种行为。

我的第一个猜测是类似于:

from calendar import Calendar, monthrange
c = Calendar()

for date in list(c.itermonthdates(2019, 7))[:monthrange(2019, 7)[1]]:
    print(date)

这个表现的符合预期,但我不确定是否有更好、更优雅的做法。


什么是“日历”?什么是“日期时间”? - Mad Physicist
3
calendar 是 Python 的一个标准模块。 - John Gordon
1
calendar是一个标准库中的模块名称。我把DateTime修改为datetime.date,对此表示抱歉。 - Chgad
你可以使用 for d in itertools.takewhile(lambda x: x.month == 7, c.itermonthdates(2019, 7)): 替换 monthrange 调用,使代码更加整洁。我不确定是否有更好的方法可以使用标准库实现。 - Peter DeGlopper
2个回答

13

只需按月过滤日期对象。

for d in [x for x in c.itermonthdates(2019, 7) if x.month == 7]:

1
吹毛求疵:使用生成器表达式而不是列表推导式可以避免创建中间列表。 - glibdud
True;OP已经在创建新列表,所以我继续使用它。 - chepner

7

日历(calendar)模块专门用于显示日历。如果您想要一个简单的迭代器,最好使用calendar.monthlendatetime.date结合使用:

def date_iter(year, month):
    for i in range(1, calendar.monthlen(year, month) + 1):
        yield date(year, month, i)

for d in date_iter(2019, 12):
    print(d)

当然,你可以把整个东西写成一行代码:
for d in (date(2019, 12, i) for i in range(1, calendar.monthlen(2019, 12) + 1)):
    print(d)

monthlen 属性似乎是Python 3.7中 calendar 的公共但未记录的属性。它类似于 monthrange 的第二个元素,因此您可以在上面的代码中使用 monthrange(year, month)[1] 替换它。


1
calendar.monthlen 不存在。我认为我们需要坚持使用 calendar.monthrange(year, month)[1] - Chgad
1
哦,好的。我正在使用Python 3.6,但它“不存在”。如果您在答案中添加这个,我很乐意接受它。 - Chgad
3
在Python 3.8中似乎不再存在(至少在Ubuntu 20.04中是如此)。 - pcworld
一个只存在于一个Python版本中的未记录属性不应该成为这个问题的被接受答案。 - Brett Holman
@BrettHolman。我必须同意你的看法 :) - Mad Physicist
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接