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 das ersetzen würdetzinfo=pytz.timezone('Israel')
durch die aktuelle lokale Zeitzone ersetzt.
Irgendwelche Ideen?
local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0).astimezone()
(Python> = 3.6) abrufen . [[docs]] ( docs.python.org/3/library/… )Antworten:
Probieren Sie dateutil aus , das einen tzlokalen Typ hat, der genau das tut, was Sie brauchen.
quelle
dateutil
schlägt für einige Zeitzonen mit Daten in der Vergangenheit fehl. Und für Fälle, in denen es funktioniert, könnten Sie reine stdlib-Lösung verwendenfrom dateutil.tz import tzlocal
dateutil
ist kein Defekt und befindet sich in der aktiven Entwicklung.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 heikle Verwendung von
datetime
‚s - Code .Für Python> = 3.6 benötigen Sie
import datetime LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone(datetime.timedelta(0))).astimezone().tzinfo
quelle
datetime.datetime.now().astimezone().tzinfo
schon OK sein.datetime.datetime.utcnow().astimezone().tzinfo
scheint auch korrekt zu sein und ist für mich leichter zu lesen, da ausdrücklich angegeben wird, dass zunächst UTC verwendet wird. Da nodatetime
anfangs an eine Zeitzone gebunden ist, sollte es intern keinen Unterschied machen.astimezone()
naiven Daten vor 3.6 aufrufen.Es ist schwierig, den Namen Olson TZ für eine lokale Zeitzone auf tragbare Weise herauszufinden . Glücklicherweise benötigen Sie es nicht, um den Vergleich durchzuführen.
tzlocal
Das Modul 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 vermeidet der obige Code die folgenden Probleme:
dateutil
), berücksichtigen dies nichtHinweis: Um ein zeitzonenbewusstes datetime-Objekt von einem naiven datetime-Objekt abzurufen, sollten Sie * verwenden :
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
Anstatt von:
#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 angegebene Ortszeit nicht eindeutig 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
undtimestamp2
kann direkt verglichen werden.Hinweis:
timestamp1
Die Formel funktioniert nur, wenn der UTC-Offset bei epoch (datetime.fromtimestamp(0)
) derselbe ist wie jetztfromtimestamp()
Erstellt ein naives Datum / Uhrzeit-Objekt in der aktuellen lokalen Zeitzoneutcfromtimestamp()
Erstellt ein naives Datum / Uhrzeit-Objekt in UTC.quelle
pytz
Zeitzone benötigen würden , hatte Python seit Ewigkeiten eine lokale Zeitzone in stdlib. 2- PEP 615 - Unterstützung für die IANA-Zeitzonendatenbank in der Standardbibliothek wird in Python 3.9 akzeptiert (es bietet Zugriff auf dieselben tzdata wiepytz
)Ich habe mir dasselbe gefragt und die Antwort in 1 gefunden:
Schauen Sie sich Abschnitt 8.1.7 an: das Format "% z" (Kleinbuchstaben, der Großbuchstabe Z gibt auch die Zeitzone zurück, jedoch nicht im 4-stelligen Format, sondern in Form von Zeitzonenabkürzungen, wie in [3]). of strftime gibt die in E-Mail-Headern standardmäßige Form "+/- 4DIGIT" zurück (siehe Abschnitt 3.3 von RFC 2822, siehe [2], in dem die anderen Möglichkeiten zur Angabe der Zeitzone für E-Mail-Header überholt sind).
Wenn Sie also 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] Zeitzonenabkürzungen: http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations , nur als Referenz.
quelle
tzinfo
Objekt zu finden, das der lokalen Zeitzone entspricht, und nicht den aktuellen utc-Offset als Zeichenfolge.time.timezone
,.altzone
Geben Sie aktuelle UTC - Offset. Zeitzonenversatz oder Abkürzungen sind nicht eindeutig. Es ist nicht so einfach, eine lokale Zeitzone zu erhalten, die Sie für Daten in der fernen Vergangenheit, Gegenwart und nahen Zukunft verwenden können. Sehen Sie sichtzlocal
den Quellcode des Moduls an, um ein Beispiel zu sehen, wie dies durchgeführt werden kann.Holen Sie sich zuerst Pytz- und Tzlocal-Module
dann
from tzlocal import get_localzone local = get_localzone()
dann kannst du Dinge wie tun
from datetime import datetime print(datetime.now(local))
quelle
Hier ist eine Möglichkeit, die lokale Zeitzone nur mit der Standardbibliothek abzurufen (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 anwenden können auf
datetime
:>>> 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>)
quelle
tzlocal
Quellcode anFolgendes scheint für 3.7+ mit Standardbibliotheken zu funktionieren:
from datetime import timedelta from datetime import timezone import time def currenttz(): if time.daylight: return timezone(timedelta(seconds=-time.altzone),time.tzname[1]) else: return timezone(timedelta(seconds=-time.timezone),time.tzname[0])
quelle
Vermeiden von nicht standardmäßigen Modulen (scheint eine fehlende Methode des datetime-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)
quelle
-time.timezone
.Basierend auf der Antwort von JF Sebastian können Sie dies mit der Standardbibliothek tun:
import time, datetime local_timezone = datetime.timezone(datetime.timedelta(seconds=-time.timezone))
Getestet in 3.4, sollte auf 3.4+ funktionieren
quelle
Hier ist eine etwas präzisere Version der Lösung von @ vbem:
from datetime import datetime as dt dt.utcnow().astimezone().tzinfo
Der einzige wesentliche Unterschied ist , dass ich ersetzt
datetime.datetime.now(datetime.timezone.utc)
mitdatetime.datetime.utcnow()
. Der Kürze halber habe ich auchdatetime.datetime
als aliasiertdt
.Für meine Zwecke möchte ich den UTC-Offset in Sekunden. So sieht das aus:
quelle
pytz
undtzlocal
. Ich bin vorsichtig, wenn ich Abhängigkeiten von Drittanbietern hinzufüge, wenn Python bereits mit so viel ausgeliefert wird, aber wenn Sie sich mit Zeitzonen befassen, benötigen Sie eindeutig externe Hilfe.Basierend auf der obigen Antwort von Thoku ist hier eine Antwort, die die Zeitzone auf die nächste halbe Stunde auflöst (was für einige Zeitzonen relevant ist, z. B. für Südaustralien):
from datetime import datetime round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2)
quelle
round((round((datetime.datetime.now()-datetime.datetime.utcnow()).total_seconds())/1800)/2)
round()
kann hier (für einige Zeitzonen) einen falschen UTC-Offset erzeugen, und dies ist nicht erforderlich. InformationenIch habe auch nach einer einfachen Möglichkeit gesucht, die lokale Hostkonfiguration zu lesen und die zeitzonenbezogene local_time darauf basierend zu erhalten. Ab Python 3.6+ ist der einfachste Ansatz die Verwendung von dateutil.tz, das gelesen wird
/etc/localtime
zeitzonenbezogene Datum / Uhrzeit-Objekt und unterstützt wird.Hier finden Sie weitere Informationen dazu: https://dateutil.readthedocs.io/en/stable/tz.html
Die Implementierung, um das zu erreichen, wonach Sie suchen, lautet wie folgt:
from datetime import datetime from dateutil import tz local_time = datetime.now(tz.gettz())
Dadurch erhalten Sie die folgende local_time:
2019-10-18 13:41:06.624536-05:00
Zusätzliche Ressourcen, die ich bei der Untersuchung dieses Themas verwendet habe: Paul Ganssle Präsentation zu Zeitzonen: https://www.youtube.com/watch?v=l4UCKCo9FWY
pytz: Die schnellste Fußwaffe im Westen https://blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html
quelle
Für einfache Dinge kann die folgende
tzinfo
Implementierung verwendet werden, die das Betriebssystem nach Zeitzonenversätzen 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())
quelle
time
Modul auf einer bestimmten Plattform keinen Zugriff auf die tz-Datenbank hat (Hinweis:pytz
In der Frage wird ein solcher Zugriff auf tragbare Weiset
bereitgestellt ). (2) Die Formel ist falsch, wenn der entsprechende utc-Offsetdt
nicht lautet-time.timezone
und selbst wenn dastime
Modul das Richtige kennt,localtime(t)
fragt Ihr Code möglicherweise nach einem falschen Wert (berücksichtigen Sie die Zeit um einen Sommerzeitübergang).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.
quelle
Sie können mit Pendel glücklich sein
>>> pendulum.datetime(2015, 2, 5, tz='local').timezone.name 'Israel'
Pendel hat eine gut gestaltete API zum Bearbeiten von Daten. Alles ist TZ-bewusst.
quelle
Wenn dies Ihre Absicht ist, würde ich mir keine Gedanken darüber machen, bestimmte tzinfo-Parameter oder zusätzliche externe Bibliotheken anzugeben. Seit Python 3.5 ist das integrierte Datum / Uhrzeit-Modul alles, was Sie benötigen, um automatisch eine UTC und einen lokalen Zeitstempel zu erstellen.
import datetime f = "%a %b %d %H:%M:%S %Z %Y" # Full format with timezone # tzinfo=None cdatetime = datetime.datetime(2010, 4, 27, 12, 0, 0, 0) # 1. Your example from log cdatetime = datetime.datetime.now() # 2. Basic date creation (default: local time) print(cdatetime.strftime(f)) # no timezone printed # Tue Apr 27 12:00:00 2010 utctimestamp = cdatetime.astimezone(tz=datetime.timezone.utc) # 1. convert to UTC utctimestamp = datetime.datetime.now(tz=datetime.timezone.utc) # 2. create in UTC print(utctimestamp.strftime(f)) # Tue Apr 27 17:00:00 UTC 2010 localtimestamp = cdatetime.astimezone() # 1. convert to local [default] localtimestamp = datetime.datetime.now().astimezone() # 2. create with local timezone print(localtimestamp.strftime(f)) # Tue Apr 27 12:00:00 CDT 2010
Der Parameter '% Z' von datetime.strftime () druckt das Zeitzonenakronym in den Zeitstempel, den Menschen lesen können.
quelle
Beachten Sie zunächst, dass die Frage eine falsche Initialisierung eines bewussten Datetime-Objekts 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 ein ungerader Bruchteil einer Stunde ist.)
Um eine bewusste Datumszeit mit Pytz richtig zu initialisieren, sollte die folgende
localize()
Methode angewendet werden:>>> local_time=pytz.timezone('Israel').localize(datetime.datetime(2010, 4, 27, 12)) >>> print(local_time.utcoffset()) 3:00:00
Wenn Sie nun eine lokale Pytz-Zeitzone als neues tzinfo benötigen, sollten Sie das tzlocal-Paket verwenden, wie andere erklärt haben. Wenn Sie jedoch nur eine Instanz mit einem korrekten lokalen Zeitzonenversatz und einer korrekten Abkürzung benötigen, können Sie mit Python 3.3 starten Rufen Sie die
astimezone()
Methode ohne Argumente auf, um eine bewusstedatetime
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'
quelle
pytz
Übergebendatetime()
Sie die Zeitzone nicht direkt an den Konstruktor - wenn Sie wissen, dass Sie dies nicht tun sollten; warum machst du das (2) Wenn Siepytz
installiert haben; Warum verwenden Sie nicht portableastimezone()
Geräte, die auf einer bestimmten Plattform möglicherweise keinen Zugriff auf die tz-Datenbank haben? Sie könnten ein reines Python-tzlocal
Modul erhalten, daspytz
stattdessen ein tzinfo-Objekt für die lokale Zeitzone unter Windows und Unix (/etc/localtime
oder/usr/local/etc/localtime
) findet.tzlocal von dateutil .
Es folgt ein Codebeispiel. Letzte Zeichenfolge, die zur Verwendung in Dateinamen geeignet ist.
>>> from datetime import datetime >>> from dateutil.tz import tzlocal >>> str(datetime.now(tzlocal())) '2015-04-01 11:19:47.980883-07:00' >>> str(datetime.now(tzlocal())).replace(' ','-').replace(':','').replace('.','-') '2015-04-01-111947-981879-0700' >>>
quelle