---
type: how-to
language: javascript
slug: string/format-date
title: "日付を「2026-09-08」や「2026年9月8日」に整形する"
title_tag: "JavaScript 日付の整形 — YYYY-MM-DD と和暦表記の作り方"
summary: >
  日付を決まった形の文字列にする方法をまとめます。Intl.DateTimeFormat と toISOString の
  使い分け、時間帯で結果が変わる落とし穴、月が0から始まる罠まで実行して確かめます。
description: >
  Intl.DateTimeFormat には timeZone を必ず書きます。書かないと読み手の場所で日付が変わります。月が0から始まる罠、ハイフンとスラッシュで別の瞬間になる違いまで扱います。
status: published
difficulty: 2
minutes: 9

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

sources:
  - title: "Date Objects — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-date-objects"
  - title: "Intl.DateTimeFormat — ECMAScript® 2026 Internationalization API Specification"
    url: "https://tc39.es/ecma402/#datetimeformat-objects"
  - title: "Date.prototype.toISOString — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString"

terms: [時間帯, ISO 8601, ロケール, 協定世界時]

links:
  related:
    - javascript/learn/string/slice
    - javascript/how-to/string/to-number

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

## 答え

**人に見せるなら `Intl.DateTimeFormat`。**[key:時間帯を必ず書きます]。

```js run
const date = new Date('2026-09-08T12:34:56Z');

const formatter = new Intl.DateTimeFormat('ja-JP', {
  dateStyle: 'long',
  timeZone: 'Asia/Tokyo',
});

console.log(formatter.format(date));
```
```output
2026年9月8日
```

**保存や送信に使う `2026-09-08` なら `toISOString()` を切ります。**

```js run
const date = new Date('2026-09-08T12:34:56Z');

console.log(date.toISOString().slice(0, 10));
```
```output
2026-09-08
```

この2つで、ほとんどの用が足ります。

## 使い分け

| 用途 | 書き方 | 出るもの |
|---|---|---|
| 画面に出す | `Intl.DateTimeFormat` | `2026年9月8日` |
| 保存・送信・比較 | `toISOString().slice(0, 10)` | `2026-09-08` |
| ファイル名 | 同上 | `2026-09-08` |

**人に見せる形と、機械が読む形を混ぜないでください。**
`2026年9月8日` を保存すると、あとで並べ替えも比較もできなくなります。

## 見せ方をもっと細かく

`dateStyle` と `timeStyle` の組み合わせで、たいていの形が作れます。

```js run
const date = new Date('2026-09-08T12:34:56Z');
const tokyo = { timeZone: 'Asia/Tokyo' };

console.log(date.toLocaleDateString('ja-JP', tokyo));
console.log(new Intl.DateTimeFormat('ja-JP', { dateStyle: 'full', timeStyle: 'short', ...tokyo }).format(date));
console.log(new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeZone: 'UTC' }).format(date));
```
```output
2026/9/8
2026年9月8日火曜日 21:34
Sep 8, 2026
```

**曜日も、英語表記も、自分で表を持たずに出せます。**
`ja-JP` を `en-US` に変えるだけで英語になります。

## いちばん多い落とし穴：時間帯

`Intl` の例で `timeZone` を毎回書いているのには理由があります。
**書かないと、実行した環境の時間帯で結果が変わります。**

上の例の日付は[type:協定世界時]で `12:34` です。
これを日本時間で見れば `21:34`、ニューヨークで見れば同じ日の朝になります。
**同じコードなのに、見る場所で違う日付が出ます。**

```js run
const date = new Date('2026-09-08T12:34:56Z');

// ★時間帯を書かないと、あなたの環境の時間帯で出ます。
//   このページを開いている場所によって結果が変わります。
console.log(date.toLocaleDateString('ja-JP'));
console.log(date.toLocaleDateString('ja-JP', { timeZone: 'Asia/Tokyo' }));
```

**上の例には出力を載せていません。** 載せられないからです。
実行して、2行が同じになるか確かめてみてください。
[dim:日本時間の環境なら同じになります。違う地域なら1行目だけずれます。]

**保存するなら、時間帯の要らない `toISOString()` を使ってください。**
これは常に協定世界時なので、どこで実行しても同じ文字列になります。

## 「今日」を使うとき

`new Date()` は[key:実行した瞬間]を持ちます。

