2018/11/30

[Python] datetime のコンストラクタでタイムゾーンは指定しない方がよい

以下を見てください。
日本のタイムゾーンが `+9:19` になってしまいました。

```python
>>> import datetime, pytz
>>> datetime.datetime(2018, 9, 1, tzinfo=pytz.timezone('Asia/Tokyo'))
datetime.datetime(2018, 9, 1, 0, 0, tzinfo=)
```

調べてみると、pytz 2017.2 以降を使う場合、上記のような動作になるようです。

原因については、以下のコメント欄が参考になります。(以下の記事で触れているのは `replace` でタイムゾーン指定した場合ですが、コンストラクタで指定した場合も同様)

> 参考
>
> [pytzの仕様が変わっている - Qiita](https://qiita.com/higitune/items/0ca244373d380cf1c060)


簡単に言うと、「複数のタイムゾーン(UTC オフセット)を持つエリアでは、日付が決まらないとオフセットが決定できないので、
勝手にデフォルトのオフセットが採用される」ということのようです。

一般的に「複数のタイムゾーンを持つエリア」といえば、サマータイムがあるようなエリアで、日本は当てはまらない気がします。
ところが、日本は 1887年以前は今とは異なるタイムゾーン (`+09:18:59`9:19:00 ではない。pytz は秒まで持てないからね…) だったそうです。

> 参考
>
> [一行入魂 PostgreSQLのtime zoneについて](http://aoyagikouhei.blog8.fc2.com/blog-entry-61.html)

pytz 2017.2 以降はこれを厳密に守るようになったということみたいですねとはいえ、100年以上前のタイムゾーンがデフォルトってどうなのよ?と思いますが…。

というわけで、aware な datetime オブジェクトを作成するには、
一度 native で作成してから aware に変換するのが正しいやり方のようです。

```python
>>> import datetime, pytz
>>> dt = datetime.datetime(2018, 9, 1)
>>> pytz.timezone('Asia/Tokyo').localize(dt)
datetime.datetime(2018, 9, 1, 0, 0, tzinfo=)
```

今回、たまたま日本のタイムゾーンで問題が起こって調べましたが、他のタイムゾーンサマータイムがあるなどでは同じ問題が前からあったということですね多分。確認はしていないけど。

0 件のコメント: