create - string to datetime python
¿Cuál es la mejor manera de encontrar el inverso de datetime.isocalendar()? (7)
A partir de Python 3.6 (actualmente en desarrollo ), puede usar las nuevas directivas %G
, %u
y %V
Ver el número 12006 y la documentación actualizada :
%G
ISO 8601 año con siglo representando el año que contiene la mayor parte de la semana ISO (%V
).
%u
Entre semana de ISO 8601 como un número decimal donde 1 es lunes.
%V
ISO 8601 semana como un número decimal con el lunes como el primer día de la semana. La semana 01 es la semana que contiene el 4 de enero.
Dada una cadena con el número del año, número de semana y día de la semana, es fácil analizarlos en una fecha con:
from datetime import date
date.strptime(''2002 01 1'', ''%G %V %u'')
o como una función con entradas enteras:
from datetime import date
def date_from_isoweek(iso_year, iso_weeknumber, iso_weekday):
return date.strptime(
''{:04d} {:02d} {:d}''.format(iso_year, iso_weeknumber, iso_weekday)
''%G %V %u'')
El método python datetime.isocalendar()
devuelve una tupla (ISO_year, ISO_week_number, ISO_weekday)
para el objeto datetime
dado. ¿Hay una función inversa correspondiente? Si no es así, ¿existe una manera fácil de calcular una fecha dada un año, un número de semana y un día de la semana?
Comenzando en Python 3.6, datetime.strptime()
soportará las directivas %G
, %V
y %u
, por lo que simplemente puede hacer datetime.strptime(''2015 1 2'', ''%G %V %u'').date()
Ver: https://hg.python.org/cpython/rev/acdebfbfbdcf
Para las próximas personas que vienen aquí, una versión más corta y de una sola definición de la buena solución de Ben:
def iso_to_gregorian(iso_year, iso_week, iso_day):
jan4 = datetime.date(iso_year, 1, 4)
start = jan4 - datetime.timedelta(days=jan4.isoweekday()-1)
return start + datetime.timedelta(weeks=iso_week-1, days=iso_day-1)
Recientemente tuve que resolver este problema yo mismo, y se me ocurrió esta solución:
import datetime
def iso_year_start(iso_year):
"The gregorian calendar date of the first day of the given ISO year"
fourth_jan = datetime.date(iso_year, 1, 4)
delta = datetime.timedelta(fourth_jan.isoweekday()-1)
return fourth_jan - delta
def iso_to_gregorian(iso_year, iso_week, iso_day):
"Gregorian calendar date for the given ISO year, week and day"
year_start = iso_year_start(iso_year)
return year_start + datetime.timedelta(days=iso_day-1, weeks=iso_week-1)
Algunos casos de prueba:
>>> iso = datetime.date(2005, 1, 1).isocalendar()
>>> iso
(2004, 53, 6)
>>> iso_to_gregorian(*iso)
datetime.date(2005, 1, 1)
>>> iso = datetime.date(2010, 1, 4).isocalendar()
>>> iso
(2010, 1, 1)
>>> iso_to_gregorian(*iso)
datetime.date(2010, 1, 4)
>>> iso = datetime.date(2010, 1, 3).isocalendar()
>>> iso
(2009, 53, 7)
>>> iso_to_gregorian(*iso)
datetime.date(2010, 1, 3)
Tenga en cuenta que% W es la semana # (0-53) que NO ES LO MISMO que la semana ISO (1-53). Habrá casos extremos donde% W no funcionará.
EDITAR: ignora esto, los casos extremos son un dolor. Ve con la solución de Ben.
Ok, en una inspección más cercana noté que strptime
tiene %W
y %w
parámetros, por lo que el siguiente funciona:
def fromisocalendar(y,w,d):
return datetime.strptime( "%04dW%02d-%d"%(y,w-1,d), "%YW%W-%w")
Un par de errores: el número de semana ISO comienza en 1
, mientras que %W
comienza en 0
. El día de la semana ISO comienza en 1
(lunes), que es lo mismo que %w
, por lo que el domingo probablemente tendría que ser 0
, no 7
...
import datetime
def iso_to_gregorian(iso_year, iso_week, iso_day):
"Gregorian calendar date for the given ISO year, week and day"
fourth_jan = datetime.date(iso_year, 1, 4)
_, fourth_jan_week, fourth_jan_day = fourth_jan.isocalendar()
return fourth_jan + datetime.timedelta(days=iso_day-fourth_jan_day, weeks=iso_week-fourth_jan_week)
Esto fue adaptado de la muy buena respuesta de @ BenJames. No tienes que saber el primer día del año. Solo tiene que saber un ejemplo de una fecha que ciertamente está en el mismo año ISO, y la semana y el día del calendario ISO de esa fecha.
El 4 de enero es simplemente un ejemplo, porque, como señaló Ben, el 4 de enero siempre pertenece al mismo año ISO y al año gregoriano, y es el primer día del año para hacerlo.
Como las semanas tienen la misma longitud, puede restar los días y semanas entre el ISO de la fecha que desea y el ISO de la fecha que conoce en ambos formularios, y agregar esa cantidad de días y semanas. (No importa si estos números son positivos o negativos, por lo que podría elegir otro "día fijo" como el 28 de diciembre).
Editar
Corregí esto porque, como señaló útilmente @JoSo, el primer día del año gregoriano que también pertenece al año ISO es el 4 de enero y no el 5 de enero. Como dice la explicación, no importa qué fecha se elija como punto de referencia, pero elegir el 4 de enero hace que esta elección sea menos "mágica".