wake-up-neo.net

Konvertieren Sie eine Python-UTC-Datumszeit in eine lokale Datumszeit, indem Sie nur die Python-Standardbibliothek verwenden?

Ich habe eine Python-Datetime-Instanz, die mit datetime.utcnow () erstellt wurde und in der Datenbank persistent war.

Zur Anzeige möchte ich die aus der Datenbank abgerufene datetime-Instanz mit der lokalen Standardzeitzone in lokale datetime konvertieren (d. H. Als ob die datetime mit datetime.now () erstellt wurde).

Wie kann ich die UTC-Datumszeit in eine lokale Datumszeit konvertieren, indem nur die Python-Standardbibliothek verwendet wird (z. B. keine Pytz-Abhängigkeit)?

Es scheint eine Lösung zu sein, datetime.astimezone (tz) zu verwenden, aber wie würden Sie die lokale Standardzeitzone erhalten?

116
Nitro Zark

Ich glaube, ich habe es herausgefunden: Berechnet die Anzahl der Sekunden seit Epoche, konvertiert dann mit time.localtime in ein lokales Timzeone und konvertiert dann die Zeitstruktur wieder in eine Datumszeit ...

Epoch_DATETIME = datetime.datetime(1970,1,1)
SECONDS_PER_DAY = 24*60*60

def utc_to_local_datetime( utc_datetime ):
    delta = utc_datetime - Epoch_DATETIME
    utc_Epoch = SECONDS_PER_DAY * delta.days + delta.seconds
    time_struct = time.localtime( utc_Epoch )
    dt_args = time_struct[:6] + (delta.microseconds,)
    return datetime.datetime( *dt_args )

Es wendet die Sommer-/Winterzeit korrekt an:

>>> utc_to_local_datetime( datetime.datetime(2010, 6, 6, 17, 29, 7, 730000) )
datetime.datetime(2010, 6, 6, 19, 29, 7, 730000)
>>> utc_to_local_datetime( datetime.datetime(2010, 12, 6, 17, 29, 7, 730000) )
datetime.datetime(2010, 12, 6, 18, 29, 7, 730000)
6
Nitro Zark

In Python 3.3+:

from datetime import timezone

def utc_to_local(utc_dt):
    return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)

In Python 2/3:

import calendar
from datetime import datetime, timedelta

def utc_to_local(utc_dt):
    # get integer timestamp to avoid precision lost
    timestamp = calendar.timegm(utc_dt.timetuple())
    local_dt = datetime.fromtimestamp(timestamp)
    assert utc_dt.resolution >= timedelta(microseconds=1)
    return local_dt.replace(microsecond=utc_dt.microsecond)

Verwendung von pytz (beide Python 2/3):

import pytz

local_tz = pytz.timezone('Europe/Moscow') # use your local timezone name here
# NOTE: pytz.reference.LocalTimezone() would produce wrong result here

## You could use `tzlocal` module to get local timezone on Unix and Win32
# from tzlocal import get_localzone # $ pip install tzlocal

# # get local timezone    
# local_tz = get_localzone()

def utc_to_local(utc_dt):
    local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz)
    return local_tz.normalize(local_dt) # .normalize might be unnecessary

Beispiel

def aslocaltimestr(utc_dt):
    return utc_to_local(utc_dt).strftime('%Y-%m-%d %H:%M:%S.%f %Z%z')

print(aslocaltimestr(datetime(2010,  6, 6, 17, 29, 7, 730000)))
print(aslocaltimestr(datetime(2010, 12, 6, 17, 29, 7, 730000)))
print(aslocaltimestr(datetime.utcnow()))

Ausgabe

2010-06-06 21:29:07.730000 MSD+0400
2010-12-06 20:29:07.730000 MSK+0300
2012-11-08 14:19:50.093745 MSK+0400
2010-06-06 21:29:07.730000 
2010-12-06 20:29:07.730000 
2012-11-08 14:19:50.093911 
2010-06-06 21:29:07.730000 MSD+0400
2010-12-06 20:29:07.730000 MSK+0300
2012-11-08 14:19:50.146917 MSK+0400

Hinweis: Berücksichtigt die Sommerzeit und die kürzliche Änderung des Versatzes für die MSK-Zeitzone.

Ich weiß nicht, ob Nicht-Pytz-Lösungen unter Windows funktionieren.

171
jfs

Sie können dies nicht nur mit der Standardbibliothek machen, da die Standardbibliothek keine Zeitzonen hat. Sie benötigen pytz oder dateutil .

>>> from datetime import datetime
>>> now = datetime.utcnow()
>>> from dateutil import tz
>>> HERE = tz.tzlocal()
>>> UTC = tz.gettz('UTC')

The Conversion:
>>> gmt = now.replace(tzinfo=UTC)
>>> gmt.astimezone(HERE)
datetime.datetime(2010, 12, 30, 15, 51, 22, 114668, tzinfo=tzlocal())

Oder gut, Sie können dies auch ohne pytz oder dateutil tun, indem Sie Ihre eigenen Zeitzonen implementieren. Aber das wäre dumm.

37
Lennart Regebro

