Làm thế nào để có được số tuần trong Python?


337

Làm thế nào để tìm ra số tuần là năm hiện tại vào ngày 16 tháng 6 (wk24) với Python?


1
@Donal: Một cái nhìn vào ngày 16 tháng 6, cái kia vào ngày 26 tháng 6
interjay

5
Xác định tuần 1. isocalWiki () không phải là cách duy nhất để làm điều đó.
Đánh dấu Tolonen

3
Lưu ý rằng đầu ra của strftime("%U", d)có thể khác với isocalendar(). Ví dụ: nếu bạn thay đổi năm thành 2004, bạn sẽ nhận được tuần 24 bằng cách sử dụng strftime()và tuần 25 bằng cách sử dụng isocalendar().
moooeeeep

Câu trả lời:


408

datetime.datecó một isocalendar()phương thức, trả về một tuple chứa tuần theo lịch:

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

datetime.date.isocalWiki () là một phương thức cá thể trả về một tuple chứa năm, số tuần và ngày trong tuần theo thứ tự tương ứng cho thể hiện ngày đã cho.


7
Sẽ rất hữu ích nếu bạn giải thích ' [1]' hoặc đưa ra một con trỏ để tìm thông tin.
Jonathan Leffler

5
Tôi đoán cách dễ nhất là trích xuất số tuần bằng cách sử dụng strftime, nhập dữ liệu tốt nhất vào ngày hôm nay = datetime.now () week = today.strftime ("% W")
bipsa

7
Đây là một chút muộn. Nhưng trên máy của tôi, date(2010, 1, 1).isocalendar()[1]trả lại 53. Từ các tài liệu: "Ví dụ: 2004 bắt đầu vào thứ năm, vì vậy tuần đầu tiên của năm ISO 2004 bắt đầu vào thứ Hai, ngày 29 tháng 12 năm 2003 và kết thúc vào Chủ nhật, ngày 4 tháng 1 năm 2004, vì vậy date(2003, 12, 29).isocalendar() == (2004, 1, 1)date(2004, 1, 4).isocalendar() == (2004, 1, 7)."
jclancy

17
isocalendar()là tuyệt vời, nhưng hãy chắc chắn đó là những gì bạn muốn. Hôm nay là một ví dụ hoàn hảo. 01/01/2016 bằng (2015, 53, 5). now.strftime("%W")now.strftime("%U")bằng với 00đó thường là những gì muốn. Ví dụ về STRFTIME
DaveL17

thật tuyệt, tôi vừa thêm vào ngày hôm nay tôi nghĩ nó sẽ hữu ích, đó là những gì tôi đang tìm kiếm: D
Vitaliy Terziev

123

Bạn có thể lấy số tuần trực tiếp từ datetime dưới dạng chuỗi.

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

Ngoài ra, bạn có thể nhận được các "loại" khác nhau của số tuần trong năm thay đổi strftimetham số cho:

%U- Số tuần trong năm (Chủ nhật là ngày đầu tiên của tuần) dưới dạng số thập phân có đệm bằng không. Tất cả các ngày trong năm mới trước Chủ nhật đầu tiên được coi là vào tuần 0. Ví dụ: 00 , 01, Lỗi, 53

%W- Số tuần trong năm ( Thứ Hai là ngày đầu tiên của tuần) dưới dạng số thập phân. Tất cả các ngày trong năm mới trước ngày thứ Hai đầu tiên được coi là vào tuần 0. Ví dụ: 00 , 01, Lỗi, 53

[...]

( Đã thêm vào Python 3.6, được nhập vào một số bản phân phối của Python 2.7 ) Một số chỉ thị bổ sung không được yêu cầu bởi tiêu chuẩn C89 được đưa vào để thuận tiện. Các tham số này đều tương ứng với các giá trị ngày ISO 8601. Chúng có thể không có sẵn trên tất cả các nền tảng khi được sử dụng với strftime()phương thức.

