Jak uzyskać numer tygodnia w Pythonie?

339

Jak dowiedzieć się, jaki numer tygodnia jest w bieżącym roku 16 czerwca (wk24) w Pythonie?

Gerry
źródło
1
@Donal: Jeden patrzy na 16 czerwca, a drugi na 26 czerwca.
interjay
5
Zdefiniuj tydzień 1. isocalendar () to nie jedyny sposób, aby to zrobić.
Mark Tolonen,
3
Zauważ, że wyjście strftime("%U", d)może różnić się od isocalendar(). Na przykład, jeśli zmienisz rok na 2004, otrzymasz 24 tydzień korzystania strftime()i tydzień 25 korzystania isocalendar().
moooeeeep

Odpowiedzi:

409

datetime.datema isocalendar()metodę, która zwraca krotkę zawierającą tydzień kalendarzowy:

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

datetime.date.isocalendar () to metoda instancji zwracająca krotkę zawierającą rok, numer tygodnia i dzień tygodnia w odpowiedniej kolejności dla danej instancji daty.

Horst Gutmann
źródło
7
Byłoby to pomocne, gdybyś wyjaśnił „ [1]” lub wskazał miejsce, gdzie szukać informacji.
Jonathan Leffler,
5
Wydaje mi się, że najłatwiej jest wyodrębnić numer tygodnia za pomocą strftime, najlepszy import datetime dzisiaj = datetime.now () tydzień = Today.strftime ("% W")
bipsa
7
To trochę za późno. Ale na mojej maszynie date(2010, 1, 1).isocalendar()[1]wraca 53. Z dokumentów: „Na przykład 2004 r. Rozpoczyna się w czwartek, więc pierwszy tydzień roku ISO 2004 rozpoczyna się w poniedziałek, 29 grudnia 2003 r., A kończy w niedzielę, 4 stycznia 2004 r., A więc date(2003, 12, 29).isocalendar() == (2004, 1, 1)i date(2004, 1, 4).isocalendar() == (2004, 1, 7).”
jclancy
17
isocalendar()jest świetne, ale upewnij się, że tego właśnie chcesz. Dzisiaj jest doskonałym przykładem. 01.01.2016 jest równa (2015, 53, 5). now.strftime("%W")i now.strftime("%U")są równe, 00co jest często tym, czego się chce. Przykłady
STRFTIME
fajnie, właśnie dodałem dzień, który myślę, że będzie pomocny, to było to, czego szukałem: D
Vitaliy Terziev
124

Numer tygodnia można uzyskać bezpośrednio z datetime jako ciąg.

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

Możesz także uzyskać różne „typy” numeru tygodnia w roku, zmieniając strftimeparametr dla:

%U- Numer tygodnia w roku (niedziela jako pierwszy dzień tygodnia) jako liczba dziesiętna wypełniona zerami. Wszystkie dni w nowym roku poprzedzającym pierwszą niedzielę uważa się za tydzień 0. Przykłady: 00 , 01,…, 53

%W- Numer tygodnia w roku ( poniedziałek jako pierwszy dzień tygodnia) jako liczba dziesiętna. Wszystkie dni w nowym roku poprzedzającym pierwszy poniedziałek uważa się za tydzień 0. Przykłady: 00 , 01,…, 53

[...]

( Dodano w Pythonie 3.6, przeniesiono do niektórych dystrybucji Pythona 2.7 ). Kilka dodatkowych dyrektyw niewymaganych przez standard C89 zostało zawartych dla wygody. Wszystkie te parametry odpowiadają wartościom daty ISO 8601. Mogą nie być dostępne na wszystkich platformach, jeśli są używane z tą strftime()metodą.

[...]

%V- ISO 8601 tydzień jako liczba dziesiętna z poniedziałkiem jako pierwszym dniem tygodnia. Tydzień 01 to tydzień zawierający 4 stycznia. Przykłady: 01 , 02,…, 53

from: datetime - Podstawowe typy daty i godziny - Dokumentacja Python 3.7.3

Dowiedziałem się o tym stąd . Działa dla mnie w Pythonie 2.7.6

jotacor
źródło
Co cytujesz, jakąś instrukcję dla Linuksa? Python 2.7.5 i 3.3.2 mówią Invalid format stringo tym wzorcu. Ich dokumenty też nie wspominają %V.
Vsevolod Golovanov
3
Przepraszam, nie wspomniałem o tym, mam stąd . Działa dla mnie w Pythonie 2.7.6.
jotacor
2
Świetna odpowiedź! Chciałbym dodać, że jeśli interesuje Cię reprezentacja twoich dat „<ROC> - <ISOWEEK>”, użyj %G-%Vzamiast %Y-%V. %Gjest odpowiednikiem roku ISO%Y
KenHBS
Musiałem napisać to w ten sposób, aby działało: datetime.datetime (2010, 6, 16) .strftime ("% V") lub jak ten datetime.datetime (2010, 6, 16) .date (). Strftime („% V”)
Einar
77

