終日予定がタイムゾーンでズレるのは当たり前というはなし
終日予定がズレるのは仕様です!
カレンダーやスケジュールアプリを作ってると、誰しも一度はハマる沼があります。
それが 終日予定がタイムゾーンでズレる問題。
「え、なんで7月9日の予定が、アメリカで見ると7月8日になってんの!?」
「わたしの誕生日が1日早まって通知きたんだけど(怒)」
。。。ってユーザーから言われて、ヒヤッとしたことがあるあなた。
わかります、その気持ち。僕も最初そうでした。
仕事でタイムゾーン対応を行っていて、この問題にちょいちょい直面します。
でも大丈夫。これはバグじゃないです。
時差がある地球に生きる我々の宿命なんです。
グローバル対応するためには避けては通れない問題です。
終日予定、見た目はシンプル。でも中身は…
カレンダーで「終日」って言うと、普通は
「その日ずっと、朝から晩まで」って意味ですよね。
たとえば、
7月9日(水): 山田さん誕生日🎂
って感じ。
でも、DBの中ではどう保存されてるかというと…
start: 2025-07-09T00:00:00
end: 2025-07-10T00:00:00
timezone: UTC
……うん、なんか思ったより“ピンポイント”で保存されてるんですよ。
「終日」っていう割に、0時ジャスト〜翌日の0時ジャスト。
つまり 「24時間ぴったり」なイベント として保存されてる。
(さらに言えば一日が24時間だと思っているとサマータイムで痛い目を見ます)
この仕様、よくあるやつなんですが、ここで問題が起きます。
(いや、JSTで保存しろよってツッコミもあるとは思いますが、それはそれで問題が起きます。今回は話をわかりやすくするため割愛)
タイムゾーンが変わると「日付」が変わる!
たとえばこの予定、日本時間(UTC+9)で見てみると…
start: 2025-07-09 09:00
end: 2025-07-10 09:00
えっ、ちょっと待って。
なんで朝9時〜翌朝9時になってるの!?
そう、これが時差の威力です。
UTCで保存されてるから、日本で見たら9時間ズレるんですよ。
しかもこれをアメリカ西海岸(UTC-7)で見たら?
start: 2025-07-08 17:00
end: 2025-07-09 17:00
おいおいおい、7月9日の予定だったのに、8日に突入しちゃってるよ!
これ、マジで初見殺しです。
「それ、バグじゃないんです」って100回くらい説明したくなる
ユーザーから見たら完全にバグっぽい動作。
でも開発者としては「そう設計されてるから…」としか言えない。
これ、バグじゃないんです。
仕様です
終日予定って、実は「日付」じゃなくて「時間帯」なんですよ。
タイムゾーンによってその“終日”がいつなのか 開始時刻と終了時刻がズレて変わってしまう。
「え、地球ってそうなってんの?」って思うかもだけど、そうなってるんです地球。ぐるぐる回ってるんで。
じゃあ、どうすればズレないの?
いくつか選択肢はあります。でも、どれも完璧ではありません。
① ユーザーのローカルタイムで保存
→ 保存時点のタイムゾーンで記録。本人にはズレないけど、他のタイムゾーンで見るとズレる。
② UTCで保存して、表示時にローカル変換
→ 一番よく使われる方法(Googleカレンダーとか)。でも他のタイムゾーンから見ると、誕生日が“前夜祭”になるかも。
③ 時間を持たない「日付」だけで保存
→ 理想的に見えるけど、内部処理がめんどい。APIとかDBが「時間ないと困る〜」って泣き出す。
終日予定、ちゃんと扱うには?
ポイント
ズレる前提で設計しろ!
ユーザーに「終日がズレるなんて知らなかった!」って思わせないUIや説明を入れるのが大事だと思います。
たとえば:
- 「この予定は◯◯さんのタイムゾーン(PDT)で設定されています」と表示
- 同じ終日予定でも、他タイムゾーンの人に見せるときは“その人の今日”に変換
- もしくは「終日予定はあなたのタイムゾーンに合わせて表示されます」と事前に伝える
まとめ:世界は広い。時差はややこしい。
スケジュールアプリ開発、見た目以上に奥が深いです。
終日予定のズレで「あれ?」と思ったら、それは地球が悪いんです。あなたのコードは悪くない。
でもユーザーはそんなこと知らないので、ちゃんと丁寧に、気づかれないように設計しましょう。
それが世界に優しいアプリ開発ってもんです。
Discussion