python-datetime avec fuseau horaire à l'époque

dans le code ci-dessous, je calcule maintenant l'époque et le début de l'époque actuelle.

import time
import pytz
from datetime import datetime

tz1 = pytz.timezone('CST6CDT')
utc = pytz.timezone('UTC')
now = pytz.UTC.localize(datetime.utcnow())
now_tz = now.astimezone(tz1)
print now_tz
print now_tz.strftime('%s')

begin_day = now_tz.replace(hour=0, minute=0, second=0)
print begin_day

print begin_day.strftime('%s')

impression des déclarations:

2012-08-28 13:52:21.595718-05:00
1346187141
2012-08-28 00:00:00.595718-05:00
1346137200

conversion des époques en timestamp avec le fuseau horaire CDT: 1346187141 - 28 Août 2012 à 15:52:21, 1346137200-Aug 28 2012 02:00: 00

j'aimerais que la deuxième époque soit le début de la journée, mais il est 2h du matin. Il semble qu'il utilise toujours locale timezone PST lors de la conversion à l'époque.

Qu'est-ce que je fais de mal ? ou cela peut-il être fait d'une manière différente?

Merci!

8
demandé sur jfs 2012-08-28 22:57:56

3 réponses

NOTE: ma réponse est totalement fausse. (j'aimerais le supprimer, mais je ne peux pas le faire tant que le drapeau accept n'est pas enlevé.)

Please see J. F. Sebastian's answer .

voici un code démontrant une valeur de now_tz pour laquelle nos deux méthodes produisent des résultats différents.

import calendar
import pytz
import datetime as dt

tz1 = pytz.timezone('US/Eastern')
utc = pytz.timezone('UTC')
now = utc.localize(dt.datetime(2002, 10, 28), is_dst=None)
now_tz = now.astimezone(tz1)
now_epoch = calendar.timegm(now_tz.utctimetuple())
begin_day = tz1.normalize(now_tz.replace(hour=0, minute=0, second=0))

midnight = tz1.localize(dt.datetime.combine(now_tz, dt.time(0, 0)), is_dst=None)
if begin_day != midnight:
    print(begin_day)
    # 2002-10-27 01:00:00-04:00  # my result -- is not midnight
    print(midnight)
    # 2002-10-27 00:00:00-04:00  # J.F.Sebastian's result is correct

(réponse Originale à cette question expurgée)

6
répondu unutbu 2017-05-23 11:46:13

pour convertir un datetime avec fuseau horaire en epoch (POSIX timestamp):

from datetime import datetime
import pytz

tz = pytz.timezone('CST6CDT')

# a datetime with timezone
dt_with_tz = tz.localize(datetime(2012, 8, 28, 19, 33, 50), is_dst=None)

# get timestamp
ts = (dt_with_tz - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
# -> 1346200430.0

C'est comment la méthode datetime.timestamp est implémentée pour les objets datetime en Python 3.

Pour obtenir "maintenant époque":

from datetime import datetime

now_epoch = (datetime.utcnow() - datetime(1970, 1, 1)).total_seconds()

Ou (en supposant que time utilise POSIX époque):

import time

now_epoch = time.time()

Arriver "au début de la journée de l'époque" est plus complexe car la journée en cours peut être différent dans des fuseaux horaires différents:

from datetime import datetime, time
import pytz

tz = pytz.timezone('CST6CDT')

# get current date in given timezone
today = datetime.now(tz).date()
# -> datetime.date(2013, 6, 22)

# get beginning of current day in given timezone as a datetime with timezone
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)
# -> datetime.datetime(2013, 6, 22, 0, 0, tzinfo=<DstTzInfo 'CST6CDT'...>)

# get timestamp
ts = (midnight - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
# -> 1371877200.0 

Voir Comment puis-je obtenir le temps UTC de "minuit" pour un fuseau horaire? .

Pour obtenir "le début de la journée de l'époque", en supposant que l'UTC date:

from datetime import datetime, date

# get current date in UTC
utc_date = datetime.utcnow().date()
# -> datetime.date(2013, 6, 23)

# get timestamp
ts = (utc_date - date(1970, 1, 1)).days * 86400
# -> 1371945600

voir Converting datetime.date / datetime.datetime to UTC timestamp en Python .

22
répondu jfs 2017-05-23 12:25:07

la dernière version de simple-date (version 0.2 sur pypi ) gérera les détails pour vous:

>>> from simpledate import *
>>> now_utc = SimpleDate(tz='UTC')
>>> now_tz = now_utc.convert(tz='CST6CDT')
>>> begin_day = now_tz.replace(hour=0, minute=0, second=0, microsecond=0)
>>> now_utc.timestamp
1371950295.777453
>>> now_tz.timestamp
1371950295.777453
>>> begin_day.timestamp
1371877200.0

nous pouvons revenir en arrière pour vérifier les horodateurs (bien qu'il soit clair au-dessus que le changement de fuseau horaire n'a pas changé l'époque, tout en se déplaçant au début de la journée a fait):

>>> SimpleDate(1371877200.0, tz='CST6CDT')
SimpleDate('2013-06-22 00:00:00.000000 CDT', tz='CST6CDT')
>>> SimpleDate(1371877200.0, tz='UTC')
SimpleDate('2013-06-22 05:00:00.000000 UTC')
0
répondu andrew cooke 2013-06-23 01:21:04