Wierzę, że date.isocalendar()to będzie odpowiedź. W tym artykule wyjaśniono matematykę związaną z kalendarzem ISO 8601. Sprawdź część date.isocalendar () strony datetime dokumentacji Pythona.

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

.isocalendar () zwraca 3-krotkę z (rok, wk num, wk dzień). dt.isocalendar()[0]zwraca rok, dt.isocalendar()[1]zwraca numer tygodnia, dt.isocalendar()[2]zwraca dzień tygodnia. Proste, jak może być.

Byron Sommardahl
źródło
4
+1 za link, który wyjaśnia nieintuicyjny charakter tygodni ISO.
Mark Ransom,
27

Oto kolejna opcja:

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

który drukuje 24 .

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

Bart Kiers
źródło
9
lub% W, jeśli tygodnie zaczynają się w poniedziałki.
ZeWaren,
1
Takie podejście jest lepsze w przypadkach, w których nie chcesz dzielić ani konwertować daty, która jest ciągiem ... po prostu przekaż ciąg w strptime w formacie ciągłym i określ format w drugim argumencie. Dobre rozwiązanie. Pamiętaj:% W, jeśli tydzień zaczyna się w poniedziałki.
TheCuriousOne
22

Tydzień ISO sugerowany przez innych jest dobry, ale może nie pasować do twoich potrzeb. Zakłada się, że każdy tydzień zaczyna się od poniedziałku, co prowadzi do interesujących anomalii na początku i na końcu roku.

Jeśli wolisz użyć definicji, która mówi, że tydzień 1 to zawsze od 1 stycznia do 7 stycznia, niezależnie od dnia tygodnia, użyj pochodnej w następujący sposób:

