Obtener la fecha del número de la semana

88

Por favor, ¿qué pasa con mi código?

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

Muestra "2013-01-01 00:00:00", Gracias.

Ali dijo OMAR
fuente

Respuestas:

175

Un número de semana no es suficiente para generar una fecha; también necesitas un día de la semana. Agregar un valor predeterminado:

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

El patrón -1y -%wle dice al analizador que elija el lunes de esa semana. Esto produce:

2013-07-01 00:00:00

%Wutiliza el lunes como primer día de la semana. Si bien puede elegir su propio día de la semana, es posible que obtenga resultados inesperados si se desvía de ese.

Consulte la sección de comportamiento strftime()ystrptime() en la documentación, nota al pie 4:

Cuando se usan con el strptime()método, %Uy %Wsolo se usan en cálculos cuando se especifican el día de la semana y el año.

Tenga en cuenta que si su número de semana es una fecha de semana ISO , ¡querrá usarla %G-W%V-%uen su lugar! Esas directivas requieren Python 3.6 o más reciente.

Martijn Pieters
fuente
Desearía poder darte más de 1 voto ... Estaba golpeándome la cabeza para averiguar por qué no estaba funcionando.
Islam Q.
2
No 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". La 1ª y 2ª semana de 2018 tienen la misma fecha de inicio.
ozw1z5rd
2
@ ozw1z5rd: eso se debe a que no hay semana 0 en 2018. La semana 0 es la semana parcial antes del primer lunes del año; en 2018 el primer lunes es el 1 de enero. En otras palabras, su cadena de entrada es el problema aquí, no la técnica, y Python ha corregido el error para interpretar que W0 significa W1.
Martijn Pieters
@ ozw1z5rd: Si esto es un problema para su aplicación, necesitará un caso especial de esos años; 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 ya admite definiciones de semana ISO 8601, uso %G(año durante la mayor parte de la semana) y %Ven ese caso.
Martijn Pieters
26

Para completar las otras respuestas, si está utilizando números de semana ISO , esta cadena es apropiada (para obtener el lunes de un número de semana ISO dado):

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

%G, %V, %uSon equivalentes ISO de %Y, %W, %w, así que esto salidas:

2013-06-24 00:00:00

Disponible en Python 3.6+; de docs .

Luka Kikelj
fuente
14

En Python 3.8 existe lo útil datetime.date.fromisocalendar:

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

En versiones anteriores de Python (3.7-), el cálculo puede usar la información de datetime.date.isocalendarpara calcular la semana que cumple con la norma 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 funcionan también con datetime.datetime.

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

Agregar 1 como día de la semana producirá el inicio exacto de la semana actual. La adición de timedelta (días = 6) le dará el fin de semana.

datetime.datetime(2018, 7, 23)
Senthilkumar C
fuente
@Senthikumar C eso debería ser como a continuaciónres = datetime.datetime.strptime("2018 W30 w1", "%Y W%W w%w")
MD Alauddin Al-Amin
1

En caso de que tenga el número anual de semanas, simplemente agregue el número de semanas al primer día del año.

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