/ / Analizar cadena con fecha y zona horaria a UTC datetime: python, datetime, python-3.x, datetime-format, datetimeoffset

Parse string con fecha y zona horaria a UTC datetime: python, datetime, python-3.x, datetime-format, datetimeoffset

Estoy codificando un script de Python 3 que recibe una completafecha con desplazamiento y quiero poder compararla con otra fecha sin desplazamiento. El principal problema al que me estoy enfrentando es que a Python no parece que le gusten los diferentes objetos de fecha y hora de desplazamiento, ya que se queja cuando intentas hacer alguna operación con esos:

>>> date_string
"Wed, 8 May 2013 15:33:29 +0200"
>>> new_date = datetime.strptime(date_string, "%a, %d %b %Y %H:%M:%S %z")
>>> new_date
datetime.datetime(2013, 5, 8, 15, 33, 29, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))
>>> new_date - datetime.today()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can"t subtract offset-naive and offset-aware datetimes

Como una solución que he despojado date_string en dos cadenas, una vez con la fecha y otra con el desplazamiento, creando dos objetos: una fecha y un delta, los resume:

>>> date_string
"Wed, 8 May 2013 15:33:29 +0200"
>>> match = re.match(r"(.*)(s+d{4})",date_string)
>>> match.group(1)
"Wed, 8 May 2013 15:33:29"
>>> match.group(2)
" +0200"
>>> parsed_date = datetime.strptime(match.group(1), "%a, %d %b %Y %H:%M:%S")
>>> match_delta = re.match(r"s+(d{2})(d{2})",match.group(2))
>>> parsed_date_delta = timedelta(minutes=int(match_delta.group(2)),hours=int(match_delta.group(1)))
>>> parsed_date_complete = parsed_date + parsed_date_delta
>>> parsed_date_complete
datetime.datetime(2013, 5, 8, 17, 33, 29)

Con esto puedo obtener una hora final con el desplazamiento correcto aplicado, por lo que cualquier comparación con otro objeto de fecha y hora normal no generaría un error.

Lo que me pregunto es si hay una manera más fácil o más eficiente de lograr esto. La idea es recibir una cadena como esta: Wed, 8 May 2013 15:33:29 +0200 y poder convertirlo en un objeto de fecha y hora sin desplazamiento, por lo que puedo trabajar con tiempos UTC.

EDITAR: Para explicar un poco más el tema, new_date tiene un valor de compensación de +0200 mientras datetime.today() y datetime.utcnow() no tiene ese desplazamiento, por lo que al intentar compararlo o realizar alguna operación, aparece el siguiente error en Python: TypeError: can"t subtract offset-naive and offset-aware datetimes.

Si la fecha es Wed, 8 May 2013 15:33:29 +0200, lo que quiero es una forma de calcular fecha como esta: Wed, 8 May 2013 17:33:29, sin el valor de compensación pero con el tiempo correcto (compensación aplicada al tiempo). De esa manera, ya que no tengo la compensación, puedo hacer cosas libremente con datetime.today() y datetime.utcnow()

Respuestas

1 para la respuesta № 1

No soy un gurú de Python, pero de acuerdo con estos documentos:

método de clase datetime.today()

Devuelve el datetime local actual, con tzinfo Ninguna. ...

No hay zona horaria asociada a la devolución.valor. No está en UTC, el desplazamiento no está especificado. Por lo tanto, tiene sentido que no le permita comparar los dos. El resultado no tendría sentido.

En otras palabras, ¿cuál esperarías que fuera el resultado de esto?

10 May 2013 13:00 +0200  >  10 May 2013 12:00
  • Eso podría ser verdad, porque 13:00 es un mayor valor que 12:00.
  • Eso podría ser falso, porque tal vez el desplazamiento de zona horaria local es -0100, entonces estas comparando los momentos 11:00Z > 13:00Z. Pero quién sabe si incluso queríamos usar el desplazamiento local ya que no especificamos.

Dado que nos referimos a un momento exacto en el lado izquierdo, pero ambiguo a la derecha, la operación da un error.

Es bueno que Python emita un error cuando intentes hacer esto. Otros marcos como .Net hacen algunas suposiciones y devuelven resultados que pueden no ser los que esperabas. (Leer aquí si estás interesado.)

Así que volviendo a tu pregunta, dijiste:

La idea es recibir una cadena como esta: miércoles 8 de mayo de 2013 15:33:29 +0200 y poder convertirla en un objeto de fecha y hora sin desplazamiento, por lo que puedo trabajar con tiempos UTC.

La cadena que tiene ya está reflejando su desplazamiento desde UTC. La forma en que lo estás analizando está bien. Solo necesita compararlo con algo que sea más significativo, como datetime.now(timezone.utc)