web-dev-qa-db-ja.com

Unixタイムスタンプから日時までDjango with timezone

Unixtimestampを送信しているJavaScriptカレンダーがあります。私はシンガポールにいます。このタイムスタンプをシンガポールのタイムスタンプとして解釈し、dbと比較するためにUTCに変換したいと思います。

私は、自分の人生のために、このタイムスタンプが現在のタイムゾーンであるシンガポールからのものであることをDjangoに伝える方法を理解できません。

タイムスタンプの印刷ステートメントを実行すると、時刻に8時間が追加されます(つまり、Djangoは、UTCで時刻を入力したと見なし、シンガポールのコンテキストにローカライズしています)

他の多くのことの中で、私は試しました:start=datetime.datetime.fromtimestamp(int(start_date)).replace(tzinfo=get_current_timezone())

Start_dateは1325376000です(これは2012-01-01 00:00:00に変換されます)

ただし、これの出力を印刷すると、2012-01-01 08:00:00 + 06:55が表示されます。シンガポールが+08:00のときに+06:55がどこから来ているのかさえわかりません。私はSO失われました。

ご協力いただきありがとうございます。

settings.py:

TIME_ZONE = 'Asia/Singapore'

USE_TZ = True

18
nknj

pytzがインストールされていると仮定します。

from datetime import datetime
import pytz
local_tz = pytz.timezone("Asia/Singapore") 
utc_dt = datetime.utcfromtimestamp(timestamp).replace(tzinfo=pytz.utc)
local_dt = local_tz.normalize(utc_dt.astimezone(local_tz))

例えば:

>>> from datetime import datetime
>>> import pytz
>>> local_tz = pytz.timezone("Asia/Singapore")
>>> utc_dt = datetime.utcfromtimestamp(1325376000).replace(tzinfo=pytz.utc)
>>> utc_dt
datetime.datetime(2012, 1, 1, 0, 0, tzinfo=<UTC>)
>>> local_dt = local_tz.normalize(utc_dt.astimezone(local_tz))
>>> local_dt
datetime.datetime(2012, 1, 1, 8, 0, tzinfo=<DstTzInfo 'Asia/Singapore' SGT+8:00:00 STD>)
>>> local_dt.replace(tzinfo=None)
datetime.datetime(2012, 1, 1, 8, 0)
22
David Wolever

上記のすべてのメソッドは有効ですが、「Djangolike」ではありません。これは簡単な例です。Djangoプログラマーがそれを行う方法:

from datetime import datetime

from Django.utils.timezone import make_aware


# valid timestamp
value = 1531489250 
# you can pass the following obj to a DateTimeField, when your settings.USE_TZ == True
datetime_obj_with_tz = make_aware(datetime.fromtimestamp(value))

Django githubタイムゾーンモジュール のその他のユーティリティを参照して、全体の概要を確認してください...

16
AntonTitov

Pytztzinfoオブジェクトをfromtimestamp()メソッドに渡します。

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

tz = pytz.timezone("Asia/Singapore")
print(datetime.fromtimestamp(1325376000, tz))
# -> 2012-01-01 08:00:00+08:00
_

注:結果オブジェクトはタイムゾーンに対応しています。他の対応する日時オブジェクトと比較できます。つまり、比較のためにUTCに変換する必要はありません。そのまま使用できます。

シンガポールが+08:00のときに+06:55がどこから来ているのかさえわかりません。

無効な.replace()呼び出しが原因で、_+06:55_が表示されます。 get_current_timezone()は、可変utcオフセットを持つpytz.timezone("Asia/Singapore")を返します(異なる日付で異なるutcオフセットを持つ場合があります)。 .replace()を呼び出すと、ランダムな(実装によって異なります)tzinfoオブジェクトが使用されます。問題は、.replace()メソッドでは、pytz.timezone("Asia/Singapore")が入力日付の正しいtzinfoを選択できないことです。

_>>> list(tz._tzinfos.values())
[<DstTzInfo 'Asia/Singapore' MALT+7:00:00 STD>,
 <DstTzInfo 'Asia/Singapore' MALT+7:20:00 STD>,
 <DstTzInfo 'Asia/Singapore' JST+9:00:00 STD>,
 <DstTzInfo 'Asia/Singapore' SMT+6:55:00 STD>,
 <DstTzInfo 'Asia/Singapore' SGT+7:30:00 STD>,
 <DstTzInfo 'Asia/Singapore' MALT+7:30:00 STD>,
 <DstTzInfo 'Asia/Singapore' MALST+7:20:00 DST>,
 <DstTzInfo 'Asia/Singapore' LMT+6:55:00 STD>,
 <DstTzInfo 'Asia/Singapore' SGT+8:00:00 STD>]
_

つまり、_+06:55_と_+0800_の両方がシンガポールで有効です(異なる日付で)。そのため、.replace()は、utcタイムゾーン自体などの一定のutcオフセットを持つタイムゾーンでのみ使用する必要があります(オフセットはゼロ、常に任意の日付)。

fromtimestamp(,tz)メソッドはtz.fromutc()を内部的に呼び出します。これによりtzは特定のUTC時間の正しいオフセットを選択できます。

6
jfs