JavaScript Tips | 基本・共通ユーティリティ:型チェック – Date 判定

JavaScript JavaScript
スポンサーリンク

「Date 判定」とは何を見分けたいのか

ここでいう「Date 判定」は、その値が「本物の Date オブジェクトかどうか」を見分けることです。
業務では「日付を表す値」がたくさん出てきますが、その正体はだいたい次のどれかです。

  • Date オブジェクト(new Date()
  • 日付文字列("2025-02-05" など)
  • タイムスタンプ(1738742400000 のような数値)
  • nullundefined(未設定)
  • よく分からない値(バグで混入したもの)

「これは Date だ」と思って value.getTime() を呼んだら、実は文字列で落ちる――
このパターンを防ぐために、「Date かどうか」をきちんと判定するユーティリティが必要になります。


typeof では Date を判定できない理由

まずは、素直に typeof を見てみます。

const d = new Date();

console.log(typeof d); // "object"
JavaScript

Date もオブジェクトの一種なので、typeof ではただの "object" にしか見えません。
つまり、typeof value === "object" では「プレーンなオブジェクト」「配列」「Date」「正規表現」などが全部混ざってしまいます。

console.log(typeof {});         // "object"
console.log(typeof []);         // "object"
console.log(typeof new Date()); // "object"
JavaScript

「Date だけを判定したい」ときに typeof は使えない、というのが最初の重要ポイントです。


Date 判定の基本:instanceof Date

一番分かりやすい Date 判定は instanceof を使う方法です。

function isDate(value) {
  return value instanceof Date;
}

console.log(isDate(new Date())); // true
console.log(isDate({}));         // false
console.log(isDate("2025-02-05"));// false
console.log(isDate(null));       // false
JavaScript

value instanceof Date は、「その値が Date コンストラクタから作られたインスタンスかどうか」を判定します。
業務コードで「普通に new Date() で作ったものだけを扱う」なら、これでほぼ足ります。

ただし、iframe や別コンテキストをまたぐような特殊なケースでは instanceof がうまく働かないこともありますが、
一般的な Web アプリや業務システムでは、まず気にしなくて大丈夫です。


「Date っぽいけど本当に有効な日付か?」という問題

もう一つ大事なポイントがあります。
new Date(...) は「失敗してもエラーを投げず、“Invalid Date” という壊れた Date オブジェクトを返す」という性質を持っています。

const d1 = new Date("2025-02-05");
const d2 = new Date("not-a-date");

console.log(d1 instanceof Date); // true
console.log(d2 instanceof Date); // true(ここがややこしい)
console.log(d1.toString());      // "Wed Feb 05 2025 ..."
console.log(d2.toString());      // "Invalid Date"
JavaScript

d2 は「Date ではあるけれど、中身が壊れている」状態です。
instanceof Date だけでは、「有効な日付かどうか」までは分かりません。

そこで、「Date かどうか」と「有効な日付かどうか」を分けて考える必要があります。


「Date かつ有効な日付か」を判定するユーティリティ

業務で本当に欲しいのは、たいてい「Date であり、かつ有効な日付であるかどうか」です。
それを判定する関数を作ってみます。

function isValidDate(value) {
  if (!(value instanceof Date)) return false;
  return !Number.isNaN(value.getTime());
}

const d1 = new Date("2025-02-05");
const d2 = new Date("not-a-date");

console.log(isValidDate(d1)); // true
console.log(isValidDate(d2)); // false
console.log(isValidDate({})); // false
console.log(isValidDate("2025-02-05")); // false
JavaScript

ここでのポイントは二つです。

一つ目は、「まず instanceof Date で Date かどうかを確認している」こと。
これで、文字列やオブジェクトが紛れ込むのを防ぎます。

二つ目は、「getTime() の結果が NaN かどうかを見ている」こと。
Invalid DategetTime()NaN になるので、Number.isNaN で弾けます。

この isValidDate を持っておくと、「Date かつ有効な日付か?」を一発で判定できるようになります。


文字列や数値から Date を作るときの流れ

実務では、「最初から Date オブジェクトが来る」ことの方が少なくて、
多くの場合は「文字列や数値から Date を作る」ところから始まります。

例えば、API から "2025-02-05T12:34:56Z" のような文字列が返ってくるケースです。

function parseDate(value) {
  if (value === null || value === undefined) return null;

  const d = new Date(value);
  return isValidDate(d) ? d : null;
}

console.log(parseDate("2025-02-05"));      // 有効な Date
console.log(parseDate("not-a-date"));      // null
console.log(parseDate(null));              // null
console.log(parseDate(1738742400000));     // タイムスタンプも OK
JavaScript

ここでは、「変換」と「判定」をセットで行っています。

変換部分:new Date(value)
判定部分:isValidDate(d)

このように、「Date に変換したあと、必ず isValidDate でチェックする」というパターンを徹底すると、
「Invalid Date が紛れ込んでバグる」事故をかなり防げます。


Date 判定ユーティリティをどう分けるか

業務ユーティリティとしては、次のように役割を分けておくと使いやすくなります。

// 単に「Date インスタンスかどうか」だけを見たいとき
function isDate(value) {
  return value instanceof Date;
}

// 「Date かつ有効な日付か」を知りたいとき
function isValidDate(value) {
  return value instanceof Date && !Number.isNaN(value.getTime());
}
JavaScript

isDate は「型チェック」、isValidDate は「型チェック+中身の妥当性チェック」というイメージです。
どちらを使うかは、「その場で何を保証したいか」で選びます。

例えば、

  • 「この関数は Date しか受け付けません」なら isDate
  • 「この時点で“壊れた日付”は絶対に通したくない」なら isValidDate

という感じです。


実務での具体的な利用イメージ

フォーム入力の日付を扱う

ユーザーがフォームで日付を入力し、それが文字列として送られてくるケースを考えます。

const raw = {
  startDate: "2025-02-05",
};

const start = parseDate(raw.startDate);

if (!isValidDate(start)) {
  console.log("開始日が不正です");
} else {
  console.log("開始日:", start.toISOString());
}
JavaScript

ここでは、「文字列 → Date に変換」「Date かつ有効かを判定」という流れを明示しています。
new Date(raw.startDate) をそのまま使ってしまうと、「Invalid Date でも気づかずに先に進む」危険があります。

期間チェック(開始日と終了日の関係)

開始日と終了日の関係をチェックするような業務ロジックでも、Date 判定は必須です。

function validatePeriod(startValue, endValue) {
  const start = parseDate(startValue);
  const end = parseDate(endValue);

  if (!isValidDate(start) || !isValidDate(end)) {
    return { ok: false, reason: "日付が不正です" };
  }

  if (end.getTime() < start.getTime()) {
    return { ok: false, reason: "終了日は開始日以降である必要があります" };
  }

  return { ok: true };
}

console.log(validatePeriod("2025-02-05", "2025-02-10")); // ok: true
console.log(validatePeriod("2025-02-10", "2025-02-05")); // ok: false
console.log(validatePeriod("not-a-date", "2025-02-05")); // ok: false
JavaScript

ここでは、「Date かどうか」と「有効な日付かどうか」をクリアしたうえで、
「開始日と終了日の大小関係」という業務ルールをチェックしています。


小さな練習で感覚をつかむ

最後に、手を動かして慣れるためのミニ課題を提案します。

自分で isDate, isValidDate, parseDate を実装して、次の値を片っ端から試してみてください。

new Date(), new Date("2025-02-05"), new Date("not-a-date"), "2025-02-05", "not-a-date", 1738742400000, {}, null, undefined

それぞれに対して、「isDate はどう返すか」「isValidDate はどう返すか」「parseDate は何を返すか」をコンソールに出してみると、
「型としての Date」と「有効な日付としての Date」を頭の中でちゃんと分けて考えられるようになります。

タイトルとURLをコピーしました