Datetime.utcnow()を使用して作成され、データベースに保持されたpython datetimeインスタンスがあります。
表示のために、データベースから取得した日時インスタンスをデフォルトのローカルタイムゾーンを使用してローカル日時に変換します(つまり、datetime.now()を使用して日時が作成されたかのように)。
python標準ライブラリのみを使用して(たとえば、pytz依存関係なしに)UTC日時をローカル日時に変換するにはどうすればよいですか?
1つの解決策はdatetime.astimezone(tz)を使用することですが、デフォルトのローカルタイムゾーンをどのように取得しますか?
私はそれを考え出したと思います:エポックからの秒数を計算し、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)
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でピッツ以外のソリューションが機能するかどうかはわかりません。
標準ライブラリにはタイムゾーンがないため、標準ライブラリだけではできません。 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を使用せずに実行できます。しかし、それはばかげているでしょう。
標準ライブラリではできません。 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)
標準のPythonライブラリには、tzinfo
実装がまったく付属していません。私はこれを常に日時モジュールの驚くべき欠点と考えてきました。
tzinfoクラスのドキュメント には、いくつかの有用な例が付属しています。セクションの最後にある大きなコードブロックを探します。
アレクセイのコメントに基づいて。これは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)
日時形式でタイムゾーンを変更する別の方法を次に示します(これでエネルギーを無駄にしたことは知っていますが、このページが表示されなかったため、方法がわかりません)。そして秒私のプロジェクトには必要ないので:
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)
Python 2および3で機能する単純な(ただし、おそらく欠陥がある)方法
import time
import datetime
def utc_to_local(dt):
return dt - datetime.timedelta(seconds = time.timezone)
その利点は、逆関数を書くのが簡単なことです
私が見つけた最も簡単な方法は、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で機能します。
これは恐ろしい方法ですが、定義を作成することを避けます。基本的な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])