タイムゾーン対応の日時オブジェクトを、ローカルタイムゾーンの同等のタイムゾーン非対応の日時にどのように変換しますか?
私の特定のアプリケーションでは、Django(ただし、これは実際には一般的なPython質問です):
import iso8601
....
date_str="2010-10-30T17:21:12Z"
....
d = iso8601.parse_date(date_str)
foo = app.models.FooModel(the_date=d)
foo.save()
これにより、Djangoがエラーをスローします。
raise ValueError("MySQL backend does not support timezone-aware datetimes.")
私が必要なのは:
d = iso8601.parse_date(date_str)
local_d = SOME_FUNCTION(d)
foo = app.models.FooModel(the_date=local_d)
SOME_FUNCTIONはどうなりますか?
一般に、任意のタイムゾーン対応日時を単純な(ローカル)日時に変換するには、pytz
モジュールとastimezone
を使用してローカル時間に変換し、replace
日時を単純にする:
In [76]: import pytz
In [77]: est=pytz.timezone('US/Eastern')
In [78]: d.astimezone(est)
Out[78]: datetime.datetime(2010, 10, 30, 13, 21, 12, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)
In [79]: d.astimezone(est).replace(tzinfo=None)
Out[79]: datetime.datetime(2010, 10, 30, 13, 21, 12)
ただし、特定の日時はUTCタイムゾーンにあるように見えるため、代わりにこれを行うことができます。
In [65]: d
Out[65]: datetime.datetime(2010, 10, 30, 17, 21, 12, tzinfo=tzutc())
In [66]: import datetime
In [67]: import calendar
In [68]: datetime.datetime.fromtimestamp(calendar.timegm(d.timetuple()))
Out[68]: datetime.datetime(2010, 10, 30, 13, 21, 12)
ちなみに、単純なローカルの日付時刻ではなく、単純なUTC日付時刻として日付時刻を保存した方がよい場合があります。これにより、データは現地時間に依存せず、必要な場合にのみ現地時間または他のタイムゾーンに変換できます。可能な限りユニコードで動作し、必要な場合にのみエンコードすることに似ています。
したがって、単純なUTCで日付時刻を保存するのが最善の方法であることに同意する場合、必要なことは以下を定義することだけです。
local_d = d.replace(tzinfo=None)
Django(少なくとも1.4.1)の最近のバージョンでは:
from Django.utils.timezone import localtime
result = localtime(some_time_object)
ポータブルで堅牢なソリューションでは、tzデータベースを使用する必要があります。ローカルタイムゾーンを pytz
tzinfo
オブジェクトとして取得するには、 se tzlocal
module :
#!/usr/bin/env python
import iso8601
import tzlocal # $ pip install tzlocal
local_timezone = tzlocal.get_localzone()
aware_dt = iso8601.parse_date("2010-10-30T17:21:12Z") # some aware datetime object
naive_local_dt = aware_dt.astimezone(local_timezone).replace(tzinfo=None)
注:次のようなものを使用したくなるかもしれません:
#!/usr/bin/env python3
# ...
naive_local_dt = aware_dt.astimezone().replace(tzinfo=None)
ローカルタイムゾーンに可変utcオフセットがあるが、pythonは特定のプラットフォームでタイムゾーンデータベースの履歴を使用しない場合、失敗する可能性があります。
_python-dateutil
_を使用すると、UTC/Zuluタイムゾーンでdatetime
を認識できるdateutil.parsrser.parse()
を使用してiso-8561形式の日付を解析できます。
.astimezone()
を使用すると、別のタイムゾーンの認識された日時に変換できます。
.replace(tzinfo=None)
を使用すると、認識されている日時が単純な日時に変換されます。
_from datetime import datetime
from dateutil import parser as datetime_parser
from dateutil.tz import tzutc,gettz
aware = datetime_parser.parse('2015-05-20T19:51:35.998931Z').astimezone(gettz("CET"))
naive = aware.replace(tzinfo=None)
_
一般的に、すべての日付をUTCに変換して保存し、必要に応じてローカルに戻すことをお勧めします。 aware.astimezone(tzutc()).replace(tzinfo=None)
を使用して、UTCであることを確認し、ナイーブに変換します。