```js
const today = new Date();

console.log(today.toISOString().slice(0, 10));
```

[dim:このページのコード例は掲載してある出力と突き合わせているので、実行のたびに変わるものは載せていません。上の例は形だけです。]

**「今日」を日本時間で決めたいときは、時間帯を指定して取り出します。**

```js run
const date = new Date('2026-09-08T15:30:00Z');

// ★協定世界時では 9/8、日本時間ではもう 9/9
console.log(date.toISOString().slice(0, 10));
console.log(new Intl.DateTimeFormat('sv-SE', { timeZone: 'Asia/Tokyo' }).format(date));
```
```output
2026-09-08
2026-09-09
```

[dim:`sv-SE`（スウェーデン語）を使うと `YYYY-MM-DD` の形で出ます。時間帯を指定した ISO 風の日付を作る近道としてよく使われます。]

## 自分で組み立てる

`Intl` を使わず、成分から作ることもできます。**月が[num:0]から始まる**ことに注意してください。

```js run
const date = new Date(2026, 8, 8, 5, 3);
const pad = (n) => String(n).padStart(2, '0');

console.log(date.getMonth());
console.log(`${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`);
console.log(`${pad(date.getHours())}:${pad(date.getMinutes())}`);
```
```output
8
2026-09-08
05:03
```

`getMonth()` は[num:8]を返します。**9月なのに8です。**
[bad:`+ 1` を忘れると1か月ずれます]。日付だけ `getDate()` が[num:1]始まりなので、余計に間違えやすい場所です。

[dim:上の例は `new Date(2026, 8, 8)` と成分から作っています。この作り方と `getMonth()` などの読み方はどちらもローカル時間なので、どこで実行しても同じ結果になります。]

## よくある間違い

### `-` と `/` で意味が変わる

ハイフンで書いた日付は、**どこで実行しても同じ瞬間**になります。

```js run
console.log(new Date('2026-09-08').toISOString());
```
```output
2026-09-08T00:00:00.000Z
```

スラッシュで書くと、そうなりません。

```js
console.log(new Date('2026/09/08').toISOString());
```

**この例にも出力を載せていません。** 環境で変わるからです。
実行して、上の `00:00:00.000Z` と同じになるか確かめてみてください。

- `2026-09-08`（ハイフン）… [type:ISO 8601]として読まれ、[key:協定世界時]の0時
- `2026/09/08`（スラッシュ）… [key:実行環境の時間帯]の0時

日本時間なら9時間ずれます。**日付だけを比べているつもりで、時刻がずれて前日になります。**

**文字列から日付を作るなら、ハイフンの ISO 形式に統一してください。**

### 壊れた日付に気づかない

```js bad
const date = new Date('きのう');

console.log(String(date));
console.log(date.getTime());
```
```output
Invalid Date
NaN
```

**例外は出ません。** `Invalid Date` という日付になり、以後の計算が全部 `NaN` になります。

受け取った文字列から日付を作るときは、必ず確かめてください。

```js run
function parseDate(text) {
  const date = new Date(text);

  return Number.isNaN(date.getTime()) ? null : date;
}

console.log(parseDate('2026-09-08')?.toISOString() ?? '読めません');
console.log(parseDate('きのう')?.toISOString() ?? '読めません');
```
```output
2026-09-08T00:00:00.000Z
読めません
```

`getTime()` が `NaN` かどうかが、[key:唯一の判定方法]です。
[bad:`date === 'Invalid Date'` のような比較は効きません]。

## まとめ

- 人に見せるなら `Intl.DateTimeFormat`。**`timeZone` を必ず書く**
- 保存・比較なら `toISOString().slice(0, 10)`。どこでも同じ
- **`timeZone` を省くと、読み手の場所で日付が変わる**
- `getMonth()` は[num:0]始まり。`+ 1` を忘れない
- `-` は協定世界時、`/` はローカル。**混ぜない**
- 読めない文字列でも例外は出ない。`Number.isNaN(date.getTime())` で見る

桁を揃える `padStart()` そのものの挙動（すでに長いとき、埋める文字が複数のとき）はこちらにあります。
→ [文字列を切り出す・整える](/ja/javascript/learn/string/slice/)

日付の文字列を数値として扱いたいときの落とし穴（`NaN` の見分け方）は、こちらでも扱っています。
→ [文字列を数値に変換する](/ja/javascript/how-to/string/to-number/)
