web-dev-qa-db-ja.com

python標準ライブラリのみを使用して、python UTC日時をローカル日時に変換しますか?

Datetime.utcnow()を使用して作成され、データベースに保持されたpython datetimeインスタンスがあります。

表示のために、データベースから取得した日時インスタンスをデフォルトのローカルタイムゾーンを使用してローカル日時に変換します(つまり、datetime.now()を使用して日時が作成されたかのように)。

python標準ライブラリのみを使用して(たとえば、pytz依存関係なしに)UTC日時をローカル日時に変換するにはどうすればよいですか?

1つの解決策はdatetime.astimezone(tz)を使用することですが、デフォルトのローカルタイムゾーンをどのように取得しますか?

128
Nitro Zark

私はそれを考え出したと思います:エポックからの秒数を計算し、time.localtimeを使用してローカルtimzeoneに変換してから、time structをdatetimeに変換し直します...

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 )

夏/冬のDSTを正しく適用します。

>>> 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)
7
Nitro Zark

Python 3.3以降:

from datetime import datetime, timezone

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

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)

pytzの使用(両方[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

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()))

出力

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

注:DSTおよびMSKタイムゾーンのutcオフセットの最近の変更を考慮します。

Windowsでピッツ以外のソリューションが機能するかどうかはわかりません。

189
jfs

標準ライブラリにはタイムゾーンがないため、標準ライブラリだけではできません。 pytz または 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())

または、独自のタイムゾーンを実装することにより、pytzまたはdateutilを使用せずに実行できます。しかし、それはばかげているでしょう。

38
Lennart Regebro

標準ライブラリではできません。 pytzモジュールを使用すると、ナイーブ/アウェアな日時オブジェクトを他のタイムゾーンに変換できます。 Pythonを使用したいくつかの例を見てみましょう3。

クラスメソッドutcnow()で作成された単純なオブジェクト

naiveオブジェクトを他のタイムゾーンに変換するには、まずaware datetimeオブジェクトに変換する必要があります。 replaceメソッドを使用して、naive datetimeオブジェクトをaware datetimeオブジェクトに変換できます。次に、aware datetimeオブジェクトを他のタイムゾーンに変換するには、astimezoneメソッドを使用できます。

変数pytz.all_timezonesは、pytzモジュールで利用可能なすべてのタイムゾーンのリストを提供します。

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)

クラスメソッドnow()で作成された単純なオブジェクト

nowメソッドは現在の日付と時刻を返すため、最初にdatetimeオブジェクトのタイムゾーンを認識させる必要があります。 localize関数は、naive datetimeオブジェクトをタイムゾーン対応のdatetimeオブジェクトに変換します。その後、astimezoneメソッドを使用して、別のタイムゾーンに変換できます。

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)
6
N Randhawa

標準のPythonライブラリには、tzinfo実装がまったく付属していません。私はこれを常に日時モジュールの驚くべき欠点と考えてきました。

tzinfoクラスのドキュメント には、いくつかの有用な例が付属しています。セクションの最後にある大きなコードブロックを探します。

4
Mark Ransom

アレクセイのコメントに基づいて。これはDSTでも機能するはずです。

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

日時形式でタイムゾーンを変更する別の方法を次に示します(これでエネルギーを無駄にしたことは知っていますが、このページが表示されなかったため、方法がわかりません)。そして秒私のプロジェクトには必要ないので:

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

Python 2および3で機能する単純な(ただし、おそらく欠陥がある)方法

import time
import datetime

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

その利点は、逆関数を書くのが簡単なことです

0

私が見つけた最も簡単な方法は、yoの場所の時間オフセットを取得し、それを時間から減算することです。

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

これは、Python 3.5.2で機能します。

0
Zld Productions

これは恐ろしい方法ですが、定義を作成することを避けます。基本的なPython3ライブラリに固執するという要件を満たします。

# 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