[...]

%V- ISO 8601 tuần dưới dạng số thập phân với thứ Hai là ngày đầu tuần. Tuần 01 là tuần chứa ngày 4 tháng 1. Ví dụ: 01 , 02, Mạnh, 53

từ: datetime - Các loại ngày và giờ cơ bản - Tài liệu Python 3.7.3

Tôi đã tìm hiểu về nó từ đây . Nó hoạt động với tôi trong Python 2.7.6


Bạn đang trích dẫn điều gì, một số hướng dẫn sử dụng Linux? Python 2.7.5 và 3.3.2 nói Invalid format stringvề mẫu này. Tài liệu của họ cũng không đề cập đến %V.
Vsevolod Golovanov

3
Xin lỗi tôi đã không đề cập đến nó, tôi đã nhận được từ đây . Nó hoạt động với tôi trong Python 2.7.6.
jotacor 20/03/2015

2
Câu trả lời chính xác! Tôi muốn thêm rằng nếu bạn quan tâm đến đại diện '<NĂM> - <ISOWEEK>' về ngày của bạn, hãy sử dụng %G-%Vthay vì %Y-%V. %Glà năm ISO tương đương với%Y
KenHBS

Tôi đã phải viết nó như thế này để nó hoạt động: datetime.datetime (2010, 6, 16) .strftime ("% V"), hoặc như datetime.datetime (2010, 6, 16) .date (). ("% V")
Einar

77

Tôi tin rằng date.isocalendar()sẽ là câu trả lời. Bài viết này giải thích toán học đằng sau Lịch ISO 8601. Kiểm tra phần date.isocalWiki () của trang datetime của tài liệu Python.

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

.isocalWiki () trả lại 3-tuple với (năm, wk num, wk ngày). dt.isocalendar()[0]trả về năm, dt.isocalendar()[1]trả về số tuần, dt.isocalendar()[2]trả về ngày trong tuần. Đơn giản như có thể.


4
+1 cho liên kết giải thích bản chất không trực quan của các tuần ISO.
Đánh dấu tiền chuộc

27

Đây là một lựa chọn khác:

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

mà in 24.

Xem: http://docs.python.org/l Library / datetime.html # strftime-and-strptime-behavior


9
hoặc% W nếu tuần của bạn bắt đầu vào thứ Hai.
ZeWaren

1
Cách tiếp cận này tốt hơn trong trường hợp bạn không muốn phân tách hoặc chuyển đổi một ngày đến dưới dạng chuỗi ... chỉ cần chuyển chuỗi theo chuỗi trong định dạng chuỗi như hiện tại và chỉ định định dạng trong đối số thứ hai. Giải pháp tốt. Ghi nhớ:% W nếu tuần bắt đầu vào thứ Hai.
TheCantlyOne

22

Tuần lễ ISO được đề xuất bởi những người khác là một tuần tốt, nhưng nó có thể không phù hợp với nhu cầu của bạn. Nó giả định mỗi tuần bắt đầu bằng thứ Hai, dẫn đến một số bất thường thú vị vào đầu và cuối năm.

Nếu bạn muốn sử dụng một định nghĩa cho biết tuần 1 luôn luôn là ngày 1 tháng 1 đến ngày 7 tháng 1, bất kể ngày nào trong tuần, hãy sử dụng một dẫn xuất như thế này:

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

3
Nói rằng isocalWiki có "một số dị thường thú vị" vào đầu và cuối năm dường như là một chút thiếu sót. Các kết quả của isocalWiki rất sai lệch (ngay cả khi không thực sự không chính xác theo đặc điểm kỹ thuật ISO) đối với một số giá trị thời gian, như ngày 29 tháng 12 năm 2014, 00:00:00, theo isocalWiki có giá trị năm là 2015 và số tuần là 1 (xem mục nhập của tôi dưới đây).
Kevin

