【问题标题】:How to get all dates for a given year and calendar week in Python?如何在 Python 中获取给定年份和日历周的所有日期?
【发布时间】:2019-04-30 22:09:56
【问题描述】:

假设您有一年“2017”和一个等历周“13”。您如何有效地将与今年和日历周对应的所有日期(使用 datetime 或 calendar 等库)作为 Python 中的列表?

【问题讨论】:

  • 根据您之前的研究,到目前为止您尝试了什么?
  • 我尝试first_date_of_CW = datetime.datetime.strptime('2017-13', '%Y-%W') 使用以下 W 替代方案:U、w、V、v。想法:获取日历周的第一天(或任何其他天),然后计算其他日期与 datetime.timedelta。但是,似乎无法将 'year-cw' 转换为日期。
  • 如果您知道第 1 周第一天的序号,则添加 7*13 以获取第 13 周开始的序号...
  • 好主意,但这有点棘手。例如。对于 2017 年,第一个等历周从 1 月 2 日开始(请参阅whatweekisit.org/calendar-2017.html)。这种情况多年来一直在变化。我的问题是假设我不知道第一个日历周的第一天(目前)。

标签: python datetime calendar


【解决方案1】:

不确定这是您想要的。我玩过calendar 模块,这是我能做到的最好的,请告诉我:

import calendar

def get_week(y, w):
    weeks  = [
        tuple(w) 
        for t in cal.yeardatescalendar(y) for month in t for w in month
        if w[0].year == y
    ]
    weeks = sorted(list(set(weeks)))
    return list(weeks[w-1])
get_week(2017, 13)

输出:

[datetime.date(2017, 3, 27),
 datetime.date(2017, 3, 28),
 datetime.date(2017, 3, 29),
 datetime.date(2017, 3, 30),
 datetime.date(2017, 3, 31),
 datetime.date(2017, 4, 1),
 datetime.date(2017, 4, 2)]

或者用datetime.isocalendar()函数:

import datetime as dt

def get_week(y, w):
    first = next(
        (dt.date(y, 1, 1) + dt.timedelta(days=i) 
         for i in range(367)
         if (dt.date(y, 1, 1) + dt.timedelta(days=i)).isocalendar()[1] == w))
    return [first + dt.timedelta(days=i) for i in range(7)]

get_week(2017, 13)

【讨论】:

  • 谢谢,看起来不错!它还解决了我在@hinev 的解决方案中遇到的get_month(2096, 1) 的问题。
【解决方案2】:

应该这样做。

import datetime
def get_month (year: int, weekday: int):
    start = datetime.datetime (year=year, month=1, day=1)
    '''
    Weekday correction:
    source: https://www.calendar-week.org/
    "In Europe, the first calendar week of the year is the week that
    contains four days of the new year."
    '''
    if start.weekday () >= 4:
        start += datetime.timedelta (days=7-start.weekday ())
    else:
        start -= datetime.timedelta (days=start.weekday ())
    start += datetime.timedelta (days=7*(weekday-1))
    return [start + datetime.timedelta(days=i) for i in range (0, 7)]

将返回datetime-s 的列表。获取字符串表示:

print (list (map (lambda x: str (x.date()), get_month (2017, 2))))

【讨论】:

  • 谢谢,看起来不错。但是,对于 2017 年,我的周数从星期日开始,2018 年从星期一开始,2019 年从星期二开始,等等。为什么会这样?
  • @jollycat 哦,算作一个错误。不保证 1 月 1 日是星期日。计算后剑的两行修复它。
  • 这与我在问题下方最顶部的 cmets 中提到的问题有关。 2017 年第一个等历周从星期日开始,2018 年第一个等历周从星期一开始,2019 年第一个等历周从星期二开始。当然,您可以对这种模式进行硬编码,但这并不是很好和可靠的(考虑闰年)。
  • 好吧,回到第一个星期日/星期一(取决于工作日 0 的含义),然后从那里算起 7 天。第 4 行解决了这个问题。
  • 但是,闰年怎么样?这在闰年变化 +2(而不是 +1)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多