【JavaScript】日付を操作する方法|加算・減算・比較・差分計算・月末取得・曜日判定・Date の set 系メソッドまで解説

JavaScript で日付を扱うとき、現在の日時の取得だけでなく「N 日後の日付」「2 つの日付の差分」「月末日」「曜日判定」など、日付を操作する場面が実務では頻繁にあります。この記事では Date オブジェクトの set 系メソッドを中心に、日付の加算・減算・比較・差分計算・月末取得など操作系のテクニックを体系的に解説します。

この記事でわかること
・set 系メソッドで年月日時分秒を変更する方法
・日付の加算(N 日後・N 月後・N 年後)と減算
・2 つの日付の大小比較・一致判定
・日付の差分計算(日数・時間数)
・月末日(月の最終日)の取得
・曜日の取得と日本語表示
・うるう年判定
・営業日計算・日付バリデーションの実務パターン
スポンサーリンク

set 系メソッドで日付を変更する

Date オブジェクトは get 系メソッドで各要素を取得するのに対し、set 系メソッドで各要素を変更できます。

メソッド 設定する値 範囲
setFullYear(y, m, d) 年(月・日は省略可) 4桁の年
setMonth(m, d) 月(日は省略可) 0〜11(1月=0)
setDate(d) 1〜31
setHours(h, m, s, ms) 0〜23
setMinutes(m, s, ms) 0〜59
setSeconds(s, ms) 0〜59
setMilliseconds(ms) ミリ秒 0〜999
setTime(ms) タイムスタンプ(エポックからのミリ秒)
JavaScript
const date = new Date("2026-03-31T10:30:00");

date.setFullYear(2027);
console.log(date); // 2027-03-31

date.setMonth(0);  // 1月(0始まり注意)
console.log(date); // 2027-01-31

date.setDate(15);
console.log(date); // 2027-01-15

date.setHours(9, 0, 0, 0); // 09:00:00.000
console.log(date); // 2027-01-15T09:00:00
setMonth0 始まりです。1月 = 0、12月 = 11 です。setMonth(12) と指定すると翌年の 1 月になります(自動繰り上がり)。

日付の加算・減算(N日後・N月後・N年後)

N 日後 / N 日前を取得する

JavaScript
function addDays(date, days) {
  const result = new Date(date);
  result.setDate(result.getDate() + days);
  return result;
}

const today = new Date("2026-03-31");
console.log(addDays(today, 7));   // 2026-04-07(7日後)
console.log(addDays(today, -3));  // 2026-03-28(3日前)
console.log(addDays(today, 365)); // 2027-03-31(1年後)

N 月後 / N 月前を取得する

JavaScript
function addMonths(date, months) {
  const result = new Date(date);
  result.setMonth(result.getMonth() + months);
  return result;
}

console.log(addMonths(new Date("2026-01-31"), 1));
// 2026-03-03(1月31日の1月後 → 2月31日は存在しないため3月3日に繰り上がり)
月の加算で月末の繰り上がり問題が発生します。1月31日の 1 月後は「2月31日」→ 存在しないため 3月3日になります。月末を超えないようにするには、加算後の月が想定と異なる場合に月末日に補正する処理が必要です。
月末補正付きの月加算
function addMonthsSafe(date, months) {
  const result = new Date(date);
  const targetMonth = result.getMonth() + months;
  result.setMonth(targetMonth);

  // 月が想定と異なる場合は月末日に補正
  if (result.getMonth() !== ((targetMonth % 12) + 12) % 12) {
    result.setDate(0); // 前月の末日に戻す
  }
  return result;
}

console.log(addMonthsSafe(new Date("2026-01-31"), 1));
// 2026-02-28(2月の末日に補正)

N 年後 / N 年前を取得する

JavaScript
function addYears(date, years) {
  const result = new Date(date);
  result.setFullYear(result.getFullYear() + years);
  return result;
}

console.log(addYears(new Date("2024-02-29"), 1));
// 2025-03-01(うるう年2/29の1年後は3/1に繰り上がり)

2つの日付を比較する

大小比較(どちらが先か)

JavaScript
const date1 = new Date("2026-03-01");
const date2 = new Date("2026-04-15");

// 比較演算子で直接比較可能
console.log(date1 < date2);  // true(date1 が先)
console.log(date1 > date2);  // false

// getTime() で数値比較も可能
console.log(date1.getTime() < date2.getTime()); // true

同じ日付かどうかを判定する

JavaScript
const a = new Date("2026-03-31");
const b = new Date("2026-03-31");

// NG: === ではオブジェクトの参照が異なるため false
console.log(a === b); // false

// OK: getTime() で数値比較
console.log(a.getTime() === b.getTime()); // true

// 日付のみ(時刻を無視して)比較する場合
function isSameDate(d1, d2) {
  return d1.getFullYear() === d2.getFullYear()
    && d1.getMonth() === d2.getMonth()
    && d1.getDate() === d2.getDate();
}
console.log(isSameDate(a, b)); // true
Date オブジェクト同士は === で比較しても参照が異なるため常に false です。必ず getTime() で数値に変換してから比較してください。

日付の差分を計算する(日数・時間数)

JavaScript
const start = new Date("2026-03-01");
const end = new Date("2026-04-15");

// ミリ秒の差分
const diffMs = end - start;

// 日数に変換
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
console.log(diffDays); // 45