3
@Kevin, không sai, chỉ là định nghĩa của họ không khớp với bạn. ISO quyết định hai điều: thứ nhất là toàn bộ tuần từ thứ Hai đến Chủ nhật sẽ trong cùng một năm, thứ hai là năm chứa hầu hết các ngày sẽ là một ngày được giao. Điều này dẫn đến các ngày trong tuần vào khoảng đầu và cuối năm chuyển sang năm liền kề.
Đánh dấu tiền chuộc

6
Đã đồng ý. Nhưng theo định nghĩa của hầu hết mọi người, ngày 29 tháng 12 năm 2014 chắc chắn sẽ không phải là tuần 1 của năm 2015. Tôi chỉ muốn thu hút sự chú ý đến nguồn gây nhầm lẫn tiềm năng này.
Kevin

Điều này thật đúng với gì mà tôi đã tìm kiếm. Không phải về cách làm điều này, nhưng thông tin liên quan đến ISO và bắt đầu với thứ hai.
Amit Amola

19

Nói chung để có được số tuần hiện tại (bắt đầu từ Chủ nhật):

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

4
Từ tài liệu về strftime ('% U'): "Số tuần trong năm (Chủ nhật là ngày đầu tuần) dưới dạng số thập phân [00,53]. Tất cả các ngày trong năm mới trước Chủ nhật đầu tiên được xem xét đến tuần thứ 0. "
Dolan Antenucci

14

Để biết giá trị nguyên của tuần tức thời trong năm, hãy thử:

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

10

nhiều hệ thống để đánh số tuần . Sau đây là các hệ thống phổ biến nhất chỉ cần đặt với các ví dụ mã:

  • ISO : Tuần đầu tiên bắt đầu với Thứ Hai và phải có ngày 4 tháng 1. Lịch ISO đã được triển khai trong Python:

    >>> from datetime import date
    >>> date(2014, 12, 29).isocalendar()[:2]
    (2015, 1)
  • Bắc Mỹ : Tuần đầu tiên bắt đầu với Chủ nhật và phải có ngày 1 tháng 1. Đoạn mã sau đây là phiên bản sửa đổi của tôi về triển khai lịch ISO của Python cho hệ thống Bắc Mỹ:

    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) : Tuần đầu tiên bắt đầu bằng Chủ nhật và phải có ngày 4 tháng 1. Tôi đã tạo ra các epiweek gói dành riêng cho hệ thống đánh số này (cũng có hỗ trợ cho hệ thống ISO). Đây là một ví dụ:
    >>> from datetime import date
    >>> from epiweeks import Week
    >>> Week.fromdate(date(2014, 12, 29))
    (2014, 53)

8

Nếu bạn chỉ sử dụng số tuần isocalWiki trên bảng thì điều sau đây là đủ:

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

Điều này lấy thành viên thứ hai của bộ dữ liệu được trả về bởi isocalWiki cho số tuần của chúng tôi.

Tuy nhiên, nếu bạn đang sử dụng các hàm ngày có trong lịch Gregorian, một mình isocalWiki sẽ không hoạt động! Lấy ví dụ sau:

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

Chuỗi ở đây nói sẽ trả lại thứ Hai của tuần đầu tiên vào năm 2014 như ngày của chúng tôi. Khi chúng tôi sử dụng isocalWiki để lấy lại số tuần ở đây, chúng tôi sẽ mong nhận lại số tuần tương tự, nhưng chúng tôi thì không. Thay vào đó, chúng tôi nhận được một số tuần là 2. Tại sao?

Tuần 1 trong lịch Gregorian là tuần đầu tiên có thứ Hai. Tuần 1 trong isocalWiki là tuần đầu tiên chứa thứ Năm. Tuần một phần vào đầu năm 2014 có một ngày thứ Năm, vì vậy đây là tuần 1 của isocalWiki và thực hiệndate tuần 2.

Nếu chúng ta muốn có được tuần lễ Gregorian, chúng ta sẽ cần phải chuyển đổi từ isocalWiki sang Gregorian. Đây là một chức năng đơn giản mà thực hiện các mẹo.

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

