2010-04-05 7 views
6

J'utilise les fonctions suivantes:Python 3: horodatage à datetime: d'où vient cette heure supplémentaire?

# 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 

et de les utiliser avec le code passé:

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

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

et obtenir les résultats suivants:

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

Pour une raison quelconque, je J'obtiens un supplémentaire heure ajoutée dans le dernier appel, malgré mon code ayant, autant que je peux voir, aucun défaut.

D'où vient cette heure supplémentaire?

+0

Est-ce encore l'heure d'été britannique? – msw

+0

@msw Est-ce un indice déguisé sur les fuseaux horaires? ...Cela a commencé il y a environ une semaine, mais je ne vois pas où, dans mon code, il gère les informations de fuseau horaire ou agit de manière naïve plutôt que d'agir de façon non naïve? –

+1

oui, c'était un indice, car j'obtiens les mêmes résultats et je suis aussi à l'heure avancée (en Python 2.6). Je suis maintenant en train de passer à travers l'opération datetime.tzinfo de dieu-horreur pendant que j'attends que le monde passe à http://en.wikipedia.org/wiki/Swatch_Internet_Time – msw

Répondre

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

(C'est coupant le temps de jour complètement, comme « ordinale » est un nombre de jours. Est-ce que vous vouliez dire faire? Je crains que non.)

Quoi qu'il en soit, comme Michael dit, datetime.fromtimestamp vous donne un datetime naïf correspondant à ce que local heure pour ce timestamp POSIX (UTC) serait pour vous. Alors, quand vous appelez -

date = datetime.datetime.fromtimestamp(adjusted_timestamp) 

vous obtenez l'heure locale pour l'horodatage représentant 2010-04-04T00 POSIX: 00: 00, ce qui bien sûr est en BST une heure d'avance. Cela n'arrive pas dans le sens du retour car votre époque est en janvier, quand la BST n'est pas en vigueur. (Cependant, votre EPOCH serait également complètement désactivé si vous n'étiez pas au Royaume-Uni.)

Vous devez remplacer vos deux utilisations de datetime.fromtimestamp par datetime.utcfromtimestamp.

Il est triste que datetime continue l'horrible tradition time de garder les temps en temps local. Les appeler «naïfs» et enlever le drapeau DST les rend encore pire. Personnellement, je ne peux pas supporter datetime, préférant des horodatages UTC entiers pour tout (conversion aux fuseaux horaires locaux pour le formatage seulement).

+0

L'API date-heure de Python m'a effrayé de ne plus jamais l'utiliser ... –

1

En juger par votre profil, vous êtes au Royaume-Uni. Cela signifie que vous utilisez actuellement UTC + 1 en raison de l'heure d'été.

Si je prends votre horodatage et l'exécute par datetime.fromtimestamp sur Python 2.6 (je sais que vous utilisez Python 3, mais c'est ce que j'ai), cela me montre qu'il croit qu'il se réfère à 2010-04-04 02 : 00: 00 - et je suis en CEST, donc c'est UTC + 2.

En cours d'exécution datetime.fromtimestamp (0), j'obtiens que l'époque est 1970-01-01 01:00:00. Cela me montre ensuite qu'il ajoute correctement une seule heure (puisque le 1er janvier est en dehors de l'heure d'été, et que l'heure est à minuit UTC à cette date, ce serait 01:00 ici). En d'autres termes, votre problème est que vous envoyez une heure d'application de l'heure d'été, mais que datetime_to_timestamp la traite comme si l'heure d'été n'existait pas. timestamp_to_datetime, cependant, applique l'heure d'été.

Malheureusement, je ne connais pas assez Python pour savoir comment résoudre ce problème, mais cela devrait au moins vous donner quelque chose à faire.

Questions connexes