Obter data do número da semana

88

Por favor, o que há de errado com meu código:

import datetime
d = "2013-W26"
r = datetime.datetime.strptime(d, "%Y-W%W")
print(r)

Exibir "2013-01-01 00:00:00", Obrigado.

Ali SAID OMAR
fonte

Respostas:

175

Um número de semana não é suficiente para gerar uma data; você também precisa de um dia da semana. Adicione um padrão:

import datetime
d = "2013-W26"
r = datetime.datetime.strptime(d + '-1', "%Y-W%W-%w")
print(r)

O padrão -1e -%wdiz ao analisador para escolher a segunda-feira daquela semana. Isso resulta em:

2013-07-01 00:00:00

%Wusa segunda-feira como o primeiro dia da semana. Embora você possa escolher seu próprio dia da semana, poderá obter resultados inesperados se não fizer isso.

Consulte a seção de comportamento strftime()estrptime() na documentação, nota de rodapé 4:

Quando usados ​​com o strptime()método, %Ue %Wsão usados ​​apenas em cálculos quando o dia da semana e o ano são especificados.

Observe, se o número da sua semana for uma data da semana ISO , você vai querer usar %G-W%V-%u! Essas diretivas requerem Python 3.6 ou mais recente.

Martijn Pieters
fonte
Eu gostaria de poder dar a você mais de 1 voto ... Eu estava batendo minha cabeça para descobrir por que não estava funcionando.
Islam Q.
2
Não funciona. datetime.datetime.strptime ("2018-W0-0", "% YW% W-% w") == datetime.datetime.strptime ("2018-W1-0", "% YW% W-% w") -> "2018-01-07 00:00:00". 1ª e 2ª semanas de 2018 têm a mesma data de início.
ozw1z5
2
@ ozw1z5rd: isso porque não há semana 0 em 2018. A semana 0 é a semana parcial antes da primeira segunda-feira do ano; em 2018, a primeira segunda-feira é 1º de janeiro. Em outras palavras, sua string de entrada é o problema aqui, não a técnica, e o Python corrigiu o erro para interpretar W0 para significar W1.
Martijn Pieters
@ ozw1z5rd: Se isso for um problema para seu aplicativo, você precisará considerar casos especiais como esses anos; if d.endswith('-W0') and r.day == 7: raise ValueError('Invalid date string, No week 0 in {}'.format(r.year))
Martijn Pieters
1
@darda: Python 3.6 já suporta definições de semana ISO 8601, use %G(ano na maior parte da semana) e %Vnesse caso.
Martijn Pieters
27

Para completar as outras respostas - se você estiver usando números de semana ISO , esta string é apropriada (para obter a segunda-feira de um determinado número de semana ISO):

import datetime
d = '2013-W26'
r = datetime.datetime.strptime(d + '-1', '%G-W%V-%u')
print(r)

%G, %V, %uSão equivalentes ISO de %Y, %W, %w, de modo que este saídas:

2013-06-24 00:00:00

Disponível em Python 3.6+; de docs .

Luka Kikelj
fonte
14

No Python 3.8, há o prático datetime.date.fromisocalendar:

>>> from datetime import date
>>> date.fromisocalendar(2020, 1, 1)  # (year, week, day of week)
datetime.date(2019, 12, 30, 0, 0)

Em versões mais antigas do Python (3.7-), o cálculo pode usar as informações de datetime.date.isocalendarpara descobrir a semana em conformidade com ISO8601:

from datetime import date, timedelta

def monday_of_calenderweek(year, week):
    first = date(year, 1, 1)
    base = 1 if first.isocalendar()[1] == 1 else 8
    return first + timedelta(days=base - first.isocalendar()[2] + 7 * (week - 1))

Ambos funcionam também com datetime.datetime.

Jens W. Klein
fonte
6
import datetime
res = datetime.datetime.strptime("2018 W30 w1", "%Y %W w%w")
print res

Adicionar 1 como dia da semana resultará no início exato da semana atual. A adição de timedelta (dias = 6) dará a você o fim de semana.

datetime.datetime(2018, 7, 23)
Senthilkumar C
fonte
@Senthikumar C que deve ser como abaixores = datetime.datetime.strptime("2018 W30 w1", "%Y W%W w%w")
MD Alauddin Al-Amin
1

Caso você tenha o número da semana anual, basta adicionar o número de semanas ao primeiro dia do ano.

>>> import datetime
>>> from dateutil.relativedelta import relativedelta

>>> week = 40
>>> year = 2019
>>> date = datetime.date(year,1,1)+relativedelta(weeks=+week)
>>> date
datetime.date(2019, 10, 8)
dimosbele
fonte
0

Aqui está uma função útil, incluindo o problema com a semana zero.

Ron
fonte