Tiempo ISO (ISO 8601) en Python

Tengo un archivo En Python, me gustaría aprovechar su tiempo de creación y convertirlo en una cadena de tiempo ISO (ISO 8601) a la vez que se conserva el hecho de que se creó en la zona horaria del este (ET) .

¿Cómo tomo el ctime del archivo y lo convierto en una cadena de tiempo ISO que indica la Zona Horaria del Este (y toma en cuenta el horario de verano, si es necesario)?

Local a ISO 8601:

import datetime datetime.datetime.now().isoformat() 

UTC a ISO 8601:

 import datetime datetime.datetime.utcnow().isoformat() 

Local a ISO 8601 sin microsegundo:

 import datetime datetime.datetime.now().replace(microsecond=0).isoformat() 

UTC a ISO 8601 con información de Zona horaria (Python 3):

 import datetime datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).isoformat() 

Local a ISO 8601 con información de Zona horaria (Python 3):

 import datetime, time # Calculate the offset taking into account daylight saving time utc_offset_sec = time.altzone if time.localtime().tm_isdst else time.timezone utc_offset = datetime.timedelta(seconds=-utc_offset_sec) datetime.datetime.now().replace(tzinfo=datetime.timezone(offset=utc_offset)).isoformat() 

Para Python 2, vea y use pytz .

Encontré el datetime.isoformat en la documentación . Parece hacer lo que quieres:

 datetime.isoformat([sep]) Return a string representing the date and time in ISO 8601 format, YYYY-MM-DDTHH:MM:SS.mmmmmm or, if microsecond is 0, YYYY-MM-DDTHH:MM:SS If utcoffset() does not return None, a 6-character string is appended, giving the UTC offset in (signed) hours and minutes: YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or, if microsecond is 0 YYYY-MM-DDTHH:MM:SS+HH:MM The optional argument sep (default 'T') is a one-character separator, placed between the date and time portions of the result. For example, >>> >>> from datetime import tzinfo, timedelta, datetime >>> class TZ(tzinfo): ... def utcoffset(self, dt): return timedelta(minutes=-399) ... >>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ') '2002-12-25 00:00:00-06:39' 

ISO 8601 Representación de Tiempo

La norma internacional ISO 8601 describe una representación de cadena para fechas y horas. Dos ejemplos simples de este formato son

 2010-12-16 17:22:15 20101216T172215 

(que ambos representan el 16 de diciembre de 2010), pero el formato también permite tiempos de resolución por debajo del segundo y especificar zonas horarias. Por supuesto, este formato no es específico de Python, pero es bueno para almacenar fechas y horas en un formato portátil. Los detalles sobre este formato se pueden encontrar en la entrada de Markus Kuhn .

Recomiendo el uso de este formato para almacenar tiempos en archivos.

Una forma de obtener la hora actual en esta representación es usar strftime desde el módulo de hora en la biblioteca estándar de Python:

 >>> from time import strftime >>> strftime("%Y-%m-%d %H:%M:%S") '2010-03-03 21:16:45' 

Puede usar el constructor strptime de la clase datetime:

 >>> from datetime import datetime >>> datetime.strptime("2010-06-04 21:08:12", "%Y-%m-%d %H:%M:%S") datetime.datetime(2010, 6, 4, 21, 8, 12) 

El más robusto es el módulo mxDateTime de Egenix:

 >>> from mx.DateTime.ISO import ParseDateTimeUTC >>> from datetime import datetime >>> x = ParseDateTimeUTC("2010-06-04 21:08:12") >>> datetime.fromtimestamp(x) datetime.datetime(2010, 3, 6, 21, 8, 12) 

Referencias

  • La documentación del módulo de tiempo de Python.

  • La documentación de la clase datetime de Python.

  • La clase mxDateTime de Egenix

Aquí está lo que uso para convertir al formato de fecha y hora XSD:

 from datetime import datetime datetime.now().replace(microsecond=0).isoformat() # You get your ISO string 

Encontré esta pregunta cuando buscaba el formato de fecha y hora de XSD ( xs:dateTime ). Necesitaba eliminar los microsegundos de la isoformat .

El formato de hora ISO 8601 no almacena un nombre de zona horaria, solo se conserva el desplazamiento UTC correspondiente.

Para convertir un archivo ctime en una cadena de tiempo ISO 8601 mientras conserva el desplazamiento UTC en Python 3:

 >>> import os >>> from datetime import datetime, timezone >>> ts = os.path.getctime(some_file) >>> dt = datetime.fromtimestamp(ts, timezone.utc) >>> dt.astimezone().isoformat() '2015-11-27T00:29:06.839600-05:00' 

