2010-01-27 48 views
128

Tengo un archivo. En Python, me gustaría tomar su tiempo de creación, y convertirlo a ISO time (ISO 8601) stringconservando el hecho de que fue creado en la Zona Horaria del Este.ISO Time (ISO 8601) en Python?

¿Cómo tomo el tiempo del archivo y lo convierto en una cadena de tiempo ISO, que indica la zona horaria del este (y tiene en cuenta el horario de verano, si es necesario)?

+0

posible duplicado de (http://stackoverflow.com/questions/969285/ how-do-i-translate-a-iso-8601-datetime-string-into-a-python-datetime-object) –

+7

@ Nick- Enlace útil, pero no es un duplicado; pregunta por la conversión en el otro sentido. – Yarin

+1

@ Joseph- Acabo de preguntar esto en lo que respecta a RFC 3999- debería funcionar para esto - [Generar RFC 3339 marca de tiempo en Python] (http://stackoverflow.com/q/8556398/165673) – Yarin

Respuesta

9

Tendrá que utilizar os.stat para obtener la hora de creación del archivo y una combinación de time.strftime y time.timezone para el formato:

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

EDIT: cambiaron de gmtime() a localtime().

+0

¿La zona horaria cuenta para el horario de verano? ¿hora? Parece que tz será el mismo independientemente del horario de verano o no. –

+2

Será cualquier compensación que esté actualmente en vigencia. Si DST está activo, tendrá un desplazamiento diferente de cuando DST no lo está. –

4

Corrígeme si me equivoco (no lo estoy), pero el desplazamiento de UTC cambia con el horario de verano. Por lo que debe utilizar

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

también me creer, que el signo debe ser diferente

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

Podría estar equivocado, pero yo no lo creo

2

Estoy de acuerdo con Jarek, y Además, observo que el carácter separador de desplazamiento 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('.', ':') 
37

ISO 8601 Representación de tiempo

El estándar internacional ISO 8601 describe una cadena de representación de fechas y horas. Dos ejemplos sencillos de este formato son

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

(que tanto se destacan para el 16 de diciembre de 2010), pero el formato también permite inferiores a un segundo tiempo de resolución y para especificar zonas horarias. Este formato, por supuesto, 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 el Markus Kuhn entry

Recomiendo el uso de este formato para almacenar las horas en los archivos.

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

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

Usted puede utilizar el constructor strptime de la clase de fecha y hora:

>>> 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 Egenix mxDateTime:

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

+1

¿En qué sentido es "más robusto"? –

-6
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 
39

I encontraron la datetime.isoformat en el doc; Parece que hacer lo que quiere:

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' 
+2

¿Puedes explicar cómo obtuviste el timedelta correcto? –

163

local con la norma ISO-8601:

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

UTC la norma ISO-8601:

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

local con la norma ISO-8601 sin microsegundo:

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

UTC a ISO-8601 con la información de TimeZone (Python 3):

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

local con la norma ISO-8601 con la 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 
datetime.datetime.now().replace(tzinfo=datetime.timezone(offset=utc_offset_sec)).isoformat() 

para Python 2, ver y utilizar pytz

+3

'.isoformat()' puede tomar un parámetro separador, (En caso de que desee algo más que 'T'): '.isoformat ('')' – ThorSummoner

+0

@ThorSummoner ¡es bueno saberlo! Pero tenga cuidado de que cambiar el separador ya no cumpla con ISO-8601 ... lo cual tiene poco sentido (además, hay mejores formas de imprimir las fechas, pero esa no era la cuestión aquí). [RFC] (https://tools.ietf.org/html/rfc3339#section-5.6) – estani

+2

Se permite espacio como parte del estándar ISO-8601. 'Se permite omitir el carácter 'T' de mutuo acuerdo. – raychi

12

ISO8601 time format no almacena una zona horaria nombre, solo se conserva el desplazamiento utc correspondiente.

Para convertir un ctime archivo a una cadena de tiempo ISO 8601 preservando al mismo tiempo el desplazamiento en Python 3 UTC:

>>> 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 se supone que su zona horaria local es zona horaria del Este y que el sistema proporciona una UTC correcta offset para la marca de tiempo POSIX dada (ts) es decir, python tiene acceso a una base de datos de zona horaria histórica en su sistema o la zona horaria tiene las mismas reglas en una fecha dada.

Si necesita una solución portátil; use pytz module que proporciona acceso a the tz database:

>>> 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 la zona horaria nombre/abreviatura/identificación de zona; almacenarlo 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 de UTC y la zona horaria EST abreviatura no es parte del formato de hora ISO8601. 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 se trata de una fecha futura, las reglas aún podrían ser desconocidas. En otras palabras, la misma hora UTC puede corresponder a una hora local diferente según las reglas que use; al guardar una hora en formato ISO8601 se conserva la hora UTC y la hora local que corresponde a las reglas actuales de la zona horaria en su plataforma . Es posible que necesite volver a calcular la hora local en una plataforma diferente si tiene reglas diferentes.

25

Esto es lo que utilizo para convertir a formato de fecha y hora XSD:

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

me encontré con esta pregunta en la búsqueda de formato de fecha y hora XSD. Necesitaba eliminar los microsegundos de isoformat. ¡Aclamaciones!

0

he desarrollado esta función: [? ¿Cómo puedo traducir una cadena de fecha y hora ISO 8601 en un objeto de fecha y hora Python]

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 
Cuestiones relacionadas