---
type: how-to
language: javascript
slug: date/diff
title: "2つの日付の差を日数で出す"
title_tag: "JavaScript 日付の差 — 日数を正しく数える方法"
summary: >
  引き算するとミリ秒が返ります。86400000 で割れば日数ですが、時刻が混ざると1日ずれます。
  日付だけに揃えてから引く形、負の差、月をまたぐ場合、年齢の数え方まで実行して確かめます。
description: >
  日付の引き算はミリ秒を返します。時刻が入っていると「日をまたいだのに0日」になります。
  日付だけに揃えてから引く書き方と、年齢を正しく数える形を実行して確かめられます。
status: published
difficulty: 2
minutes: 8

versions:
  verified: "Node 22.22.3"
  since: "ES1"
  deprecated: null
  removed: null

sources:
  - title: "Date Objects — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-date-objects"
  - title: "Date.prototype.getTime — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-date.prototype.gettime"
  - title: "Date() コンストラクター — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/Date"

terms: [経過時間, 時間帯, 切り捨て]

links:
  related:
    - javascript/reference/date/date
    - javascript/how-to/string/format-date
    - javascript/reference/number/rounding

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

## 答え

**引き算するとミリ秒が返ります。**

```js run
const from = new Date(2026, 8, 1);
const to = new Date(2026, 8, 8);

const ms = to - from;

console.log(ms);
console.log(ms / 86400000);
```
```output
604800000
7
```

`86400000` は1日のミリ秒（`24 * 60 * 60 * 1000`）です。

[dim:`new Date(2026, 8, 1)` の月は0から数えるので、これは9月1日です。]
→ [Date — 作る・比べる・差を出す](/ja/javascript/reference/date/date/)

## 時刻が混ざると1日ずれる

**ここが本当の落とし穴です。**

```js bad
const from = new Date(2026, 8, 1, 23, 0);
const to = new Date(2026, 8, 2, 1, 0);

console.log((to - from) / 86400000);
console.log(Math.floor((to - from) / 86400000));
```
```output
0.08333333333333333
0
```

**日をまたいでいるのに `0` 日です。**
差は2時間しかないので、当然といえば当然です。

「何日前か」を出したいなら、**先に時刻を落としてください。**

```js run
function toDay(date) {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate());
}

const from = new Date(2026, 8, 1, 23, 0);
const to = new Date(2026, 8, 2, 1, 0);

console.log((toDay(to) - toDay(from)) / 86400000);
```
```output
1
```

**求めているのが[key:経過時間]なのか[key:日付の枚数]なのかを、先に決めてください。**
この2つは別のものです。

| 知りたいこと | 書き方 |
|---|---|
| 経過した時間 | そのまま引く |
| 日付が何枚またいだか | **0時に揃えてから引く** |

## 順番が逆だと負になる

```js run
const a = new Date(2026, 0, 31);
const b = new Date(2026, 1, 1);

console.log((b - a) / 86400000);
console.log((a - b) / 86400000);
console.log(Math.abs((a - b) / 86400000));
```
```output
1
-1
1
```

月をまたいでも、**月末の日数を気にする必要はありません。**
内部では通し番号のミリ秒で持っているからです。

「何日前か」を表示するなら `Math.abs()` を使うか、
[bad:負のまま出さないよう]どちらが先かを決めてください。

## 割り切れないことがある

日数に直すとき、`Math.round()` と `Math.floor()` で結果が変わります。

```js run
const from = new Date(2026, 8, 1);
const to = new Date(2026, 8, 3, 12, 0);

const days = (to - from) / 86400000;

console.log(days);
console.log(Math.floor(days), Math.round(days), Math.ceil(days));
```
```output
2.5
2 3 3
```

**「2日半」を2日と呼ぶか3日と呼ぶかは仕様です。**
0時に揃えてから引けば、この迷いはそもそも起きません。

→ [四捨五入と桁の丸め](/ja/javascript/reference/number/rounding/)

## 時間・分で出す

割る数を変えるだけです。

| 欲しい単位 | 割る数 |
|---|---|
| 秒 | `1000` |
| 分 | `60000` |
| 時間 | `3600000` |
| 日 | `86400000` |

```js run
const from = new Date(2026, 8, 8, 9, 0);
const to = new Date(2026, 8, 8, 17, 30);

const ms = to - from;

console.log(ms / 60000);
console.log(ms / 3600000);
console.log(Math.floor(ms / 3600000) + '時間' + ((ms / 60000) % 60) + '分');
```
```output
510
8.5
8時間30分
```

## 「同じ日か」を知りたいだけなら

差を出す必要はありません。

```js run
function isSameDay(a, b) {
  return (
    a.getFullYear() === b.getFullYear() &&
    a.getMonth() === b.getMonth() &&
    a.getDate() === b.getDate()
  );
}

console.log(isSameDay(new Date(2026, 8, 8, 1), new Date(2026, 8, 8, 23)));
console.log(isSameDay(new Date(2026, 8, 8, 23), new Date(2026, 8, 9, 1)));
```
```output
true
false
```

**引き算より読みやすく、時刻の混入で間違えることもありません。**

## 「3日前」と表示する

自分で組み立てず、`Intl` に任せてください。

```js run
const relative = new Intl.RelativeTimeFormat('ja-JP', { numeric: 'auto' });

console.log(relative.format(-1, 'day'));
console.log(relative.format(-3, 'day'));
console.log(relative.format(2, 'day'));
console.log(relative.format(-1, 'month'));
```
```output
昨日
3 日前
明後日
先月
```

`numeric: 'auto'` を付けると、[key:1日前は「昨日」]になります。
言語を渡しているので、読み手の環境によって変わりません。

[dim:言語を省くと読み手の設定で変わります。このサイトの掲載出力が環境で変わらないよう、必ず `'ja-JP'` のように書いています。]

## 年齢を数える

**日数から割り出さないでください。**

```js bad
const birth = new Date(2000, 8, 9);
const today = new Date(2026, 8, 8);

console.log(Math.floor((today - birth) / 86400000 / 365));
```
```output
26
```

**誕生日は明日なので、正しくは 25 です。**
1年を365日として割っているので、うるう年の分だけ先に進んでしまいます。
[bad:年数が大きいほどずれます。]

**年・月・日で比べてください。**

```js run
function age(birth, today) {
  const years = today.getFullYear() - birth.getFullYear();

  const beforeBirthday =
    today.getMonth() < birth.getMonth() ||
    (today.getMonth() === birth.getMonth() && today.getDate() < birth.getDate());

  return beforeBirthday ? years - 1 : years;
}

console.log(age(new Date(2000, 8, 9), new Date(2026, 8, 8)));
console.log(age(new Date(2000, 8, 8), new Date(2026, 8, 8)));
```
```output
25
26
```

誕生日の当日に[num:1]つ増えます。

## 文字列から作るときの注意

```js run
const iso = new Date('2026-09-08');
const slash = new Date('2026/09/08');

console.log(iso.toISOString());
console.log(iso.getTime() === slash.getTime());
```
```output
2026-09-08T00:00:00.000Z
false
```

- `2026-09-08`（ハイフン）… **協定世界時**の0時
- `2026/09/08`（スラッシュ）… **その場所の**0時

日本で動かすと[num:9]時間ずれます。
**同じ書式で揃えるか、`new Date(2026, 8, 8)` のように成分から作ってください。**

[bad:片方をハイフン、もう片方をスラッシュで作って引き算すると、答えが9時間分だけ狂います。]
→ [日付を書式どおりに整える](/ja/javascript/how-to/string/format-date/)

## 実務では何を使うか

- **差を出すだけ**なら、標準の `Date` で足ります。この記事の書き方で十分です
- 「3日前」「先月の同じ日」のような**日付の計算**が増えるなら、
  専用のライブラリを検討してください。月末の扱いで必ず悩みます
- 時間帯をまたぐ集計をするなら、**どの地域の0時か**を最初に決めてください

[dim:標準にも新しい日付の仕組み（Temporal）が入りつつありますが、動く環境がまだ限られます。使う前に、対象の環境で確かめてください。]

## まとめ

- 引き算で返るのは**ミリ秒**。`86400000` で割ると日数
- **時刻が入っていると日をまたいでも0日になる**
- 「日付の枚数」を数えるなら[key:0時に揃えてから引く]
- 順番が逆なら負になる。`Math.abs()` か、順番を決める
- **年齢は日数から割り出さない。** 年・月・日で比べる
- 「同じ日か」だけなら**引き算せずに年・月・日で比べる**
- 「3日前」の表示は `Intl.RelativeTimeFormat` に任せる
- ハイフンとスラッシュで[bad:基準の時間帯が変わる]
