如何在Python中获取星期数?


339

如何使用Python找出6月16日(wk24)当年的星期几?


1
@Donal:我们看一下6月16日,另一个在6月26日
interjay

5
定义第1周。isocalendar()不是唯一的方法。
Mark Tolonen

3
请注意,的输出strftime("%U", d)可能与的不同isocalendar()。例如,如果将年份更改为2004,则将使用第24周,而使用strftime()第25周isocalendar()
moooeeeep 2012年

Answers:


409

datetime.date有一个isocalendar()方法,该方法返回包含日历周的元组:

>>> import datetime
>>> datetime.date(2010, 6, 16).isocalendar()[1]
24

datetime.date.isocalendar()是一种实例方法,该方法返回给定日期实例的元组,该元组按各自的顺序包含年,周号和周日。


7
如果您解释了“ [1]”,或者给出了在哪里查找信息的指针,那将有所帮助。
乔纳森·莱夫勒

5
我猜最简单的方法是使用strftime提取周数,最好的导入日期时间今天= datetime.now()周= Today.strftime(“%W”)
bipsa 2015年

7
这有点晚了。但是在我的机器上,date(2010, 1, 1).isocalendar()[1]return 53。从文档中得出:“例如,2004年从星期四开始,因此ISO年度2004的第一周从2003年12月29日星期一开始,到2004年1月4日星期日结束,所以date(2003, 12, 29).isocalendar() == (2004, 1, 1)date(2004, 1, 4).isocalendar() == (2004, 1, 7)。”
jclancy

17
isocalendar()很棒,但是请确保它是您想要的。今天是一个完美的例子。2016年1月1日等于(2015, 53, 5)now.strftime("%W")now.strftime("%U")等于00通常所需要的。 STRFTIME示例
DaveL17'1

不错,我只是补充说,今天我认为这会有所帮助,这就是我想要的:D
Vitaliy Terziev

124

您可以直接从日期时间获取星期数作为字符串。

>>> import datetime
>>> datetime.date(2010, 6, 16).strftime("%V")
'24'

您还可以通过更改以下strftime参数来获得一年中星期几的不同“类型” :

%U- 一年中的周号(星期日为一周的第一天),以零填充的十进制数表示。在第一个星期天之前的新的一年的所有天都被认为是在本周0示例:00,01,...,53

%W-一年中的星期数(星期一为一周的第一天),以十进制数表示。第一个星期一之前的新的一年中的所有天都视为在第0周。例如:00,01,...,53

[...]

在Python 3.6中添加,并反向移植到某些发行版的Python 2.7中。)为方便起见,还包含了C89标准不需要的其他一些指令。这些参数都对应于ISO 8601日期值。当与该strftime()方法一起使用时,可能并非在所有平台上都可用。

[...]

%V- ISO 8601星期与周一的十进制数作为一周的第一天。周01是包含在1月4例子的一周:01,02,...,53

from:datetime-基本日期和时间类型-Python 3.7.3文档

我从这里找到了。它在Python 2.7.6中为我工作


您在引用什么Linux手册?Python 2.7.5和3.3.2说Invalid format string了这种模式。他们的文档也没有提及%V
Vsevolod Golovanov

3
抱歉,我没有提到,我是从这里来的。它在Python 2.7.6中为我工作。
jotacor

2
好答案!我想补充一点,如果您对日期的'<YEAR>-<ISOWEEK>'表示感兴趣,请使用%G-%V代替%Y-%V%G是等效的ISO年%Y
KenHBS

为了使其正常工作,我不得不这样写:datetime.datetime(2010,6,16).strftime(“%V”),或者像这样的datetime.datetime(2010,6,16).date()。strftime (“%V”)
埃纳尔

77

我相信date.isocalendar()这将是答案。本文介绍了ISO 8601日历背后的数学原理。查看Python文档的datetime页面的date.isocalendar()部分。

>>> dt = datetime.date(2010, 6, 16) 
>>> wk = dt.isocalendar()[1]
24

.isocalendar()返回带有(年,周,周,日)的三元组。dt.isocalendar()[0]返回年份,dt.isocalendar()[1]返回星期数,dt.isocalendar()[2]返回星期几。可以很简单。


4
+1链接说明了ISO周的非直观性质。
Mark Ransom

27

这是另一个选择:

import time
from time import gmtime, strftime
d = time.strptime("16 Jun 2010", "%d %b %Y")
print(strftime("%U", d))

哪个打印 24

请参阅:http//docs.python.org/library/datetime.html#strftime-and-strptime-behavior


9
或%W(如果您的星期从星期一开始)。
ZeWaren

1
如果您不想拆分或转换以字符串形式出现的日期,则此方法更好。...只需按原样以字符串格式以strptime传递字符串,然后以第二个参数指定格式。好的解决方案。请记住:%W(如果星期从星期一开始)。
TheCuriousOne '17

22

