Frage

Das Beste, was ich mit jetzt kommen kann, ist diese Ungeheuerlichkeit:

>>> datetime.utcnow() \
...   .replace(tzinfo=pytz.UTC) \
...   .astimezone(pytz.timezone("Australia/Melbourne")) \
...   .replace(hour=0,minute=0,second=0,microsecond=0) \
...   .astimezone(pytz.UTC) \
...   .replace(tzinfo=None)
datetime.datetime(2008, 12, 16, 13, 0)

d., In englischer Sprache, die aktuelle Zeit erhalten (in UTC), wandelt es in einer anderen Zeitzone, die Zeit bis Mitternacht gesetzt, dann zu UTC konvertieren zurück.

Ich bin nicht gerade jetzt () oder localtime () wie die Server-Zeitzone verwenden würde, nicht der Benutzer Zeitzone.

Ich kann das Gefühl nicht los ich etwas fehle, irgendwelche Ideen?

War es hilfreich?

Lösung

Ich denke, man kann ein paar Methode abrasieren ruft, wenn Sie es tun, wie folgt:

>>> from datetime import datetime
>>> datetime.now(pytz.timezone("Australia/Melbourne")) \
            .replace(hour=0, minute=0, second=0, microsecond=0) \
            .astimezone(pytz.utc)

ABER ... es gibt ein größeres Problem als Ästhetik in Ihrem Code. Es wird das falsche Ergebnis am Tag des Schalters oder von Sommerzeit geben

Der Grund dafür ist, dass weder die Datetime-Konstrukteuren noch replace() nehmen DST ändert berücksichtigt werden.

Zum Beispiel:

>>> now = datetime(2012, 4, 1, 5, 0, 0, 0, tzinfo=pytz.timezone("Australia/Melbourne"))
>>> print now
2012-04-01 05:00:00+10:00
>>> print now.replace(hour=0)
2012-04-01 00:00:00+10:00 # wrong! midnight was at 2012-04-01 00:00:00+11:00
>>> print datetime(2012, 3, 1, 0, 0, 0, 0, tzinfo=tz)
2012-03-01 00:00:00+10:00 # wrong again!

Allerdings ist die Dokumentation für tz.localize() lautet:

  

Diese Methode sollte verwendet werden Localtimes zu konstruieren, sondern   als ein Tzinfo Argument in ein Datetime-Konstruktor übergeben.

Damit Ihr Problem wie so gelöst:

>>> import pytz
>>> from datetime import datetime, date, time

>>> tz = pytz.timezone("Australia/Melbourne")
>>> the_date = date(2012, 4, 1) # use date.today() here

>>> midnight_without_tzinfo = datetime.combine(the_date, time())
>>> print midnight_without_tzinfo
2012-04-01 00:00:00

>>> midnight_with_tzinfo = tz.localize(midnight_without_tzinfo)
>>> print midnight_with_tzinfo
2012-04-01 00:00:00+11:00

>>> print midnight_with_tzinfo.astimezone(pytz.utc)
2012-03-31 13:00:00+00:00

Es wird keine Garantien für die Daten vor 1582, though.

Andere Tipps

@ Antwort den Hop ist falsch am Tag des Übergangs von der Sommerzeit (DST) zB 1. April 2012 . Um es zu beheben tz.localize() verwendet werden könnte:

tz = pytz.timezone("Australia/Melbourne")
today = datetime.now(tz).date()
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)
utc_dt = midnight.astimezone(pytz.utc)        

Das gleiche mit Kommentaren:

#!/usr/bin/env python
from datetime import datetime, time
import pytz # pip instal pytz

tz = pytz.timezone("Australia/Melbourne") # choose timezone

# 1. get correct date for the midnight using given timezone.
today = datetime.now(tz).date()

# 2. get midnight in the correct timezone (taking into account DST)
#NOTE: tzinfo=None and tz.localize()
# assert that there is no dst transition at midnight (`is_dst=None`)
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)

# 3. convert to UTC (no need to call `utc.normalize()` due to UTC has no 
#    DST transitions)
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
print midnight.astimezone(pytz.utc).strftime(fmt)

die TZ Umgebungsvariable ändert, was Zeitzone Python Datums- und Zeitfunktionen arbeiten.

>>> time.gmtime()
(2008, 12, 17, 1, 16, 46, 2, 352, 0)
>>> time.localtime()
(2008, 12, 16, 20, 16, 47, 1, 351, 0)
>>> os.environ['TZ']='Australia/Melbourne'
>>> time.localtime()
(2008, 12, 17, 12, 16, 53, 2, 352, 1)

Jede Zeitzone hat eine Nummer, zB US / Zentral = -6. Diese ist definiert als der Offset in Stunden von UTC. Seit 0000 Mitternacht ist, können Sie einfach diese Zeit in jeder Zeitzone Offset verwenden, um zu finden, wenn es Mitternacht UTC ist. Für den Zugriff auf das, glaube ich können Sie

 time.timezone

Nach Der Python-Docs , time.timezone gibt tatsächlich den negativen Wert diese Zahl:

  
    

time.timezone

         
      

Der Versatz der lokalen (nicht-DST) Zeitzone, in Sekunden westlich von UTC (negativ in den meisten Westeuropa, positiv in den USA, Null in Großbritannien).

    
  

Sie würden also nur die Zahl für die Zeit in Stunden verwenden, wenn es positiv ist (das heißt, wenn es Mitternacht ist in Chicago (die einen 6 Zeitzone-Wert) hat, dann ist es 6000 = 06.00 UTC).

Wenn die Zahl negativ ist, subtrahieren von 24. Zum Beispiel würde Berlin geben -1, so. 24 - 1 => 2300 = 23.00

Dies ist einfacher mit dateutil.tz als pytz:

>>>import datetime
>>>import dateutil.tz
>>>midnight=(datetime.datetime
             .now(dateutil.tz.gettz('Australia/Melbourne'))
             .replace(hour=0, minute=0, second=0, microsecond=0)
             .astimezone(dateutil.tz.tzutc()))
>>>print(midnight)
2019-04-26 14:00:00+00:00

Die Tzinfo Dokumentation empfiehlt dateutil.tz seit Python 3.6. Die Tzinfo Objekte aus dateutil.tz haben keine Probleme mit Anomalien wie DST, ohne die localize Funktionalität von pytz zu erfordern. Am Beispiel von user3850:

>>> now = (datetime.datetime(2012, 4, 1, 5,  
...         tzinfo = dateutil.tz.gettz('Australia/Melbourne'))) 
>>> print(now.replace(hour = 0).astimezone(dateutil.tz.tzutc()))
2012-03-31 13:00:00+00:00
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top