web-dev-qa-db-fra.com

Python: Comment convertissez-vous datetime / timestamp d'un fuseau horaire à un autre fuseau horaire?

Plus précisément, compte tenu du fuseau horaire de mon serveur (perspective de l'heure système) et d'une entrée de fuseau horaire, comment puis-je calculer l'heure système comme si elle se trouvait dans ce nouveau fuseau horaire (indépendamment de l'heure d'été, etc.)?

import datetime
current_time = datetime.datetime.now() #system time

server_timezone = "US/Eastern"
new_timezone = "US/Pacific"

current_time_in_new_timezone = ???
20
kfan

Si vous connaissez votre fuseau horaire d'origine et le nouveau fuseau horaire dans lequel vous souhaitez le convertir, utilisez d'abord pytz.localize Pour gérer toute localisation (par exemple pour l'heure d'été, etc.), puis utilisez pytz.timezone Pour créer des objets de fuseau horaire , et enfin utilisez datetime.astimezone(timezone) pour un calcul facile. Par exemple:

import datetime
import pytz # new import

my_timestamp = datetime.datetime.now() # some timestamp
old_timezone = pytz.timezone("US/Eastern")
new_timezone = pytz.timezone("US/Pacific")

# returns datetime in the new timezone
my_timestamp_in_new_timezone = old_timezone.localize(my_timestamp).astimezone(new_timezone) 

Et bien sûr, si tout ce que vous voulez, c'est l'heure actuelle dans un fuseau horaire spécifique, vous pouvez passer ce fuseau horaire directement dans datetime.now () pour obtenir l'horodatage. Comme ça:

datetime.datetime.now(new_timezone)

Maintenant, avec tout cela, je recommande fortement de stocker tous vos horodatages en UTC en tant que norme système, et d'éviter tout le problème DST. Pour le contexte à ce sujet, voir: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/

Et pour savoir à quel point il est difficile de gérer les calculs de temps en général: http://yourcalendricalfallacyis.com

22
kfan

Comment convertissez-vous datetime/timestamp d'un fuseau horaire à un autre fuseau horaire?

Il y a deux étapes:

  1. Créez un objet datetime conscient à partir de l'heure système et du fuseau horaire par exemple, pour obtenir l'heure système actuelle dans le fuseau horaire donné:

    #!/usr/bin/env python
    from datetime import datetime
    import pytz
    
    server_timezone = pytz.timezone("US/Eastern")
    server_time = datetime.now(server_timezone) # you could pass *tz* directly
    

    Remarque: datetime.now(server_timezone) fonctionne même pendant les périodes ambiguës par exemple, pendant les transitions DST tandis que server_timezone.localize(datetime.now()) peut échouer (50% de chances).

    Si vous êtes sûr que votre heure d'entrée existe dans le fuseau horaire du serveur et qu'elle est unique, vous pouvez passer is_dst=None Pour affirmer que:

    server_time = server_timezone.localize(naive_time, is_dst=None)
    

    Il déclenche une exception pour les heures non valides.
    S'il est acceptable d'ignorer jusqu'à une erreur de jour (bien que généralement une erreur due à l'heure d'été soit d'environ une heure ), vous pouvez alors supprimer le paramètre is_dst:

    server_time = server_timezone.normalize(server_timezone.localize(naive_time))
    

    .normalize() est appelée pour ajuster les temps non existants (heure locale dans l'intervalle, lors des transitions "spring forward"). Si les règles de fuseau horaire n'ont pas changé; votre serveur ne doit pas générer d'heures inexistantes. Voir "Puis-je toujours définir is_dst = True?"

  2. Convertissez un objet datetime conscient en fuseau horaire cible tz:

    tz = pytz.timezone("US/Pacific")
    server_time_in_new_timezone = server_time.astimezone(tz)
    
3
jfs