Bạn có thể thử chỉ thị% W như dưới đây:

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

'% W': Số tuần trong năm (Thứ Hai là ngày đầu tiên của tuần) dưới dạng số thập phân. Tất cả các ngày trong một năm mới trước ngày thứ Hai đầu tiên được coi là vào tuần 0. (00, 01, ..., 53)


2

isocalWiki () trả về giá trị năm và số tuần không chính xác cho một số ngày:

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

So sánh với phương pháp của 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
Nhìn vào một số liên kết về lịch iso8601 (ví dụ: staff.science.uu.nl/~gent0113/calWiki/isocalWiki.htmlm ), tôi thấy rằng các giá trị năm và số tuần được trả về bởi isocalWiki () không phải là "không chính xác" như vậy. Ví dụ, theo ISO8601, năm 2004 bắt đầu vào ngày 29 tháng 12 năm 2003. Vì vậy, isocalWiki () có thể đúng khi trả lại một năm 2015 cho ngày 29 tháng 12 năm 2014, nhưng đối với nhiều mục đích của mọi người, điều này sẽ gây hiểu nhầm .
Kevin

2

Tôi tóm tắt các cuộc thảo luận thành hai bước:

  1. Chuyển đổi định dạng thô thành một datetimeđối tượng.
  2. Sử dụng chức năng của một datetimeđối tượng hoặc một dateđối tượng để tính số tuần.

Ấm lên

`` `trăn

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

`` `

Bước 1

Để tự tạo một datetimeđối tượng, chúng ta có thể sử dụng datetime.datetime(2017,5,3)hoặcdatetime.datetime.now() .

Nhưng trong thực tế, chúng ta thường cần phân tích một chuỗi hiện có. chúng ta có thể sử dụng strptimechức năng, chẳng hạn như datetime.strptime('2017-5-3','%Y-%m-%d')trong đó bạn phải xác định định dạng cụ thể. Chi tiết về mã định dạng khác nhau có thể được tìm thấy trong tài liệu chính thức .

Ngoài ra, một cách thuận tiện hơn là sử dụng mô-đun dateparse . Ví dụ là dateparser.parse('16 Jun 2010'), dateparser.parse('12/2/12')hoặcdateparser.parse('2017-5-3')

Hai cách tiếp cận trên sẽ trả về một datetimeđối tượng.

Bước 2

Sử dụng datetimeđối tượng thu được để gọi strptime(format). Ví dụ,

`` `trăn

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.

`` `

Thật khó để quyết định sử dụng định dạng nào. Một cách tốt hơn là để có được một dateđối tượng để gọi isocalendar(). Ví dụ,

`` `trăn

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

`` `

Trong thực tế, bạn sẽ có nhiều khả năng sử dụng date.isocalendar()để chuẩn bị báo cáo hàng tuần, đặc biệt là trong mùa mua sắm "Giáng sinh-Năm mới".


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

Rất nhiều câu trả lời đã được đưa ra, nhưng id muốn thêm vào chúng.

Nếu bạn cần tuần để hiển thị theo kiểu năm / tuần (ví dụ: 1953 - tuần 53 năm 2019, 2001 - tuần 1 năm 2020, v.v.), bạn có thể làm điều này:

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)

Nó sẽ mất năm và tuần hiện tại và long_week_num trong ngày viết bài này sẽ là:

>>> 2006

Tại sao tạo một date()từ đầu? datetime.datetime()trường hợp có một .date()phương pháp cho công việc đó.
Martijn Pieters

Tuy nhiên, đáng lo ngại hơn là câu trả lời của bạn chọn thế kỷ , không phải năm hiện tại. Và nếu bạn định sử dụng định dạng chuỗi cho số tuần, tại sao sau đó không sử dụng định dạng đó để bao gồm cả năm?
Martijn Pieters
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.