2017-10-19 19 views
3

pytzライブラリを使用したくないため、私が作業しているプロジェクトでは依存関係を導入するために書類作成が必要です。私が第三者の図書館なしでこれを達成できるなら、私はもっと幸せになるでしょう。日時オブジェクトをCESTタイムゾーンとUTCタイムゾーンの間で変換する方法

日付が夏時間に設定されている場合は、CETとUTCの間で日付を変換する際に問題が発生しています。

>>> print from_cet_to_utc(year=2017, month=7, day=24, hour=10, minute=30) 
2017-07-24T09:30Z 

2017-07-24T08:30Z # expected 

CETはUTCより1時間遅れ、夏時間は2時間先です。だから私は真夏の真中の10:30を実際には8:30 UTCにすると期待しています。

機能は次のとおりです。

from datetime import datetime, tzinfo, timedelta 

def from_cet_to_utc(year, month, day, hour, minute): 
    cet = datetime(year, month, day, hour, minute, tzinfo=CET()) 
    utc = cet.astimezone(tz=UTC()) 
    return '{:%Y-%m-%d:T%H:%MZ}'.format(utc) 

私は2つのタイムゾーン情報オブジェクトを使用します。

class CET(tzinfo): 
    def utcoffset(self, dt): 
     return timedelta(hours=1) 

    def dst(self, dt): 
     return timedelta(hours=2) 

class UTC(tzinfo): 
    def utcoffset(self, dt): 
     return timedelta(0) 

    def dst(self, dt): 
     return timedelta(0) 

答えて

3

ちょうど補完する@Sergey's answer

DSTの適用時期を知るには、DSTの開始日時と終了日時の履歴データを取得し、指定したdatetimeに適用するかどうかを確認する必要があります。 IANA databaseから取得するか、多くのオンラインソース(timeanddate websiteなど)に問い合わせることができます。

もう1つの詳細はby more than one timezoneであるため、CETambiguous nameです。リアルタイムタイムゾーンの名前は、the ones defined by IANA database(常にEurope/ParisまたはEurope/BerlinのようなフォーマットRegion/City)です。


ギャップとオーバーラップ

私は、一例としてEurope/Berlin timezone使用するつもりです。今年(2017年)、ベルリンのDSTは3月26日に開始しましたth:午前2時には、時計は1時間になりました。は午前3時にオフセットされ、オフセットは+01:00から+02:00に変更されました。

時計は午前1時59分から午前3時に直接ジャンプしたと考えることもできます。つまり、午前2時から午前2時59分までのすべてのローカル時刻は、その日のそのタイムゾーンに存在しませんでした。これはギャップと呼ばれ、この状況を確認する必要があります(1つの一般的なアプローチは、午前2時を有効な1時間に調整することです - この場合はDSTで3 AM)。同じ時間帯で

、2017年に、DSTは、10月29日番目に終了します:午前3時に、クロックはバック 1時間に2 AMをシフトし、+02:00から+01:00に変更され相殺します。

これは、午前2時から午前2時59分までのローカル時刻は、DST(+02:00)に1回、DST以外(+01:00)に2回存在することを意味します。これはオーバーラップと呼ばれ、この場合にはdatetimeを作成するときに、どちらを作成するかを決定する必要があります(はDSTで午前2時、またはDSTオフセットでない場合はとなります)。


PS: CETを使用して欧州各国は、今日さまざまな年でそれを採用したので、あなたは、古い日付を扱っている場合は、あまりにもすることを考慮する必要があります。

DSTは政府によって定義されているため、このようなルールは永遠に続くとは限りません。それに応じてルールを更新する必要があります。pytzを使用するもう1つの利点は、 IANAのリリースとpublished in PyPI(ありがとう@マットジョンソンpointing this info)。

これらのルールを手作業でコーディングするよりも文書処理が悪いですか?ちょうどhow to read IANA tz filesをチェックし、おそらくあなたの心を変えるでしょう。

+2

pytzのアップデートについてのあなたの意見に答えるために、IANAのリリースから生成されています。 IANA 2017b => pytz 2017.2。 Stuart Bishopはそれらを保守し、ここにpypiに公開しています。https://pypi.python.org/pypi/pytz#downloads –

+0

@MattJohnsonこの情報で回答を更新しました。ありがとうございます! –

+1

あなたとSergeyの答えはとても役に立ちました。私はあなたが私が本当に専門家に任せておくべきだと私に確信させるために一番の努力をしたと思います。私たちの解決策は、入力としてUTC時間を要求することであり、我々の部分では変換は必要ありません(c: –

3

それはそこに説明するようにあなたは、tzinfo manualを慎重にお読みください。は、通常、timedelta(0)またはtimedelta(hours=1)を返します。決して2時間以上、まれに何か(たとえば30分)を返す必要があります。これは、dstモードでの完全なTZオフセットではなく、通常のTZオフセットに対するdstシフトだけです。

第2に、utcoffset()には既にdst補正が含まれている必要があります。 dst()メソッドは、マニュアルに記載されている場合(dstが有効かどうかなど)にも使用されますが、そうしない限り自動的にTZオフセットに適用されることはありません。

あなたのコードは次のようになります。ここでは

from datetime import datetime, tzinfo, timedelta 

class CET(tzinfo): 
    def utcoffset(self, dt): 
     return timedelta(hours=1) + self.dst(dt) 

    def dst(self, dt): 
     dston = datetime(year=dt.year, month=3, day=20) 
     dstoff = datetime(year=dt.year, month=10, day=20) 
     if dston <= dt.replace(tzinfo=None) < dstoff: 
      return timedelta(hours=1) 
     else: 
      return timedelta(0) 

class UTC(tzinfo): 
    def utcoffset(self, dt): 
     return timedelta(0) 

    def dst(self, dt): 
     return timedelta(0) 

def from_cet_to_utc(year, month, day, hour, minute): 
    cet = datetime(year, month, day, hour, minute, tzinfo=CET()) 
    utc = cet.astimezone(tz=UTC()) 
    return '{:%Y-%m-%d:T%H:%MZ}'.format(utc) 


print from_cet_to_utc(year=2017, month=7, day=24, hour=10, minute=30) 
# 2017-07-24:T08:30Z 

、私は勇敢にDSTが有効20.03.YYYYであると仮定 - YYYY日付/ datetimeオブジェクトの年である包括的19.10.YYYY、。

この論理は、通常、オフ日の&の論理ははるかに複雑です。シフトは日曜日の夜だけで、時には月の最後の日曜日に発生し、時々、時には州の主権境界線も年々変化しています)、そして夏時間の法律とタイムゾーン変更は数年ごとに変わります(こんにちは、ロシア)。

+3

実際には、日中の時刻も確認する必要があります。ヨーロッパ中部では、DSTの変更は通常、午前2時から午前3時の間に行われます。とにかく、日が変わるとすぐに私はupvoteします(私は今日の私の投票限度に達しました)。 –

+0

現在、春の2:00 AM、秋の3:00 AMです。 https://www.timeanddate.com/time/change/france/paris –

+1

@Hugoあなたは正しいです。私の答えを補うためにありがとう。しかし、あなたが描いたものでさえ、氷山の一角に過ぎません。私は意図的に、質問の著者にとって問題に思えるpythonと 'datetime.tzinfo'部分についてのみ質問に答えました。実際のtz計算は非常に困難で大きなトピックですが、それは大きすぎるので、日付と時間(冗談ではない)で純粋に正しい仕事に本を書くことができます。 –

関連する問題