// 時間数に変換
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
console.log(diffHours); // 1080
日数・時間・分・秒に分解する
function dateDiff(start, end) {
  const ms = Math.abs(end - start);
  return {
    days:    Math.floor(ms / (1000 * 60 * 60 * 24)),
    hours:   Math.floor((ms % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
    minutes: Math.floor((ms % (1000 * 60 * 60)) / (1000 * 60)),
    seconds: Math.floor((ms % (1000 * 60)) / 1000)
  };
}

console.log(dateDiff(
  new Date("2026-03-31T10:00:00"),
  new Date("2026-04-02T15:30:45")
));
// { days: 2, hours: 5, minutes: 30, seconds: 45 }

月末日(月の最終日)を取得する

new Date(year, month, 0) で前月の末日を取得するテクニックを利用します。日に 0 を指定すると「その月の 0 日目 = 前月の最終日」になるという Date の仕様を活用しています。

JavaScript
function getLastDay(year, month) {
  // month は 1始まり(1月=1)で受け取る
  return new Date(year, month, 0).getDate();
}

console.log(getLastDay(2026, 2));  // 28(2月)
console.log(getLastDay(2024, 2));  // 29(うるう年の2月)
console.log(getLastDay(2026, 4));  // 30(4月)
console.log(getLastDay(2026, 12)); // 31(12月)

曜日を取得する

getDay() は曜日を 0(日曜)〜 6(土曜)の整数で返します。

getDay() 0 1 2 3 4 5 6
曜日
JavaScript
const dayNames = ["日", "月", "火", "水", "木", "金", "土"];

const date = new Date("2026-03-31");
console.log(dayNames[date.getDay()]); // "火"

// toLocaleDateString で曜日を含めたフォーマット
console.log(date.toLocaleDateString("ja-JP", {
  year: "numeric", month: "long", day: "numeric", weekday: "long"
}));
// "2026年3月31日火曜日"

うるう年を判定する

JavaScript
function isLeapYear(year) {
  return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}

console.log(isLeapYear(2024)); // true
console.log(isLeapYear(2026)); // false
console.log(isLeapYear(2000)); // true(400の倍数)
console.log(isLeapYear(1900)); // false(100の倍数だが400の倍数ではない)

// Date を使った別解(2月29日が存在するか)
function isLeapYear2(year) {
  return new Date(year, 1, 29).getDate() === 29;
}
console.log(isLeapYear2(2024)); // true

実務でよく使うパターン

日付のバリデーション

JavaScript
function isValidDate(year, month, day) {
  const date = new Date(year, month - 1, day);
  return date.getFullYear() === year
    && date.getMonth() === month - 1
    && date.getDate() === day;
}

console.log(isValidDate(2026, 2, 28));  // true
console.log(isValidDate(2026, 2, 29));  // false(うるう年でない)
console.log(isValidDate(2026, 13, 1));  // false(13月は存在しない)

今日が期間内かどうか判定する

JavaScript
function isWithinPeriod(start, end) {
  const now = new Date();
  return now >= new Date(start) && now <= new Date(end);
}

console.log(isWithinPeriod("2026-01-01", "2026-12-31"));
// true(2026年内なら)

営業日(土日を除く)を計算する

JavaScript
function addBusinessDays(date, days) {
  const result = new Date(date);
  let added = 0;

  while (added < days) {
    result.setDate(result.getDate() + 1);
    const day = result.getDay();
    if (day !== 0 && day !== 6) { // 土日を除く
      added++;
    }
  }
  return result;
}

// 2026-03-31(火)の5営業日後
console.log(addBusinessDays(new Date("2026-03-31"), 5));
// 2026-04-07(火)(4/4土, 4/5日をスキップ)

関連記事

よくある質問

QsetMonth で月末の繰り上がりが発生する問題をどう回避しますか?
A1月31日に setMonth(1)(2月)を設定すると、2月31日は存在しないため 3月3日に繰り上がります。加算後の月が想定と異なる場合は setDate(0) で前月の末日に補正する処理を入れてください。本記事の addMonthsSafe 関数を参照してください。
Q2つの Date オブジェクトを === で比較しても false になるのはなぜですか?
ADate オブジェクトは参照型のため、=== はオブジェクトの参照(メモリアドレス)を比較します。同じ日時でも別のインスタンスなら false です。a.getTime() === b.getTime() で数値比較してください。
Q月末日を簡単に取得する方法は?
Anew Date(year, month, 0).getDate() で取得できます。month は 1 始まりで指定します(3月の末日なら new Date(2026, 3, 0).getDate() → 31)。日に 0 を指定すると「その月の 0 日 = 前月の最終日」になる仕様を利用しています。
QDate ライブラリ(date-fns や Day.js)を使うべきですか?
A単純な日付の加減算や比較なら標準の Date で十分です。タイムゾーン変換、複雑なフォーマット、月差分の正確な計算など高度な操作が必要な場合は date-fns や Day.js の導入を検討してください。
QTemporal API とは何ですか?
ADate の設計上の問題(ミュータブル・月の 0 始まり・タイムゾーン操作の弱さ)を解決するために提案されている新しい日時 API です。2026 年現在はまだ Stage 3(ブラウザ実装が進行中)のため、本番での使用はポリフィルが必要です。

まとめ

JavaScript で日付を操作する方法を整理しました。

  • 加算・減算: setDate(getDate() + n) で N 日後、setMonth で N 月後
  • 比較: getTime() で数値比較(=== はNG)
  • 差分: date2 - date1 でミリ秒差分を取得し、日数・時間に変換
  • 月末日: new Date(year, month, 0).getDate()
  • 曜日: getDay()(0=日曜、6=土曜)
  • 注意点: 月は 0 始まり、月末の繰り上がり、うるう年の 2/29

日付の取得やフォーマットについては「日付を取得する方法」で詳しく解説しています。操作と取得の両方を押さえて、日付処理を確実にマスターしましょう。