Mit der Standardbibliothek ist das nicht möglich. Mit pytz module können Sie jedes naive/aware datetime-Objekt in eine andere Zeitzone konvertieren. Schauen wir uns einige Beispiele mit Python 3 an.

Naive Objekte, die mit der Klassenmethode utcnow() erstellt wurden

Um ein naive - Objekt in eine andere Zeitzone zu konvertieren, müssen Sie es zuerst in aware datetime-Objekt konvertieren. Sie können die replace-Methode verwenden, um ein naive datetime-Objekt in ein aware datetime-Objekt zu konvertieren. Um ein aware datetime-Objekt in eine andere Zeitzone zu konvertieren, können Sie die astimezone-Methode verwenden.

Die Variable pytz.all_timezones gibt Ihnen die Liste aller verfügbaren Zeitzonen im pytz-Modul.

import datetime,pytz

dtobj1=datetime.datetime.utcnow()   #utcnow class method
print(dtobj1)

dtobj3=dtobj1.replace(tzinfo=pytz.UTC) #replace method

dtobj_hongkong=dtobj3.astimezone(pytz.timezone("Asia/Hong_Kong")) #astimezone method
print(dtobj_hongkong)

Naive Objekte, die mit der Klassenmethode now() erstellt wurden

Da die now-Methode das aktuelle Datum und die aktuelle Uhrzeit zurückgibt, müssen Sie zuerst die Zeitzone des datetime-Objekts aktivieren. Die localize-Funktion konvertiert ein naive datetime-Objekt in ein zeitzonenabhängiges datetime-Objekt. Dann können Sie die astimezone-Methode verwenden, um sie in eine andere Zeitzone zu konvertieren.

dtobj2=datetime.datetime.now()

mytimezone=pytz.timezone("Europe/Vienna") #my current timezone
dtobj4=mytimezone.localize(dtobj2)        #localize function

dtobj_hongkong=dtobj4.astimezone(pytz.timezone("Asia/Hong_Kong")) #astimezone method
print(dtobj_hongkong)
5
N Randhawa

Die Standard-Python-Bibliothek enthält keine tzinfo-Implementierungen. Ich habe das immer als überraschendes Manko des datetime-Moduls betrachtet.

Die Dokumentation für die Klasse tzinfo enthält einige nützliche Beispiele. Suchen Sie nach dem großen Codeblock am Ende des Abschnitts.

4
Mark Ransom

Aufbauend auf Alexeis Kommentar. Dies sollte auch für DST funktionieren.

import time
import datetime

def utc_to_local(dt):
    if time.localtime().tm_isdst:
        return dt - datetime.timedelta(seconds = time.altzone)
    else:
        return dt - datetime.timedelta(seconds = time.timezone)
4
John Kerns

Hier ist eine andere Möglichkeit, die Zeitzone im datetime-Format zu ändern (ich weiß, dass ich meine Energie dafür verschwendet habe, aber ich habe diese Seite nicht gesehen, daher weiß ich nicht wie), ohne min. und sek. denn ich brauche es nicht für mein projekt:

def change_time_zone(year, month, day, hour):
      hour = hour + 7 #<-- difference
      if hour >= 24:
        difference = hour - 24
        hour = difference
        day += 1
        long_months = [1, 3, 5, 7, 8, 10, 12]
        short_months = [4, 6, 9, 11]
        if month in short_months:
          if day >= 30:
            day = 1
            month += 1
            if month > 12:
              year += 1
        Elif month in long_months:
          if day >= 31:
            day = 1
            month += 1
            if month > 12:
              year += 1
        Elif month == 2:
          if not year%4==0:
            if day >= 29:
              day = 1
              month += 1
              if month > 12:
                year += 1
          else:
            if day >= 28:
              day = 1
              month += 1
              if month > 12:
                year += 1
      return datetime(int(year), int(month), int(day), int(hour), 00)
0
Guest

Eine einfache (aber möglicherweise fehlerhafte) Methode, die in Python 2 und 3 funktioniert:

import time
import datetime

def utc_to_local(dt):
    return dt - datetime.timedelta(seconds = time.timezone)

Der Vorteil ist, dass es einfach ist, eine Umkehrfunktion zu schreiben

0

Der einfachste Weg, den ich gefunden habe, ist, den Zeitversatz von/zu erhalten, wo Sie sind.

def format_time(ts,offset):
    if not ts.hour >= offset:
        ts = ts.replace(day=ts.day-1)
        ts = ts.replace(hour=ts.hour-offset)
    else:
        ts = ts.replace(hour=ts.hour-offset)
    return ts

Dies funktioniert für mich in Python 3.5.2.

0
Zld Productions

Dies ist ein schrecklicher Weg, aber es wird vermieden, eine Definition zu erstellen. Es erfüllt die Anforderung, sich an die grundlegende Python3-Bibliothek zu halten.

# Adjust from UST to Eastern Standard Time (dynamic)
# df.my_localtime should already be in datetime format, so just in case
df['my_localtime'] = pd.to_datetime.df['my_localtime']

df['my_localtime'] = df['my_localtime'].dt.tz_localize('UTC').dt.tz_convert('America/New_York').astype(str)
df['my_localtime'] = pd.to_datetime(df.my_localtime.str[:-6])
0