268

データベースを使用して作成され、永続化されたpythondatetimeインスタンスがあります。datetime.utcnow()

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

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

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

4

14 に答える 14

380

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

出力

パイソン3.3
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
パイソン 2
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 オフセットの最近の変更が考慮されます。

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

于 2012-11-08T10:22:27.453 に答える
70

Python 3.9 以降、このモジュールを使用できzoneinfoます。

最初にその時間を取得しましょうutcnow()

>>> from datetime import datetime
>>> database_time = datetime.utcnow()
>>> database_time
datetime.datetime(2021, 9, 24, 4, 18, 27, 706532)

次に、タイム ゾーンを作成します。

>>> from zoneinfo import ZoneInfo
>>> utc = ZoneInfo('UTC')
>>> localtz = ZoneInfo('localtime')

次に、変換します。タイムゾーン間で変換するには、datetime が現在のタイムゾーンを認識している必要がありますastimezone()

>>> utctime = database_time.replace(tzinfo=utc)
>>> localtime = utctime.astimezone(localtz)
>>> localtime
datetime.datetime(2021, 9, 24, 6, 18, 27, 706532, tzinfo=zoneinfo.ZoneInfo(key='localtime'))

Python 3.6 から 3.8 では backports.zoneinfo モジュールが必要です:

>>> try:
>>>     from zoneinfo import ZoneInfo
>>> except ImportError:
>>>     from backports.zoneinfo import ZoneInfo

残りは同じです。

それより前のバージョンの場合は、 または が必要pytzですdateutil。datutil は zoneinfo と同様に機能します。

>>> from dateutil import tz
>>> utc = tz.gettz('UTC')
>>> localtz = tz.tzlocal()

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

pytzあいまいな時間を処理しない Python のタイム ゾーン処理の結果である別のインターフェイスがあります。

>>> import pytz
>>> utc = pytz.timezone('UTC')
# There is no local timezone support, you need to know your timezone
>>> localtz = pytz.timezone('Europe/Paris')

>>> utctime = utc.localize(database_time)
>>> localtime = localtz.normalize(utctime.astimezone(localtz))
>>> localtime
于 2010-12-30T14:42:23.970 に答える
6

私はそれを理解したと思います: エポックからの秒数を計算し、time.localtime を使用してローカル timzeone に変換し、time 構造体を 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)
于 2010-12-30T15:02:47.357 に答える
4

tzinfo標準の Python ライブラリには、実装はまったく含まれていません。私はいつもこれを datetime モジュールの驚くべき欠点だと考えてきました。

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

于 2010-12-30T17:29:37.623 に答える
0

Python 2 および 3 で機能する単純な (ただし欠陥がある可能性がある) 方法:

import time
import datetime

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

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

于 2016-03-09T12:15:48.353 に答える
0

私が見つけた最も簡単な方法は、現在地のタイム オフセットを取得しそれを時間から差し引くことです。

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 で機能します。

于 2016-12-13T21:50:53.470 に答える