web-dev-qa-db-ja.com

UTCの日時文字列をローカルの日時に変換する

UTCとの間で時間を変換する必要はありませんでした。最近、私のアプリにタイムゾーン対応を要求するようになり、私は自分自身をサークルで走らせてきました。現地時間からUTCへの変換に関する多くの情報は、私はかなり基本的なことであると思うかもしれませんが(ただし、私も同様に間違っているのかもしれませんが)、UTCの時間をエンドユーザーのタイムゾーンに簡単に変換することに関する情報は得られません。

一言で言えば、そしてAndroidアプリは私(appengineアプリ)のデータを送信し、そのデータ内にタイムスタンプです。そのタイムスタンプを私の使っているutc時間に保存するには:

datetime.utcfromtimestamp(timestamp)

それはうまくいっているようです。私のアプリがデータを保存するとき、それは5時間先として保存されています(私はEST-5です)

データはappengineのBigTableに格納されており、取得すると次のような文字列として出力されます。

"2011-01-21 02:37:21"

ユーザーの正しいタイムゾーンでこの文字列をDateTimeに変換する方法を教えてください。

また、ユーザーのタイムゾーン情報に推奨されるストレージは何ですか? (どのように通常あなたはtz情報を格納しますか:すなわち、 " - 5:00"や "EST"などですか?)私の最初の質問に対する答えには2番目の答えに対するパラメータが含まれるでしょう。

179
MattoTodd

あなた自身のtzinfoオブジェクトを提供したくない場合は、 python-dateutil ライブラリを調べてください。これは zoneinfo(Olson)データベース の上にtzinfoを実装したもので、やや標準的な名前でタイムゾーンの規則を参照することができます。

from datetime import datetime
from dateutil import tz

# METHOD 1: Hardcode zones:
from_zone = tz.gettz('UTC')
to_zone = tz.gettz('America/New_York')

# METHOD 2: Auto-detect zones:
from_zone = tz.tzutc()
to_zone = tz.tzlocal()

# utc = datetime.utcnow()
utc = datetime.strptime('2011-01-21 02:37:21', '%Y-%m-%d %H:%M:%S')

# Tell the datetime object that it's in UTC time zone since 
# datetime objects are 'naive' by default
utc = utc.replace(tzinfo=from_zone)

# Convert time zone
central = utc.astimezone(to_zone)

編集例を拡大してstrptimeの使用法を表示

編集2エントリポイントメソッドを改善するためのAPIの使用法を修正しました

編集3タイムゾーンの自動検出方法を追加しました。(Yarin)

336
Joe Holloway

これは、どの外部ライブラリにも依存しない回復力のある方法です。

from datetime import datetime
import time

def datetime_from_utc_to_local(utc_datetime):
    now_timestamp = time.time()
    offset = datetime.fromtimestamp(now_timestamp) - datetime.utcfromtimestamp(now_timestamp)
    return utc_datetime + offset

これにより、DelboyJayの例のタイミングの問題が回避されます。そして、Erik van Oostenの修正におけるより小さなタイミングの問題。

興味深い脚注として、上で計算されたタイムゾーンオフセットは、おそらく夏時間規則の変更が原因で、次の一見等価な式とは異なる場合があります。

offset = datetime.fromtimestamp(0) - datetime.utcfromtimestamp(0) # NO!

更新:このスニペットには現在のUTCオフセットを使用する弱点があります。これは入力日時のUTCオフセットとは異なる場合があります。別の解決策については、この回答に対するコメントを参照してください。

さまざまな時間を回避するには、渡された時間からエポック時間を取得します。これが、私がしたことです。

def utc2local (utc):
    Epoch = time.mktime(utc.timetuple())
    offset = datetime.fromtimestamp (Epoch) - datetime.utcfromtimestamp (Epoch)
    return utc + offset
36
David Foster

tzinfo オブジェクトについては、 datetime のドキュメントを参照してください。あなたはあなたがあなた自身を支えたいタイムゾーンを実行しなければなりません。ドキュメントの下部にある例です。

これは簡単な例です:

from datetime import datetime,tzinfo,timedelta

class Zone(tzinfo):
    def __init__(self,offset,isdst,name):
        self.offset = offset
        self.isdst = isdst
        self.name = name
    def utcoffset(self, dt):
        return timedelta(hours=self.offset) + self.dst(dt)
    def dst(self, dt):
            return timedelta(hours=1) if self.isdst else timedelta(0)
    def tzname(self,dt):
         return self.name

GMT = Zone(0,False,'GMT')
EST = Zone(-5,False,'EST')

print datetime.utcnow().strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(GMT).strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(EST).strftime('%m/%d/%Y %H:%M:%S %Z')

t = datetime.strptime('2011-01-21 02:37:21','%Y-%m-%d %H:%M:%S')
t = t.replace(tzinfo=GMT)
print t
print t.astimezone(EST)

出力

01/22/2011 21:52:09 
01/22/2011 21:52:09 GMT
01/22/2011 16:52:09 EST
2011-01-21 02:37:21+00:00
2011-01-20 21:37:21-05:00a
21
Mark Tolonen

あいまいな現地時間に対応する時間(DST移行中など)や現地のutcオフセットが現地のタイムゾーンの時間によって異なる場合でも正しい結果を取得するには、pytzタイムゾーンを使用します。

#!/usr/bin/env python
from datetime import datetime
import pytz    # $ pip install pytz
import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone() # get pytz tzinfo
utc_time = datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
local_time = utc_time.replace(tzinfo=pytz.utc).astimezone(local_timezone)
14
jfs

