.NET での時刻のシリアライズで失敗したという話。
背景
.NET の DateTime 構造体 (System) は、時刻とは別に、その値が現地時刻なのか、世界協定時刻(UTC)なのか、その辺不明(Unspecified)なのかを持っている。
その辺を明示しないでDateTime構造体を構築すると、その辺不明の値になる。
その辺不明のDateTime値は大体において現地時刻相当で扱われる。 特に意識しないで時刻を扱う場合は、今いる場所の時刻だろうから、妥当な扱いだと思う。
で、DateTime構造体には DateTime.ToUniversalTime メソッド (System) という、呼べばUTCを返してくれるいい感じのメソッドがある。
やらかしたこと
- UTC(ISOで尻がZ)な時刻文字列を DateTime にする
- なんも考えないでシリアライズして永続化する
- ここでタイムゾーン情報消えた
- なんも考えないでデシリアライズして DateTime にする
- DateTimeKind.UnspecifiedなDateTimeになった
- なんも考えないで ToUniversalTime() してUTCにした気になる
- +09:00 な時刻からUTC変換した感じに -9 時間された
- 2 に戻る
教訓
時刻をシリアライズするときにはタイムゾーンに関する情報を持たせるようにしましょう。
続きを読む