>>> testdate=datetime.datetime(2010,6,16)
>>> print(((testdate - datetime.datetime(testdate.year,1,1)).days // 7) + 1)
24
Mark Ransom
źródło
3
Mówienie, że izocalendar ma „kilka interesujących anomalii” na początku i na końcu roku, wydaje się nieco niedopowiedzeniem. wyniki isocalendar są bardzo mylące (nawet jeśli w rzeczywistości nie są nieprawidłowe zgodnie ze specyfikacją ISO) w przypadku niektórych wartości daty i godziny, takich jak 29 grudnia 2014 r., 00:00:00, które według isocalendar mają wartość roku 2015 i tydzień Numer 1 (patrz mój wpis poniżej).
Kevin,
3
@Kevin, to nie jest źle, po prostu ich definicje nie pasują do twojej. ISO zdecydowało o dwóch rzeczach: po pierwsze, że cały tydzień od poniedziałku do niedzieli będzie w tym samym roku, po drugie, że rok zawierający większość dni zostanie wyznaczony. Prowadzi to do dni tygodnia na początku i na końcu roku, które przechodzą do roku sąsiedniego.
Mark Ransom,
6
Zgoda. Ale według definicji większości ludzi 29 grudnia 2014 roku zdecydowanie nie będzie pierwszym tygodniem 2015 roku. Chciałem tylko zwrócić uwagę na to potencjalne źródło zamieszania.
Kevin
Właśnie tego szukałem. Nie chodzi o to, jak to zrobić, ale o informacje dotyczące ISO i rozpoczęcie od poniedziałku.
Amit Amola,
19

Ogólnie, aby uzyskać numer bieżącego tygodnia (zaczyna się od niedzieli):

from datetime import *
today = datetime.today()
print today.strftime("%U")
Chaggster
źródło
4
Z dokumentacji strftime („% U”): „Numer tygodnia w roku (niedziela jako pierwszy dzień tygodnia) jako liczba dziesiętna [00,53] Uwzględnia się wszystkie dni w nowym roku poprzedzającym pierwszą niedzielę być w tygodniu 0. ”
Dolan Antenucci
14

Aby uzyskać wartość całkowitą chwilowego tygodnia w roku, spróbuj:

import datetime
datetime.datetime.utcnow().isocalendar()[1]
użytkownik2099484
źródło
10

Istnieje wiele systemów numerowania tygodni . Oto najczęściej stosowane systemy z przykładami kodu:

  • ISO : Pierwszy tydzień zaczyna się od poniedziałku i musi zawierać 4 stycznia. Kalendarz ISO jest już zaimplementowany w Pythonie:

    >>> from datetime import date
    >>> date(2014, 12, 29).isocalendar()[:2]
    (2015, 1)
  • North American : Pierwszy tydzień rozpoczyna się w niedzielę i musi zawierać 1 stycznia. Poniższy kod to moja zmodyfikowana wersja implementacji kalendarza ISO Pythona dla systemu w Ameryce Północnej:

    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) : Pierwszy tydzień rozpoczyna się w niedzielę i musi zawierać 4 stycznia. Stworzyłem pakiet epiweeks specjalnie dla tego systemu numeracji (obsługuje także system ISO). Oto przykład:
    >>> from datetime import date
    >>> from epiweeks import Week
    >>> Week.fromdate(date(2014, 12, 29))
    (2014, 53)
dralshehri
źródło
8

Jeśli używasz tylko numeru tygodnia isocalendar na całym forum, wystarczą następujące informacje:

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

Pobiera to drugiego członka krotki zwróconej przez isocalendar dla naszego numeru tygodnia.

Jeśli jednak zamierzasz używać funkcji daty, które działają w kalendarzu gregoriańskim, sam izocalendar nie będzie działał! Weź następujący przykład:

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

Ciąg tutaj mówi, aby zwrócić poniedziałek pierwszego tygodnia 2014 jako naszą datę. Gdy używamy isocalendar do pobrania numeru tygodnia tutaj, spodziewalibyśmy się zwrotu tego samego numeru tygodnia, ale nie robimy tego. Zamiast tego otrzymujemy tygodniowy numer 2. Dlaczego?

Tydzień 1 w kalendarzu gregoriańskim to pierwszy tydzień zawierający poniedziałek. Tydzień 1 w isocalendar to pierwszy tydzień zawierający czwartek. Częściowy tydzień na początku 2014 r. Zawiera czwartek, więc jest to tydzień 1 według isocalendar i tworzeniadate drugi tydzień.

Jeśli chcemy wziąć tydzień gregoriański, musimy przejść z izokalendarza na gregoriański. Oto prosta funkcja, która załatwia sprawę.

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
meesterguyperson
źródło
6

Możesz wypróbować dyrektywę% W jak poniżej:

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

„% W”: numer tygodnia w roku (poniedziałek jako pierwszy dzień tygodnia) jako liczba dziesiętna. Wszystkie dni w nowym roku poprzedzającym pierwszy poniedziałek uważa się za tydzień 0. (00, 01, ..., 53)

Tung Nguyen
źródło
2

isocalendar () zwraca niepoprawne wartości roku i numeru tygodnia dla niektórych dat:

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

Porównaj z podejściem Marka Ransoma:

>>> 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
Kevin
źródło
3
Patrząc na niektóre łącza dotyczące kalendarza iso8601 (np. Staff.science.uu.nl/~gent0113/calendar/isocalendar.htm ), widzę, że wartości roku i numeru tygodnia zwrócone przez isocalendar () jako takie nie są „niepoprawne”. Na przykład w ISO8601 rok 2004 rozpoczął się 29 grudnia 2003 r. Tak więc funkcja isocalendar () może być poprawna, zwracając rok 2015 na 29 grudnia 2014 r., Ale dla wielu osób będzie to dość mylące .
Kevin
2

Podsumowuję dyskusję na dwa etapy:

  1. Konwertuj surowy format na datetimeobiekt.
  2. Użyj funkcji datetimeobiektu lub dateobiektu, aby obliczyć numer tygodnia.

Rozgrzać się

`` python

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

``

1. krok

Aby ręcznie wygenerować datetimeobiekt, możemy użyć datetime.datetime(2017,5,3)lubdatetime.datetime.now() .

Ale w rzeczywistości zwykle musimy przeanalizować istniejący ciąg. możemy użyć strptimefunkcji, na przykład datetime.strptime('2017-5-3','%Y-%m-%d')w której musisz określić format. Szczegółowy kod innego formatu można znaleźć w oficjalnej dokumentacji .

Alternatywnie, wygodniejszym sposobem jest użycie modułu dateparse . Przykładami są dateparser.parse('16 Jun 2010'), dateparser.parse('12/2/12')lubdateparser.parse('2017-5-3')

Powyższe dwa podejścia zwrócą datetimeobiekt.

2. krok

Użyj uzyskanego datetimeobiektu do wywołania strptime(format). Na przykład,

`` 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.

``

Bardzo trudno jest zdecydować, którego formatu użyć. Lepszym sposobem jest datewywołanie obiektu isocalendar(). Na przykład,

`` 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

``

W rzeczywistości będziesz bardziej skłonny do date.isocalendar()przygotowania cotygodniowego raportu, zwłaszcza w sezonie zakupowym „Boże Narodzenie-Nowy Rok”.

Yuchao Jiang
źródło
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.............!!!") 
Wael Abo Elhassan
źródło
-1

Podano wiele odpowiedzi, ale chciałbym je dodać.

Jeśli potrzebujesz, aby tydzień był wyświetlany jako styl roku / tygodnia (np. 1953 - 53 tydzień 2019, 2001 - 1 tydzień 2020 itd.), Możesz to zrobić:

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)

Zajmie to bieżący rok i tydzień, a long_week_num w dniu pisania będzie to:

>>> 2006
Simo Todorov
źródło
Po co tworzyć date()od zera? datetime.datetime()instancje mają .date()metodę dla tego zadania.
Martijn Pieters
Bardziej niepokojące jest jednak to, że twoja odpowiedź wybiera wiek , a nie bieżący rok. A jeśli zamierzasz użyć formatowania ciągów dla numeru tygodnia, to dlaczego nie użyć tego również do włączenia roku?
Martijn Pieters