Djangoを使用している場合は、timezone.localtimeメソッドを使用できます( https://docs.djangoproject.com/en/dev/topics/i18n/timezones/ を参照)。

from Django.utils import timezone
date 
# datetime.datetime(2014, 8, 1, 20, 15, 0, 513000, tzinfo=<UTC>)

timezone.localtime(date)
# datetime.datetime(2014, 8, 1, 16, 15, 0, 513000, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)
6
frmdstryr

datetime以外のモジュールを使用したくない場合は、この回答が役立つはずです。

datetime.utcfromtimestamp(timestamp)は、単純なdatetimeオブジェクトを返します(それを意識していません)。認識しているものはタイムゾーンに対応しており、素朴ではありません。タイムゾーン間(UTCと現地時間の間など)を変換する場合は、注意が必要です。

あなたが最初の日付をインスタンス化しているのではなくても、UTC時間で素朴なdatetimeオブジェクトを作成することができるなら、あなたはそれを変換するためにこのPython 3.xコードを試すことを望むかもしれません:

import datetime

d=datetime.datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S") #Get your naive datetime object
d=d.replace(tzinfo=datetime.timezone.utc) #Convert it to an aware datetime object in UTC time.
d=d.astimezone() #Convert it to your local timezone (still aware)
print(d.strftime("%d %b %Y (%I:%M:%S:%f %p) %Z")) #Print it with a directive of choice

タイムゾーンが現在MDTである場合、その夏時間はMSTを表示するので上記のコードでは機能しないと誤って想定しないように注意してください。月を8月に変更すると、MDTが印刷されます。

意識的なdatetimeオブジェクトを取得するもう1つの簡単な方法(Python 3.xでも)は、で始まるように指定されたタイムゾーンを使用してそれを作成することです。これがUTCを使った例です。

import datetime, sys

aware_utc_dt_obj=datetime.datetime.now(datetime.timezone.utc) #create an aware datetime object
dt_obj_local=aware_utc_dt_obj.astimezone() #convert it to local time

#The following section is just code for a directive I made that I liked.
if sys.platform=="win32":
    directive="%#d %b %Y (%#I:%M:%S:%f %p) %Z"
else:
    directive="%-d %b %Y (%-I:%M:%S:%f %p) %Z"

print(dt_obj_local.strftime(directive))

Python 2.xを使用している場合、datetime.tzinfoはPython 2.xには存在しないので、おそらくdatetime.timezoneをサブクラス化し、それを使用して意識的なdatetimeオブジェクトを作成する必要があります。

5
Shule

Unix Epoch以降の時間を秒に変換するのにcalendar.timegmを使い、変換し直すにはtime.localtimeを使うことができます。

import calendar
import time

time_Tuple = time.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
t = calendar.timegm(time_Tuple)

print time.ctime(t)

(私はUTC + 03:00のタイムゾーンにいるので)Fri Jan 21 05:37:21 2011を渡します。

1
myaut

私は伝統的にフロントエンドにこれを延期します - バックエンドからの時間をUTCのタイムスタンプまたは他の日付/時刻フォーマットとして送信してから、クライアントにタイムゾーンオフセットを計算させ、このデータを適切なタイムゾーンでレンダリングさせます。

Webアプリケーションの場合、これはJavaScriptで非常に簡単に実行できます。組み込みメソッドを使用してブラウザのタイムゾーンオフセットを簡単に把握してから、バックエンドからのデータを適切にレンダリングできます。

1

これは、ローカルシステムの設定を使って時差を計算するための、すばやく汚いバージョンです。注:現在のシステムが稼働していないタイムゾーンに変換する必要がある場合、これは機能しません。BSTタイムゾーンの下でイギリスの設定でこれをテストしました。

from datetime import datetime
def ConvertP4DateTimeToLocal(timestampValue):
   assert isinstance(timestampValue, int)

   # get the UTC time from the timestamp integer value.
   d = datetime.utcfromtimestamp( timestampValue )

   # calculate time difference from utcnow and the local system time reported by OS
   offset = datetime.now() - datetime.utcnow()

   # Add offset to UTC time and return it
   return d + offset
1
DelboyJay
import datetime

def utc_str_to_local_str(utc_str: str, utc_format: str, local_format: str):
    """
    :param utc_str: UTC time string
    :param utc_format: format of UTC time string
    :param local_format: format of local time string
    :return: local time string
    """
    temp1 = datetime.datetime.strptime(utc_str, utc_format)
    temp2 = temp1.replace(tzinfo=datetime.timezone.utc)
    local_time = temp2.astimezone()
    return local_time.strftime(local_format)

utc = '2018-10-17T00:00:00.111Z'
utc_fmt = '%Y-%m-%dT%H:%M:%S.%fZ'
local_fmt = '%Y-%m-%dT%H:%M:%S+08:00'
local_string = utc_str_to_local_str(utc, utc_fmt, local_fmt)
print(local_string)   # 2018-10-17T08:00:00+08:00

たとえば、私のタイムゾーンは '+ 08:'です。入力utc = 2018-10-17T00:00:00.111Z、そして私は出力を取得します= 2018-10-17T08:00:00 + 08:

0
Eureka Bing

あなたが使用することができます 矢印

from datetime import datetime
import arrow

now = datetime.utcnow()

print(arrow.get(now).to('local').format())
# '2018-04-04 15:59:24+02:00'

arrow.get()には何でも入力できます。タイムスタンプ、ISO文字列など

0
d21d3q

答えから こちら あなたはutcからあなたのコンピュータに設定された現地時間に変換するためにtimeモジュールを使うことができます:

utc_time = time.strptime("2018-12-13T10:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
utc_seconds = calendar.timegm(utc_time)
local_time = time.localtime(utc_seconds)
0
franksands