2010-04-05 45 views
6

estoy usando las siguientes funciones:Python 3: fecha y hora a fecha y hora: ¿de dónde viene esta hora adicional?

# The epoch used in the datetime API. 
EPOCH = datetime.datetime.fromtimestamp(0) 

def timedelta_to_seconds(delta): 
    seconds = (delta.microseconds * 1e6) + delta.seconds + (delta.days * 86400) 
    seconds = abs(seconds) 

    return seconds 

def datetime_to_timestamp(date, epoch=EPOCH): 
    # Ensure we deal with `datetime`s. 
    date = datetime.datetime.fromordinal(date.toordinal()) 
    epoch = datetime.datetime.fromordinal(epoch.toordinal()) 

    timedelta = date - epoch 
    timestamp = timedelta_to_seconds(timedelta) 

    return timestamp 

def timestamp_to_datetime(timestamp, epoch=EPOCH): 
    # Ensure we deal with a `datetime`. 
    epoch = datetime.datetime.fromordinal(epoch.toordinal()) 

    epoch_difference = timedelta_to_seconds(epoch - EPOCH) 
    adjusted_timestamp = timestamp - epoch_difference 

    date = datetime.datetime.fromtimestamp(adjusted_timestamp) 

    return date 

Y ellos utilizando el código pasado:

twenty = datetime.datetime(2010, 4, 4) 

print(twenty) 
print(datetime_to_timestamp(twenty)) 
print(timestamp_to_datetime(datetime_to_timestamp(twenty))) 

Y conseguir los siguientes resultados:

2010-04-04 00:00:00 
1270339200.0 
2010-04-04 01:00:00 

por alguna razón, me Estoy obteniendo un adicional de hora en la última llamada, a pesar de que mi código no tiene defectos, por lo que puedo ver.

¿De dónde viene esta hora adicional?

+0

¿Ya es hora de verano británico? – msw

+0

@msw ¿Es eso una pista disfrazada sobre husos horarios? ...Comenzó hace aproximadamente una semana, pero no veo en qué parte de mi código maneja la información de la zona horaria o si actúa de forma ingenua en lugar de actuar de forma no ingenua. –

+1

sí, eso fue una pista, ya que obtengo los mismos resultados y estoy a la luz del día también (en Python 2.6). Ahora estoy esperando la horrible operación datetime.tzinfo mientras espero que el mundo cambie a http://en.wikipedia.org/wiki/Swatch_Internet_Time – msw

Respuesta

4
# Ensure we deal with `datetime`s. 
date = datetime.datetime.fromordinal(date.toordinal()) 

(Eso es cortando la hora del día completo, ya que 'ordinal' es sólo un número día. ¿Es eso lo que quería hacer? Sospecho que no.)

De todos modos, como Michael dicho, datetime.fromtimestamp le da un datetime ingenuo que corresponde a qué local tiempo para esa marca de tiempo POSIX (UTC) sería para usted. Así que cuando se llama -

date = datetime.datetime.fromtimestamp(adjusted_timestamp) 

que está recibiendo la hora local para la marca de tiempo POSIX que representa 2010-04-04T00: 00: 00, que por supuesto en el BST es una hora por delante. Esto no sucede en la dirección de retorno porque tu época es en enero, cuando BST no está en vigor. (Sin embargo, su EPOCH también estaría completamente apagado si no estuviera en el Reino Unido.)

Debería reemplazar ambos usos de datetime.fromtimestamp con datetime.utcfromtimestamp.

Es triste que datetime continúe la horrible tradición time de mantener los horarios en hora local. Llamarlos "ingenuos" y quitarles la bandera del horario de verano los empeora aún más. Personalmente no soporto usar datetime, prefiriendo las marcas de tiempo UTC enteras para todo (convirtiendo a zonas horarias locales solo para formatear).

+0

La API de fecha y hora de Python me ha asustado de usarla nunca más ... –

1

A juzgar por tu perfil, estás en el Reino Unido. Eso significa que actualmente se está ejecutando en UTC + 1 debido a DST.

Si tomo su indicación de fecha y hora y la ejecuto a través de datetime.fromtimestamp en Python 2.6 (sé que usa Python 3, pero esto es lo que tengo), eso me muestra que cree que se refiere a 2010-04-04 02 : 00: 00 - y estoy en CEST, entonces eso es UTC + 2.

Ejecutando datetime.fromtimestamp (0), entiendo que la época es 1970-01-01 01:00:00. Esto me muestra que está agregando correctamente solo una hora (desde el 1 de enero está fuera del horario de verano, y la época es la medianoche UTC en esa fecha, aquí sería 01:00).

En otras palabras, su problema es que está enviando en un momento que se ha aplicado el horario de verano, pero datetime_to_timestamp lo trata como si el horario de verano no existiera. timestamp_to_datetime, sin embargo, aplica el horario de verano.

Desafortunadamente, no conozco suficiente Python para saber cómo resolvería esto, pero al menos esto debería darle algo para seguir.