El código supone que su zona horaria local es la zona horaria del este (ET) y que su sistema proporciona un desplazamiento UTC correcto para la marca de tiempo POSIX ( ts ) dada, es decir, Python tiene acceso a una base de datos histórica de la zona horaria en su sistema o la zona horaria tenía Las mismas reglas en una fecha determinada.

Si necesita una solución portátil; use el módulo pytz que proporciona acceso a la base de datos tz :

 >>> import os >>> from datetime import datetime >>> import pytz # pip install pytz >>> ts = os.path.getctime(some_file) >>> dt = datetime.fromtimestamp(ts, pytz.timezone('America/New_York')) >>> dt.isoformat() '2015-11-27T00:29:06.839600-05:00' 

El resultado es el mismo en este caso.

Si necesita el nombre de la zona horaria / abreviación / ID de zona, guárdelo por separado.

 >>> dt.astimezone().strftime('%Y-%m-%d %H:%M:%S%z (%Z)') '2015-11-27 00:29:06-0500 (EST)' 

Nota: no : en el desplazamiento UTC y la abreviatura de zona horaria EST no es parte del formato de hora ISO 8601. No es único.

Diferentes bibliotecas / diferentes versiones de la misma biblioteca pueden usar diferentes reglas de zona horaria para la misma fecha / zona horaria. Si es una fecha futura, las reglas pueden ser desconocidas todavía. En otras palabras, la misma hora UTC puede corresponder a una hora local diferente, dependiendo de las reglas que use; guardar una hora en formato ISO 8601 preserva la hora UTC y la hora local que corresponde a las reglas de zona horaria actuales en uso en su plataforma . Es posible que deba volver a calcular la hora local en una plataforma diferente si tiene reglas diferentes.

Deberá usar os.stat para obtener el tiempo de creación del archivo y una combinación de time.strftime y time.timezone para el formateo:

 >>> import time >>> import os >>> t = os.stat('C:/Path/To/File.txt').st_ctime >>> t = time.localtime(t) >>> formatted = time.strftime('%Y-%m-%d %H:%M:%S', t) >>> tz = str.format('{0:+06.2f}', float(time.timezone) / 3600) >>> final = formatted + tz >>> >>> final '2008-11-24 14:46:08-02.00' 

ISO 8601 permite una representación compacta sin separadores, excepto la T , así que me gusta usar esta frase de una línea para obtener una cadena de marca de tiempo rápida:

 >>> datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%S.%fZ") '20180905T140903.591680Z' 

Si no necesita los microsegundos, simplemente omita la parte .%f :

 >>> datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") '20180905T140903Z' 

Para hora local:

 >>> datetime.datetime.now().strftime("%Y%m%dT%H%M%S") '20180905T140903' 

Corríjame si me equivoco (no lo estoy), pero el desplazamiento de UTC cambia con el horario de verano. Así que deberías usar

 tz = str.format('{0:+06.2f}', float(time.altzone) / 3600) 

También creo que el signo debe ser diferente:

 tz = str.format('{0:+06.2f}', -float(time.altzone) / 3600) 

Podría estar equivocado, pero no lo creo.

Estoy de acuerdo con Jarek, y además tengo en cuenta que el carácter separador de compensación ISO es dos puntos, por lo que creo que la respuesta final debería ser:

 isodate.datetime_isoformat(datetime.datetime.now()) + str.format('{0:+06.2f}', -float(time.timezone) / 3600).replace('.', ':') 

He desarrollado esta función:

 def iso_8601_format(dt): """YYYY-MM-DDThh:mm:ssTZD (1997-07-16T19:20:30-03:00)""" if dt is None: return "" fmt_datetime = dt.strftime('%Y-%m-%dT%H:%M:%S') tz = dt.utcoffset() if tz is None: fmt_timezone = "+00:00" else: fmt_timezone = str.format('{0:+06.2f}', float(tz.total_seconds() / 3600)) return fmt_datetime + fmt_timezone 
 import datetime, time def convert_enddate_to_seconds(self, ts): """Takes ISO 8601 format(string) and converts into epoch time.""" dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+\ datetime.timedelta(hours=int(ts[-5:-3]), minutes=int(ts[-2:]))*int(ts[-6:-5]+'1') seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0 return seconds >>> import datetime, time >>> ts = '2012-09-30T15:31:50.262-08:00' >>> dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+ datetime.timedelta(hours=int(ts[-5:-3]), minutes=int(ts[-2:]))*int(ts[-6:-5]+'1') >>> seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0 >>> seconds 1348990310.26