在Python中,如何找到给定周的第一个星期一的日期?

29

如果我知道某一年的某个周数(例如第51周)和给定的年份(例如2008),如何找到该周的第一个星期一日期?

非常感谢。


17
一周中的“第一个星期一”是什么意思?一周中有多少个星期一? - Federico A. Ramponi
35
有些星期会连续出现两个星期一,至少感觉是这样的。 - Lasse V. Karlsen
6个回答

35
>>> import time
>>> time.asctime(time.strptime('2008 50 1', '%Y %W %w'))
'Mon Dec 15 00:00:00 2008'
假设您的一周的第一天是星期一,如果您的一周的第一天是星期日,请使用%U而不是%W。有关详细信息,请参阅strptime文档
更新:修复了周数。由于%W指令是从0开始计数的,因此第51周应输入为50,而不是51。

8
请注意,此函数在使用isocalendar()时无法正确工作。例如,2013年的第一周从12月31日开始(这是正确的),但2012-1从12月26日开始(应该是1月2日)。这是因为%W使用其自己的周数实现,而isocalendar()使用ISO标准。请使用下面Vaidas的方法以获得更准确的结果。 - ralphje

33

PEZ和Gerald Kaszuba的解决方案是基于一年中的第一周始终是从1月1日开始的假设。然而这个假设在ISO日历下是不正确的,可以参考Python文档。例如,在ISO日历中,2010年的第一周实际上从1月4日开始,而2010年的1月1日则属于2009年的第53周。一个兼容ISO日历的解决方案:

from datetime import date, timedelta

def week_start_date(year, week):
    d = date(year, 1, 1)    
    delta_days = d.isoweekday() - 1
    delta_weeks = week
    if year == d.isocalendar()[0]:
        delta_weeks -= 1
    delta = timedelta(days=-delta_days, weeks=delta_weeks)
    return d + delta

根据此列表,2013年9月3日(您发表评论的那天)是ISO日历下的第36周。week_start_date(2013,36)返回2013-09-02。 - Vaidas K.
time.strftime('%W') 那天给了我 35。今天它给了我 36。这不对吗? - 2rs2ts
3
注意 Ralphje 在被接受的答案中的评论中提到,%W 使用自己的周数实现,而不是 ISO 标准。同时要注意 %W 是从0开始计算的。 - Vaidas K.

17
from datetime import date, timedelta

def first_monday(year, week):
    d = date(year, 1, 4)  # The Jan 4th must be in week 1  according to ISO
    return d + timedelta(weeks=(week-1), days=-d.weekday())

1
如果你需要确定当前一周的开始,可以使用datetime.datetime.now().isocalendar()[1]来确定当前年份的周数。这个方法很有效。 - robertzp

8

假设第一周可以在去年的某一天落在星期一,那么这似乎是有效的。

from datetime import date, timedelta

def get_first_dow(year, week):
    d = date(year, 1, 1)
    d = d - timedelta(d.weekday())
    dlt = timedelta(days = (week - 1) * 7)
    return d + dlt

4

我稍微修改了Vaidas K.的脚本,以便它能够返回一周的开始日期和结束日期。

from datetime import datetime, date, timedelta

def weekbegend(year, week):
    """
    Calcul du premier et du dernier jour de la semaine ISO
    """
    d = date(year, 1, 1)    
    delta_days = d.isoweekday() - 1
    delta_weeks = week
    if year == d.isocalendar()[0]:
        delta_weeks -= 1
    # delta for the beginning of the week
    delta = timedelta(days=-delta_days, weeks=delta_weeks)
    weekbeg = d + delta
    # delta2 for the end of the week
    delta2 = timedelta(days=6-delta_days, weeks=delta_weeks)
    weekend = d + delta2
    return weekbeg, weekend

所以你可以这样使用它。

weekbeg, weekend = weekbegend(2009, 1)
begweek = weekbeg.strftime("%A %d %B %Y")
endweek = weekend.strftime("%A %d %B %Y")

0
使用时间模块中的字符串格式化。详细解释所使用的格式
>>> import time
>>> time.strptime("51 08 1","%U %y %w")
(2008, 12, 22, 0, 0, 0, 0, 357, -1)

返回的日期与我的计算机日历相差一周,也许这是因为星期从0开始索引的原因?


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