其他人建议的ISO周是不错的一周,但它可能不符合您的需求。假设每个星期都从星期一开始,这会导致年初和年底出现一些有趣的异常情况。

如果您想使用第1周始终为1月1日至1月7日的定义,而不管一周中的星期几,请使用类似以下的推导:

>>> testdate=datetime.datetime(2010,6,16)
>>> print(((testdate - datetime.datetime(testdate.year,1,1)).days // 7) + 1)
24

3
说isocalendar在今年年初和年底存在“一些有趣的异常”似乎有些轻描淡写。对于某些日期时间值(例如,2014年12月29日00:00:00),isocalendar的结果非常容易引起误解(即使在ISO规范中实际上并非不正确),根据isocalendar,其日期值为2015,一周为1(请参见我在下面的条目)。
凯文

3
@Kevin,这没错,只是它们的定义与您的定义不符。ISO决定了两件事:第一,星期一到星期日的整个星期都在同一年,第二,包含大部分日子的那一年是指定的那一年。这导致在年初和年末的一周中的某几天移至下一年。
Mark Ransom 2014年

6
同意 但是按照大多数人的定义,2014年12月29日绝对不是2015年的第1周。我只是想提请注意这种潜在的混乱来源。
凯文

这正是我想要的。不是关于如何执行此操作,而是有关ISO以及以星期一开始的信息。
阿米特·阿莫拉

19

通常要获取当前的星期数(从星期日开始):

from datetime import *
today = datetime.today()
print today.strftime("%U")

4
从strftime('%U')的文档中:“一年中的星期几(星期日为一周的第一天)为十进制数字[00,53]。将考虑新年中第一个星期日之前的所有天数。在第0周。”
多兰·安特努奇

14

对于一年中瞬时周的整数值,请尝试:

import datetime
datetime.datetime.utcnow().isocalendar()[1]

10

许多用于周编号的系统。以下是简单地与代码示例一起放置的最常见系统:

  • ISO:第一周从星期一开始,必须包含1月4日。ISO日历已在Python中实现:

    >>> from datetime import date
    >>> date(2014, 12, 29).isocalendar()[:2]
    (2015, 1)
  • 北美:第一周从星期日开始,必须包含1月1日。以下代码是针对北美系统的Python ISO日历实现的修改后的版本:

    from datetime import date
    
    def week_from_date(date_object):
        date_ordinal = date_object.toordinal()
        year = date_object.year
        week = ((date_ordinal - _week1_start_ordinal(year)) // 7) + 1
        if week >= 52:
            if date_ordinal >= _week1_start_ordinal(year + 1):
                year += 1
                week = 1
        return year, week
    
    def _week1_start_ordinal(year):
        jan1 = date(year, 1, 1)
        jan1_ordinal = jan1.toordinal()
        jan1_weekday = jan1.weekday()
        week1_start_ordinal = jan1_ordinal - ((jan1_weekday + 1) % 7)
        return week1_start_ordinal
    >>> from datetime import date
    >>> week_from_date(date(2014, 12, 29))
    (2015, 1)
  • MMWR(CDC):第一周从星期日开始,必须包含1月4日。我专门为此编号系统创建了epiweeks程序包(也支持ISO系统)。这是一个例子:
    >>> from datetime import date
    >>> from epiweeks import Week
    >>> Week.fromdate(date(2014, 12, 29))
    (2014, 53)

8

如果您仅使用等周日历号,则以下内容就足够了:

import datetime
week = date(year=2014, month=1, day=1).isocalendar()[1]

这将检索isocalendar返回的元组的第二个成员,作为我们的星期数。

但是,如果您要使用公历中处理的日期函数,则仅等距日历无法正常工作!请看以下示例:

import datetime
date = datetime.datetime.strptime("2014-1-1", "%Y-%W-%w")
week = date.isocalendar()[1]

此处的字符串表示返回2014年第一周的星期一作为我们的日期。当我们使用isocalendar在此处检索星期数时,我们希望可以返回相同的星期数,但事实并非如此。相反,我们得到的周数为2。为什么?

阳历的第一周是包含星期一的第一周。等值线的第1周是包含星期四的第一周。2014年初的不完整一周包含一个星期四,因此这是等距日历的第1周,date第2周。

如果要获得公历周,我们将需要从等距转换为公历。这是个简单的功能,可以解决问题。

import datetime

def gregorian_week(date):
    # The isocalendar week for this date
    iso_week = date.isocalendar()[1]

    # The baseline Gregorian date for the beginning of our date's year
    base_greg = datetime.datetime.strptime('%d-1-1' % date.year, "%Y-%W-%w")

    # If the isocalendar week for this date is not 1, we need to 
    # decrement the iso_week by 1 to get the Gregorian week number
    return iso_week if base_greg.isocalendar()[1] == 1 else iso_week - 1

6

您可以尝试使用%W指令,如下所示:

d = datetime.datetime.strptime('2016-06-16','%Y-%m-%d')
print(datetime.datetime.strftime(d,'%W'))

'%W':一年中的第几周(星期一为一周的第一天),以十进制数表示。第一个星期一之前的新的一年中的所有天都视为在第0周。(00,01,...,53)


2

isocalendar()返回某些日期的不正确的年和周数值:

Python 2.7.3 (default, Feb 27 2014, 19:58:35) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime as dt
>>> myDateTime = dt.datetime.strptime("20141229T000000.000Z",'%Y%m%dT%H%M%S.%fZ')
>>> yr,weekNumber,weekDay = myDateTime.isocalendar()
>>> print "Year is " + str(yr) + ", weekNumber is " + str(weekNumber)
Year is 2015, weekNumber is 1

与Mark Ransom的方法进行比较:

>>> yr = myDateTime.year
>>> weekNumber = ((myDateTime - dt.datetime(yr,1,1)).days/7) + 1
>>> print "Year is " + str(yr) + ", weekNumber is " + str(weekNumber)
Year is 2014, weekNumber is 52

3
查看有关iso8601日历的一些链接(例如,staff.science.uu.nl/~ gent0113/calendar/ isocalendar.htm),我发现isocalendar()返回的year和weeknumber值并不是“错误的”。例如,在ISO8601下,2004年始于2003年12月29日。因此isocalendar()在返回2014年12月29日的2015年时可能是正确的,但是出于很多人的目的,这将是非常误导的。
凯文

2

我将讨论概括为两个步骤:

  1. 将原始格式转换为datetime对象。
  2. 使用datetime对象或date对象的功能来计算星期数。

暖身

python

from datetime import datetime, date, time
d = date(2005, 7, 14)
t = time(12, 30)
dt = datetime.combine(d, t)
print(dt)

```

第一步

要手动生成datetime对象,我们可以使用datetime.datetime(2017,5,3)datetime.datetime.now()

但是实际上,我们通常需要解析一个现有的字符串。我们可以使用strptime函数,例如datetime.strptime('2017-5-3','%Y-%m-%d')您必须指定的格式。有关不同格式代码的详细信息,请参见官方文档中

或者,更方便的方法是使用dateparse模块。例子有dateparser.parse('16 Jun 2010')dateparser.parse('12/2/12')dateparser.parse('2017-5-3')

以上两种方法将返回一个datetime对象。

第二步

使用获得的 datetime对象进行调用strptime(format)。例如,

python

dt = datetime.strptime('2017-01-1','%Y-%m-%d') # return a datetime object. This day is Sunday
print(dt.strftime("%W")) # '00' Monday as the 1st day of the week. All days in a new year preceding the 1st Monday are considered to be in week 0.
print(dt.strftime("%U")) # '01' Sunday as the 1st day of the week. All days in a new year preceding the 1st Sunday are considered to be in week 0.
print(dt.strftime("%V")) # '52' Monday as the 1st day of the week. Week 01 is the week containing Jan 4.

```

决定使用哪种格式是非常棘手的。更好的方法是获取date对象进行调用isocalendar()。例如,

python

dt = datetime.strptime('2017-01-1','%Y-%m-%d') # return a datetime object
d = dt.date() # convert to a date object. equivalent to d = date(2017,1,1), but date.strptime() don't have the parse function
year, week, weekday = d.isocalendar() 
print(year, week, weekday) # (2016,52,7) in the ISO standard

```

实际上,您将更有可能用来date.isocalendar()编写每周报告,尤其是在“圣诞节-新年”购物季节。


0
userInput = input ("Please enter project deadline date (dd/mm/yyyy/): ")

import datetime

currentDate = datetime.datetime.today()

testVar = datetime.datetime.strptime(userInput ,"%d/%b/%Y").date()

remainDays = testVar - currentDate.date()

remainWeeks = (remainDays.days / 7.0) + 1


print ("Please pay attention for deadline of project X in days and weeks are  : " ,(remainDays) , "and" ,(remainWeeks) , "Weeks ,\nSo  hurryup.............!!!") 

-1

已经给出了很多答案,但是id喜欢添加到它们中。

如果您需要将星期显示为年/周样式(例如1953年-2019年第53周,2001年-2020年第1周等),则可以执行以下操作:

import datetime

year = datetime.datetime.now()
week_num = datetime.date(year.year, year.month, year.day).strftime("%V")
long_week_num = str(year.year)[0:2] + str(week_num)

这将需要当前的年和周,而在撰写本文时,long_week_num将是:

>>> 2006

为什么要date()从头开始?datetime.datetime()实例具有.date()用于该工作的方法。
马丁·彼得斯

但是,更令人担忧的是您的答案是世纪,而不是当前年份。而且,如果您要对星期数使用字符串格式,那么为什么不同时使用它来包含年份呢?
马丁·彼得斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.