はじめに
日本向けの Web サービスを Vercel にデプロイすると、必ずと言っていいほどハマる問題がある。タイムゾーンだ。
Vercel のサーバーは UTC(協定世界時)で動作する。一方、日本は JST(UTC+9)。この9時間のズレが、日時処理のあらゆる場面で問題を引き起こす。
問題の発見
2026年1月26日、Wakulier のスケジュール一括調整機能を Claude Code で実装していたときのこと。開発日記にはこう書いた。
JSTタイムゾーン問題との戦い(最も苦労した) VercelはUTCサーバーで動作するため、JavaScriptの
DateメソッドがUTC時刻を返す問題に何度もハマった。
ローカル開発環境(JST)では正しく動作するのに、Vercel にデプロイすると日付がズレる。典型的な「本番環境でのみ発生する」バグだった。
なぜ問題が起きるのか
JavaScript の Date オブジェクトは、サーバーのローカルタイムゾーンに依存する。
const date = new Date();
date.setHours(10, 0, 0, 0);
このコードは「10時」を設定しているように見えるが、実際には「サーバーのローカルタイムの10時」を設定している。
- ローカル開発(JST): 10:00 JST
- Vercel(UTC): 10:00 UTC = 19:00 JST
同じコードなのに、環境によって9時間もズレる。
具体的なハマりパターン
パターン1: setHours() の罠
開発日記に記録した問題のコード。
// ❌ 問題のコード
date.setHours(10, 0, 0, 0); // UTC 10:00 = JST 19:00
朝10時の予定を設定したつもりが、夜7時になってしまう。
パターン2: setDate() の罠
日付を1日進めるコードも問題だった。
// ❌ 問題のコード
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
深夜0時 JST = 前日15時 UTC のタイミングで実行すると、「明日」の計算結果が想定と異なる。
解決策: 明示的なタイムゾーン指定
Claude Code と原因を追跡した結果、解決策は「明示的にJST(+09:00)オフセットを付与」することだとわかった。
解決策1: ISO 8601 形式でオフセットを指定
// ✅ 解決策
const jstDateStr = "2026-01-26";
const jstDateTimeStr = `${jstDateStr}T10:00:00+09:00`;
const date = new Date(jstDateTimeStr); // 確実に JST 10:00
+09:00 を明示することで、どのサーバーで実行しても同じ結果になる。
解決策2: ミリ秒計算で日付操作
setDate() の代わりにミリ秒加算を使う。
// ✅ 解決策
const tomorrow = new Date(date.getTime() + 24 * 60 * 60 * 1000);
タイムゾーンに依存しない純粋な時間計算になる。
解決策3: 日付ライブラリの活用
複雑な日時処理には date-fns-tz や dayjs のタイムゾーンプラグインを使うのも手だ。
import { formatInTimeZone } from 'date-fns-tz';
const jstDate = formatInTimeZone(
new Date(),
'Asia/Tokyo',
'yyyy-MM-dd HH:mm:ss'
);
クライアント側の注意点
サーバー側だけでなく、クライアント側にも罠がある。
datetime-local 入力の処理
HTML の <input type="datetime-local"> はタイムゾーン情報を含まない。
<input type="datetime-local" value="2026-01-26T10:00">
この値をそのままサーバーに送ると、サーバー側で UTC として解釈される可能性がある。
対策: クライアント側でタイムゾーンを付与してから送信する。
const localValue = "2026-01-26T10:00";
const jstValue = `${localValue}:00+09:00`;
学んだこと
開発日記には3つの教訓を書いた。
- Vercel(UTC)でのJST日時処理は明示的なオフセット付与が必須
setDate(),setHours()などの破壊的メソッドはサーバーのローカルタイムゾーンに依存するため避ける- ドキュメント化が大事(JSTタイムゾーン処理パターンをCLAUDE.mdに追記)
特に3つ目が重要だ。同じ問題を何度も踏まないよう、プロジェクトのドキュメントにパターンを記録しておく。
まとめ
Vercel で日本向けサービスを開発するなら、タイムゾーン問題は避けて通れない。
対処の基本方針。
- 明示的なオフセット指定:
+09:00を必ず付与 - 破壊的メソッドを避ける:
setHours(),setDate()は使わない - ミリ秒計算を活用: タイムゾーンに依存しない計算
- ドキュメント化: プロジェクト固有のパターンを記録
ローカルでは動くのに本番で動かない。その原因の多くはタイムゾーンにある。
関連記事
Zeronova(ゼロノバ)
Product Manager / AI-Native Builder
Web/IT業界19年以上・20以上のWebサービスを担当したPdM。東証プライム上場企業の子会社代表として事業経営を経験。現在はAIを駆使して企画から実装まで完結させる個人開発を実践中。