日時型についての雑なまとめ
概要
(今のところ)サマータイムがない日本でも、結構言及されているので、雑にまとめとく
DB視点
postgres の有名な with timezone 名前詐欺にとどまらず、ほとんどのRDBで ローカルタイムとtimezoneをセットで保持することができない
絶対時間、概念時間?
上記の記事および
でも書かれているが、timezoneは一旦置いといて、この概念を持ったほうがいい
- 絶対時間/Exact Time = システム上、これで表現すれば絶対的な時間を表現できる
- 概念時間/wall-clock Time = 多くの人間にとっての時間といえばこちら・ローカルタイム
ぜんぶ人間視点でええやんと言うのは大間違いで、サマータイムがもし始まると破綻する、サマータイムが終わるときに時間戻りが発生するから見分けがつかなくなる。
ZonedDateTime / OffsetDateTime
Asia/Tokyo と +09:00 の違い
Zonedだけでサマータイムは対応できない、DSTとか付与すれば別だが
サマータイム開始時にオフセットがずれて、終了時に戻る、らしい
人間視点・保存形式
人視点に限らず広範囲に渡り、包括的に書かれている。ユーザーの入力を OffsetDateTimeで捉えるのはまずいので、ZonedDateTimeとしておくという。
DBに保存する場合はOffsetDateTimeだが、timezoneを保持できるRDBMSはほぼ存在しない、のでUTC一択となる。
相互変換
ZonedDateTimeから 絶対時間=UTCは変換不可能、理由はサマータイムで、ゾーン名に加えてDSTか否かの情報が必要
OffsetDateTimeなら 絶対時間へ変換は可能、というか事実上UTCで書いているのとおなじ、サマータイムは+09:00 を +10:00とかにする(たぶん)
絶対時間からOffzetは余裕、Zonedへの変換はデータベースが必要、tz-infoとかいうやつ、頻繁に更新される&更新されてないと現実世界とずれる、これだけでもZonedで保存(できないのがほとんどだが)は悪手だとわかる
出力 = ふたたびDB視点
出力時にUTCで保存しているならば、クライアントの要求に合わせて timezoneを合わせてやるというのが postgreの with timezone
MySQLは、timestampならばそれができるが、こっちはunixtimestampであるせいか、2038年問題のためほぼつかわない、datetime型はサーバ側はクライアント側の要求とか関係なしに中の値をそのまま返す、timezoneはてめえで考えろスタイル
Parquetも日時はtimestampで表現。こちらにはisAdjustedToUTC
というLogicalTypeがあるが、俺の知る限り、ほとんどの処理系で無視されている
ORCも見た感じ、postgreと同じ
Prestoもパット見 postgreと同じはずだが、格納データによってどうなるかわはわらん、jsonとかならZonedをそのまま保持できるかも?
BigQueryはtimestampは、UTCだからtz付きの表現に変換できる(関数で)、datetime型は、サーバ側は一切口出ししないから、てめえで考えろスタイル & tzの前提がないので、tz変換関数が効かない
- timestampはUTC前提で格納
- クライアントの要求に合わせてサーバ側でLocalTimeに見せることは可能
- datetimeのtzはユーザー実装次第
- DB側としてはtz知らないから、口出ししない(できない)
Discussion