Як отримати номер тижня в Python?


339

Як дізнатись, який номер тижня - поточний рік 16 червня (wk24) з Python?


1
@Donal: Один дивиться на 16 червня, інший на 26 червня
interjay

5
Визначте тиждень 1. isocalendar () - не єдиний спосіб зробити це.
Марк Толонен

3
Зауважимо, що вихідний сигнал strftime("%U", d)може відрізнятися від рівня isocalendar(). Наприклад, якщо ви зміните рік на 2004 рік, ви отримаєте 24 тиждень використання strftime()та 25 тиждень використання isocalendar().
moooeeeep

Відповіді:


409

datetime.dateмає isocalendar()метод, який повертає кортеж, що містить календарний тиждень:

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

datetime.date.isocalendar () - це метод екземпляра, який повертає кортеж, що містить рік, число тижня та день тижня у відповідному порядку для даного екземпляра дати.


7
Це допоможе, якщо ви пояснили " [1]" або дали вказівник, де шукати інформацію.
Джонатан Леффлер

5
Напевно, найпростіше - витягнути номер тижня за допомогою стропінгу, найкраще імпортувати час сьогодні = datetime.now () тиждень = сьогодні. Тривалість ("% W")
bipsa

7
Це трохи пізно. Але на моїй машині date(2010, 1, 1).isocalendar()[1]повертається 53. З документів: "Наприклад, 2004 рік починається в четвер, тому перший тиждень ISO 2004 року починається в понеділок, 29 грудня 2003 року, і закінчується в неділю, 4 січня 2004 року, так що date(2003, 12, 29).isocalendar() == (2004, 1, 1)і date(2004, 1, 4).isocalendar() == (2004, 1, 7)".
jclancy

17
isocalendar()це чудово, але будьте впевнені, що ви хочете. Сьогодні - прекрасний приклад. 01.01.2016 дорівнює (2015, 53, 5). now.strftime("%W")і now.strftime("%U")вони рівні тому, 00що часто є бажаним. Приклади STRFTIME
DaveL17

приємно, я щойно додав день, я думаю, що це буде корисним, це було те, за що я вела: D
Віталій Терзієв

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 - це тиждень, що містить 4 січня. Приклади: 01 , 02,…, 53

від: datetime - Основні типи дати та часу - документація на Python 3.7.3

Я дізнався про це звідси . Це працювало для мене в Python 2.7.6


Що ви цитуєте, якийсь посібник з Linux? Про Invalid format stringцю схему говорять Python 2.7.5 та 3.3.2 . Їх документи також не згадують %V.
Всеволод Голованов

3
Вибачте, що не згадав про це, я дістався звідси . Це працювало для мене в Python 2.7.6.
jotacor

2
Чудова відповідь! Я хотів би додати, що якщо вас зацікавило представлення ваших дат '<РІК> - <ISOWEEK>', використовуйте %G-%Vзамість цього %Y-%V. %G- еквівалент ISO року%Y
KenHBS

Мені довелося написати це так, щоб він працював: datetime.datetime (2010, 6, 16). ("% V")
Ейнар

77

Я вірю, що date.isocalendar()це буде відповідь. У цій статті пояснюється математика, що стоїть за календарем ISO 8601. Перегляньте частину date.isocalendar () сторінки дати в документації Python.

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

.isocalendar () повертає 3-кратний з (рік, число wk, день wk). dt.isocalendar()[0]повертає рік, dt.isocalendar()[1]повертає число тижня, dt.isocalendar()[2]повертає день тижня. Простий, як може бути.


4
+1 за посиланням, яке пояснює неінтуїтивний характер тижнів ISO.
Марк Викуп

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#strearch-and-strptime-behavior


9
або% W, якщо ваші тижні починаються з понеділка.
ZeWaren

1
Такий підхід кращий у тих випадках, коли ви не хочете розбивати або конвертувати дату, яка надходить як рядок ... просто передайте рядок у strptime у форматі рядка таким, яким він є, та вкажіть формат у другому аргументі. Гарне рішення. Пам'ятайте:% W, якщо тиждень починається з понеділка.
TheCuriousOne

22

Тиждень ISO, запропонований іншими, є хорошим, але може не відповідати вашим потребам. Передбачається, що кожен тиждень починається з понеділка, що призводить до деяких цікавих аномалій на початку та в кінці року.

Якщо ви бажаєте використовувати визначення, яке говорить, що тиждень 1 - це завжди з 1 по 7 січня, незалежно від дня тижня, використовуйте таке виведення:

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

3
Сказання, що ізокалендарі мають "деякі цікаві аномалії" на початку та в кінці року, здається, трохи занижене. Результати isocalendar дуже вводять в оману (навіть якщо вони фактично невірні згідно зі специфікацією ISO) для деяких значень часу, наприклад, 29 грудня 2014 року, 00:00:00, які відповідно до isocalendar мають річну вартість 2015 року та тижденьNumber 1 (див. мій запис нижче).
Кевін

3
@Kevin, це не помиляється, просто їх визначення не відповідають вашим. ISO вирішив дві речі: по-перше, що весь тиждень з понеділка по неділю буде в тому ж році, по-друге, що рік, що містить більшість днів, буде призначеним. Це призводить до днів тижня навколо початку і кінця року, які переходять у сусідній рік.
Марк Викуп

6
Домовились. Але за визначенням більшості людей, 29 грудня 2014 року, безумовно, не буде 1 тиждень 2015 року. Я просто хотів звернути увагу на це потенційне джерело плутанини.
Кевін

Це саме те, що я шукав. Не про те, як це зробити, а інформацію, що стосується ISO та починаючи з моменту понеділка.
Аміт

19

Як правило, щоб отримати номер поточного тижня (починається з неділі):

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

4
З документації стропінгу ('% U'): "Номер тижня року (неділя як перший день тижня) як десяткове число [00,53]. Усі дні нового року, що передує першій неділі, вважаються бути в тиждень 0. "
Dolan Antenucci

14

Для цілого значення миттєвого тижня року спробуйте:

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

10

Існує багато систем для нумерації тижнів . Нижче наведені найпоширеніші системи, просто поміщені з прикладами коду:

  • ISO : Перший тиждень починається з понеділка і повинен містити 4 січня. Календар календарів ISO вже реалізований в Python:

    >>> from datetime import date
    >>> date(2014, 12, 29).isocalendar()[:2]
    (2015, 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) : Перший тиждень починається з неділі і повинен містити 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]

Це отримує другого члена кортежу, повернутого ізокалендарем на наш номер тижня.

Однак, якщо ви будете використовувати функції дати, які стосуються григоріанського календаря, тільки ізокалендаря не працюватиме! Візьмемо такий приклад:

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

У цьому рядку написано повернути понеділок першого тижня 2014 року як нашу дату. Коли ми використовуємо isocalendar для отримання номера тижня, ми очікуємо повернення того ж тижня, але ми цього не робимо. Замість цього ми отримуємо тиждень № 2. Чому?

1 тиждень за григоріанським календарем - перший тиждень, що містить понеділок. 1 тиждень в ізокалендарі - перший тиждень, що містить четвер. Частковий тиждень на початку 2014 року містить четвер, тож це тиждень 1 за ізокалендарем, а dateдругий тиждень.

Якщо ми хочемо отримати григоріанський тиждень, нам потрібно буде перейти з ізокалендаря на григоріанський. Ось проста функція, яка виконує трюк.

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

Порівняйте з підходом Марка Рансома:

>>> 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 (), не є "невірними" як такими. Наприклад, згідно ISO8601, 2004 рік розпочався 29 грудня 2003 року. Отже, isocalendar () може бути правильним при поверненні 2015 року на 29 грудня 2014 року, але для багатьох цілей людей це буде досить оманливим. .
Кевін

2

Я підсумовую дискусію за два етапи:

  1. Перетворити необроблений формат у datetime об'єкт.
  2. Використовуйте функцію datetimeоб'єкта або dateоб’єкта для обчислення числа тижня.

Розминка

`` пітон

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

`` `

1-й крок

Щоб вручну генерувати datetimeоб’єкт, ми можемо використовувати datetime.datetime(2017,5,3)абоdatetime.datetime.now() .

Але насправді нам зазвичай потрібно проаналізувати існуючий рядок. ми можемо використовувати strptimeфункцію, таку, datetime.strptime('2017-5-3','%Y-%m-%d')у якій вам потрібно вказати формат. Деталі коду іншого формату можна знайти в офіційній документації .

Крім того, більш зручним способом є використання модуля розбору дат . Прикладами є dateparser.parse('16 Jun 2010'), dateparser.parse('12/2/12')абоdateparser.parse('2017-5-3')

Зазначені вище підходи повернуть datetimeоб'єкт.

2-й крок

Використовуйте отриманий datetimeоб’єкт для дзвінка strptime(format). Наприклад,

`` пітон

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(). Наприклад,

`` пітон

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

Дано багато відповідей, але я люблю їх додавати.

Якщо вам потрібен тиждень для відображення у вигляді року / тижня (наприклад, 1953 - 53 тижня 2019, 2001 - 1 тижня 2020 тощо), ви можете зробити це:

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()метод для цієї роботи.
Martijn Pieters

Однак, тривожніше те, що ваша відповідь підбирає століття , а не поточний рік. І якщо ви збираєтесь використовувати формат рядків для тижня, чому тоді не використовувати його для включення року?
Martijn Pieters
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.