0

タイムゾーンについて黒魔術的な質問があります。

タイムスタンプ付きのイベントが必要なアプリケーションがあります。すべてをUTCで保存します。ただし、ユーザー ロケールでも UTC でもなく、特定のタイムゾーン (つまり、パリのタイムゾーン) で日付を (クライアント側で) 表示したいと考えています。

それを簡単に行う JavaScript の方法がないため (timezone.js のようなものを使用して正確な夏時間イベントを知る必要がありますが、これはやり過ぎのようです)、次のトリックを実行したいと考えました。

  • UTC 日付を取得するdutc=datetime(…,<UTC>)
  • パリの日付に変換するdparis=datetime(…,<Paris>)
  • tzinfo を強制的に UTC に戻して、パリの日付と時刻に対応する UTC タイムスタンプを取得します (例: 日付と時刻の数値は同じですが、パリではなく UTC を使用し、時間を追加または削除することはありません)。
  • この UTC 日付をタイムスタンプとして保存して、クライアントがそれを「偽の UTC」タイムスタンプとして解析し、「偽の時刻」を表示できるようにします。

ただし、元のタイムスタンプは返されません

import datetime
import time
import pytz
utc = pytz.UTC
paris = pytz.timezone('Europe/Paris')
t = 1372982409 # timestamp in UTC

dutc = datetime.datetime.fromtimestamp(t, utc) # date in UTC
# datetime.datetime(2013, 7, 5, 0, 0, 9, tzinfo=<UTC>)

dparis = datetime.datetime.fromtimestamp(t, paris) # date in Paris time
# datetime.datetime(2013, 7, 5, 2, 0, 9, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:0
0:00 DST>)

dparisasutc = dparis.replace(tzinfo=utc) # force the date in UTC time
# datetime.datetime(2013, 7, 5, 2, 0, 9, tzinfo=<UTC>)

t0 = time.mktime(dparisasutc.timetuple())
# 1372986009.0

datetime.datetime.fromtimestamp(t0)
# datetime.datetime(2013, 7, 5, 3, 0, 9) # why not 02:00:09?
4

3 に答える 3

2

あなたが望みました:

  • UTC 日付を取得 dutc=datetime(…,)
  • パリの日付に変換 dparis=datetime(…,)

わかりました、私はこれまであなたと一緒にいますが、その後...

  • tzinfo を強制的に UTC に戻して、パリの日付と時刻に対応する UTC タイムスタンプを取得します (例: 日付と時刻の数値は同じですが、パリではなく UTC を使用し、時間を追加または削除することはありません)。
  • この UTC 日付をタイムスタンプとして保存して、クライアントがそれを「偽の UTC」タイムスタンプとして解析し、「偽の時刻」を表示できるようにします。

これは悪い考えかもしれません。一般的な規則では、整数として表されるタイムスタンプは常に UTC に基づいています。これは、ほぼどこでも当てはまります (特定の Microsoft .Net タイプは例外です)。

クライアントは JavaScript を使用しているため、整数は 1970 年 1 月 1 日 UTC からのミリ秒数であると予想されます。それを変更すると、いくつかの奇妙な結果が生じます。最も興味深いのは、誤って適用される夏時間に関するユーザー独自のローカル タイム ゾーンのルールを取得することです。これらは、テストで見つけるのが非常に難しい場合があります。

DateJavaScript でタイプをまったく使用しないという最も簡単な答えです。サーバー上で完全にパリ時間への変換を行い、適切な形式の文字列をブラウザーに返します。

より興味深い解決策は、整数または のような ISO8601 文字列として UTC 時刻を渡すこと2013-08-21T17:29:00Zです。Europe/Parisクライアントでは、UTC 時刻を認識してゾーンに変換できるライブラリを使用します。timezone.js を使用してこれを行いたくないとおっしゃいましたが、他にも選択できるライブラリがいくつかあります。いくつかは非常に小さく、関心のあるゾーンの日付だけを含めることができます.

たとえば、 moment-timezoneアドオンでmoment.jsを試してください。特に、ゾーン データのみを含む moment-timezone-data.js ファイルを作成できます。(そのサイトには、このための優れたインタラクティブなデータビルダーがあります。)Europe/Paris

于 2013-08-21T17:38:13.457 に答える
1

タイムゾーンの.localize()メソッドを使用して、UTC 以外のタイムゾーンをタイムスタンプに適用します。

>>> import datetime
>>> import time
>>> import pytz
>>> utc = pytz.UTC
>>> paris = pytz.timezone('Europe/Paris')
>>> t = 1372982409 # timestamp in UTC
>>> dparis = paris.localize(datetime.datetime.fromtimestamp(t))
>>> dparis
datetime.datetime(2013, 7, 5, 1, 0, 9, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:00:00 DST>)

過去のタイムゾーンではなく現在の正しいタイムゾーン遷移が適用されるため、 1 時間の時差が表示されることに注意してください。

次に、Python がローカル タイムゾーンをタイムスタンプに再び適用しないように、結果のタイムスタンプを再び UTC として解釈する必要があります。

>>> dparisasutc = dparis.replace(tzinfo=utc) # force the date in UTC time
>>> dparisasutc
datetime.datetime(2013, 7, 5, 1, 0, 9, tzinfo=<UTC>)
>>> t0 = time.mktime(dparisasutc.timetuple())
>>> t0
1372986009.0
>>> datetime.datetime.fromtimestamp(t0, utc)
datetime.datetime(2013, 7, 5, 1, 0, 9, tzinfo=<UTC>)
于 2013-08-21T13:29:44.850 に答える