Ich möchte UTC-Zeitstempel aus einer Protokolldatei mit lokalen Zeitstempeln vergleichen. Beim Erstellen des lokalen datetime
-Objekts verwende ich Folgendes:
>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0,
tzinfo=pytz.timezone('Israel'))
Ich möchte ein automatisches Werkzeug finden, das die tzinfo=pytz.timezone('Israel')
durch die aktuelle lokale Zeitzone ersetzt.
Irgendwelche Ideen?
In Python 3.x kann die lokale Zeitzone folgendermaßen ermittelt werden:
import datetime
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
Es ist eine knifflige Verwendung von datetime
s code .
vergleichen von UTC-Zeitstempeln aus einer Protokolldatei mit lokalen Zeitstempeln.
Es ist schwierig, den Namen von Olson TZ für eine lokale Zeitzone herauszufinden auf tragbare Weise. Glücklicherweise brauchen Sie es nicht, um den Vergleich durchzuführen.
tzlocal
module gibt eine Pytz-Zeitzone zurück, die der lokalen Zeitzone entspricht:
from datetime import datetime
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
tz = get_localzone()
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc) #NOTE: utc.normalize() is unnecessary here
Im Gegensatz zu anderen bisher vorgestellten Lösungen werden durch den obigen Code folgende Probleme vermieden:
dateutil
), können dies nicht berücksichtigenHinweis: Um ein Zeitzonen-kompatibles Datetime-Objekt von einem naiven Datetime-Objekt zu erhalten, sollten Sie es verwenden*:
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
anstatt:
#XXX fails for some timezones
local_dt = datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=tz)
*is_dst=None
erzwingt eine Ausnahme, wenn die Ortszeit mehrdeutig oder nicht vorhanden ist.
Wenn Sie sicher sind, dass alle lokalen Zeitstempel denselben (aktuellen) UTC-Offset für die lokale Zeitzone verwenden, können Sie den Vergleich nur mit stdlib durchführen:
# convert a naive datetime object that represents time in local timezone to Epoch time
timestamp1 = (datetime(2010, 4, 27, 12, 0, 0, 0) - datetime.fromtimestamp(0)).total_seconds()
# convert a naive datetime object that represents time in UTC to Epoch time
timestamp2 = (datetime(2010, 4, 27, 9, 0) - datetime.utcfromtimestamp(0)).total_seconds()
timestamp1
und timestamp2
können direkt verglichen werden.
Hinweis:
timestamp1
-Formel funktioniert nur, wenn der UTC-Offset in Epoch (datetime.fromtimestamp(0)
) derselbe ist wie jetztfromtimestamp()
erstellt ein naives datetime-Objekt in der aktuellen lokalen Zeitzoneutcfromtimestamp()
erstellt ein naives datetime-Objekt in UTC.Ich habe das auch von mir selbst gefragt, und ich habe die Antwort in 1 gefunden:
Schauen Sie sich Abschnitt 8.1.7 an: das Format "% z" (Kleinbuchstaben, das Z-Großbuchstaben gibt auch die Zeitzone zurück, jedoch nicht im 4-stelligen Format, sondern in Form von Zeitzonen-Abkürzungen, wie in [3]). von strftime gibt das in E-Mail-Headern übliche Formular "+/- 4DIGIT" zurück (siehe Abschnitt 3.3 von RFC 2822, siehe [2], wodurch die anderen Möglichkeiten zur Angabe der Zeitzone für E-Mail-Header außer Kraft gesetzt werden).
Wenn Sie Ihre Zeitzone in diesem Format haben möchten, verwenden Sie:
time.strftime("%z")
[1] http://docs.python.org/2/library/datetime.html
[2] http://tools.ietf.org/html/rfc2822#section-3.3
[3] Abkürzungen für Zeitzonen: http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations , nur als Referenz.
Zuerst erhalten Sie pytz- und tzlocal-Module
pip install pytz tzlocal
dann
from tzlocal import get_localzone
local = get_localzone()
dann kannst du so etwas machen
from datetime import datetime
print(datetime.now(local))
Basierend auf J. F. Sebastians Antwort können Sie dies mit der Standardbibliothek machen:
import time, datetime
local_timezone = datetime.timezone(datetime.timedelta(seconds=-time.timezone))
In 3.4 getestet, sollte auf 3.4+ funktionieren
Hier ist eine etwas prägnantere Version der @ vbem-Lösung:
from datetime import datetime as dt
dt.utcnow().astimezone().tzinfo
Der einzige wesentliche Unterschied ist, dass ich datetime.datetime.now(datetime.timezone.utc)
durch datetime.datetime.utcnow()
ersetzt habe. Der Kürze halber habe ich auch datetime.datetime
als dt
gealtert.
Für meine Zwecke möchte ich den UTC-Offset in Sekunden. So sieht das aus:
dt.utcnow().astimezone().utcoffset().total_seconds()
So können Sie die lokale Zeitzone nur über die Standardbibliothek erhalten (funktioniert nur in einer * nix-Umgebung):
>>> '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
'Australia/Sydney'
Sie können dies verwenden, um eine pytz
-Zeitzone zu erstellen:
>>> import pytz
>>> my_tz_name = '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
>>> my_tz = pytz.timezone(my_tz_name)
>>> my_tz
<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>
... die Sie dann auf eine datetime
anwenden können:
>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059)
>>> now.replace(tzinfo=my_tz)
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059, tzinfo=<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>)
Basierend auf Thokus Antwort oben, hier eine Antwort, die die Zeitzone auf die nächste halbe Stunde auflöst (was für einige Zeitzonen relevant ist, z. B. in South Australia):
from datetime import datetime
round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2)
Nicht-Standard-Modul vermeiden (scheint eine fehlende Methode des Datum-Uhrzeit-Moduls zu sein):
from datetime import datetime
utcOffset_min = int(round((datetime.now() - datetime.utcnow()).total_seconds())) / 60 # round for taking time twice
utcOffset_h = utcOffset_min / 60
assert(utcOffset_min == utcOffset_h * 60) # we do not handle 1/2 h timezone offsets
print 'Local time offset is %i h to UTC.' % (utcOffset_h)
Für einfache Dinge kann die folgende tzinfo
-Implementierung verwendet werden, die das Betriebssystem nach Zeitzonenoffsets abfragt:
import datetime
import time
class LocalTZ(datetime.tzinfo):
_unixEpochOrdinal = datetime.datetime.utcfromtimestamp(0).toordinal()
def dst(self, dt):
return datetime.timedelta(0)
def utcoffset(self, dt):
t = (dt.toordinal() - self._unixEpochOrdinal)*86400 + dt.hour*3600 + dt.minute*60 + dt.second + time.timezone
utc = datetime.datetime(*time.gmtime(t)[:6])
local = datetime.datetime(*time.localtime(t)[:6])
return local - utc
print datetime.datetime.now(LocalTZ())
print datetime.datetime(2010, 4, 27, 12, 0, 0, tzinfo=LocalTZ())
# If you're in the EU, the following datetimes are right on the DST change.
print datetime.datetime(2013, 3, 31, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 59, 59, tzinfo=LocalTZ())
# The following datetime is invalid, as the clock moves directly from
# 01:59:59 standard time to 03:00:00 daylight savings time.
print datetime.datetime(2013, 3, 31, 2, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 59, 59, tzinfo=LocalTZ())
# The following datetime is ambigous, as 02:00 can be either DST or standard
# time. (It is interpreted as standard time.)
print datetime.datetime(2013, 10, 27, 2, 0, 0, tzinfo=LocalTZ())
Beachten Sie zunächst, dass die Frage eine falsche Initialisierung eines bekannten Datumsobjekts darstellt:
>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0,
... tzinfo=pytz.timezone('Israel'))
erstellt eine ungültige Instanz. Man kann das Problem erkennen, indem man den UTC-Offset des resultierenden Objekts berechnet:
>>> print(local_time.utcoffset())
2:21:00
(Beachten Sie das Ergebnis, das einen ungeraden Bruchteil einer Stunde darstellt.)
Um eine bewusste Datetime korrekt mit pytz zu initialisieren, sollte die localize()
-Methode wie folgt verwendet werden:
>>> local_time=pytz.timezone('Israel').localize(datetime.datetime(2010, 4, 27, 12))
>>> print(local_time.utcoffset())
3:00:00
Wenn Sie als neue tzinfo eine lokale pytz-Zeitzone benötigen, sollten Sie das tzlocal-Paket wie von anderen erläutert verwenden. Wenn Sie jedoch nur eine Instanz mit einem korrekten lokalen Zeitzonen-Offset und einer entsprechenden Abkürzung benötigen, können Sie mit Python 3.3 beginnen Rufen Sie die astimezone()
-Methode ohne Argumente auf, um eine bewusste datetime
-Instanz in Ihre lokale Zeitzone zu konvertieren:
>>> local_time.astimezone().strftime('%Y-%m-%d %H:%M %Z %z')
'2010-04-27 05:00 EDT -0400'
Sie sind vielleicht zufrieden mit Pendel
>>> pendulum.datetime(2015, 2, 5, tz='local').timezone.name
'Israel'
Pendulum verfügt über eine gut entwickelte API zur Bearbeitung von Datumsangaben. Alles ist TZ-bewusst.
now_dt = datetime.datetime.now()
utc_now = datetime.datetime.utcnow()
now_ts, utc_ts = map(time.mktime, map(datetime.datetime.timetuple, (now_dt, utc_now)))
offset = int((now_ts - utc_ts) / 3600)
hoffe das wird dir helfen.