この記事の対象読者
- 日付入力や予約画面を作る人
- UTC/JSTで混乱したことがある人
- JavaScriptの
Dateをなんとなく使っていて不安な人
本題に入る前に
予約日、締切日、集計日。業務アプリには日付がたくさん出てきます。
ところが、画面では7月1日だったのに、DBやログでは6月30日に見えることがあります。最初に見るとかなり焦りますよね。
この手のズレは、コードが派手に壊れているというより、「日付だけ」と「日時」を同じように扱っていると起きやすいです。
この記事では、TypeScriptで日付を扱うときに、最初に分けて考えたいことを整理します。
「日付だけ」と「日時」は違う
まず分けたいのはこの2つです。
| 種類 | 例 | 意味 |
|---|---|---|
| 日付だけ | 2026-07-01 |
その日を表す |
| 日時 | 2026-07-01T10:00:00+09:00 |
具体的な時刻を表す |
誕生日や対象日、集計日などは「日付だけ」で扱いたいことがあります。
一方、予約開始時刻や作成日時、ログ時刻は「日時」として扱うことが多いです。
この2つを混ぜると、1日ズレたように見えることがあります。
toISOStringで日付が変わる例
JavaScriptの Date は時刻を含みます。
const date = new Date("2026-07-01T00:00:00+09:00");
console.log(date.toISOString());
出力はこうなります。
2026-06-30T15:00:00.000Z
JSTの7月1日0時は、UTCでは6月30日15時です。
これは間違いではありません。ただ、画面で「7月1日」と見ていた人が、ログで「6月30日」を見るとびっくりします。
日付だけなら文字列で持つ選択肢もある
業務上「日付だけ」が大事な項目なら、YYYY-MM-DD の文字列として扱う選択肢があります。
type DateOnly = string; // "2026-07-01"
type DailyReport = {
reportDate: DateOnly;
errorCount: number;
};
もちろん、文字列なら何でもよいわけではないので、バリデーションは必要です。
function isDateOnly(value: string) {
return /^\d{4}-\d{2}-\d{2}$/.test(value);
}
日付だけでよいものを無理に Date にすると、タイムゾーン変換が入り込んで分かりにくくなることがあります。
APIで決めておきたいこと
API設計では、次のように決めておくと安心です。
作成日時: UTCのISO文字列で返す
予約開始日時: タイムゾーン付きISO文字列で扱う
集計日: YYYY-MM-DD の文字列で扱う
画面表示: ユーザーのタイムゾーンで整形する
大事なのは、項目ごとに「これは日付だけなのか、日時なのか」を決めることです。
まとめ
日付ズレは、JavaScriptが悪いというより、日付の意味が曖昧なまま実装されると起きやすいです。
「日付だけ」と「日時」を分ける。UTCなのかJSTなのか、画面表示なのか保存形式なのかを分ける。
この整理だけでも、日付まわりの不具合はかなり追いやすくなります。