web-dev-qa-db-fra.com

Python - Définition d'une date / heure dans un fuseau horaire spécifique (sans conversions UTC)

Juste pour être clair, c'est python 2.6, j'utilise pytz.

C'est pour une application qui ne traite que des fuseaux horaires américains, je dois pouvoir ancrer une date (aujourd'hui) et obtenir un horodatage Unix (heure de l'époque) pour 20h et 23h en PST uniquement.

Ça me rend fou.

> pacific = pytz.timezone("US/Pacific")

> datetime(2011,2,11,20,0,0,0,pacific)

datetime.datetime(2011, 2, 11, 20, 0, tzinfo=<DstTzInfo 'US/Pacific' PST-1 day, 16:00:0 STD>)

> datetime(2011,2,11,20,0,0,0,pacific).strftime("%s")
'1297454400'

zsh> date -d '@1297454400'    
Fri Feb 11 12:00:00 PST 2011

Donc, même si je configure un fuseau horaire et que je crée le datetime avec ce fuseau horaire, il le crée toujours en UTC puis le convertit. C'est plus un problème car UTC aura un jour d'avance lorsque j'essaierai de faire les calculs.

Existe-t-il un moyen simple (ou du moins sensé) de générer un horodatage pour 20h00 PST aujourd'hui?

(pour être clair, je comprends la valeur de l'utilisation de l'UTC dans la plupart des situations, comme les horodatages de la base de données ou pour le stockage général. Ce n'est pas une de ces situations, j'ai spécifiquement besoin d'un horodatage pour la soirée en PST, et l'UTC ne devrait pas avoir à entrez dedans.)

21
liam

Créez un objet tzinfo utc pour le fuseau horaire UTC, puis essayez ceci:

#XXX: WRONG (for any timezone with a non-fixed utc offset), DON'T DO IT
datetime(2011,2,11,20,0,0,0,pacific).astimezone(utc).strftime("%s")

Edit: Comme indiqué dans les commentaires, placer le fuseau horaire dans le constructeur datetime n'est pas toujours robuste. La méthode préférée utilisant la documentation pytz serait:

pacific.localize(datetime(2011,2,11,20,0,0,0)).astimezone(utc).strftime("%s")

Notez également dans les commentaires que strftime("%s") n'est pas fiable, il ignore les informations de fuseau horaire (même UTC) et suppose le fuseau horaire du système sur lequel il fonctionne. Il repose sur une implémentation de bibliothèque C sous-jacente et ne fonctionne pas du tout sur certains systèmes (par exemple Windows).

15
Mark Ransom

Il y a au moins deux problèmes:

  1. vous ne devez pas passer un fuseau horaire avec un décalage UTC non fixe tel que "US/Pacific" comme paramètre tzinfo directement. Vous devez tiliser la méthode pytz.timezone("US/Pacific").localize() à la place
  2. .strftime('%s') n'est pas portable, il ignore tzinfo , et il utilise toujours le fuseau horaire local. Utilisez plutôt datetime.timestamp() ou ses analogues sur les anciennes versions Python à la place.

Pour créer un datetime sensible au fuseau horaire dans le fuseau horaire donné:

#!/usr/bin/env python
from datetime import datetime 
import pytz # $ pip install pytz

tz = pytz.timezone("US/Pacific")
aware = tz.localize(datetime(2011, 2, 11, 20), is_dst=None)

Pour obtenir l'horodatage POSIX:

timestamp = (aware - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()

(On Python 2.6, voir la fonction totimestamp() sur la façon d'émuler la méthode .total_seconds() ).

15
jfs