【JavaScript】外部ライブラリに頼らないDateフォーマット (日付編)【Intl.DateTimeFormat】

#この記事について

- JavaScriptで日付をフォーマットする方法を3種類紹介しています。
  - "/"区切り (例: 2020/7/3)
  - "西暦+年月日" (例: 2020年7月3日)
  - "和暦+年月日" (例: 令和2年7月3日)

- いろいろ検証した結果や調べたことも書いています。
- 「<font color="MediumVioletRed">**コピペしたいだけ！結論だけほしい！**</font>」という方は各章の<font color="MediumVioletRed">**「コードと解説」だけ読めばOK**</font>です。
- この記事は[前回の記事](https://qiita.com/hinaqiita/items/d5737855a3abe071a168)(時間編)の知識を前提にしています。解説で不明点があれば参考にしてみてください。

## 📅 "/"区切り (例: 2020/7/3)
日付を`年/月/日`というフォーマットで出力する方法を紹介します。

### コードと解説

Intl.DateTimeFormatの引数にlocaleを設定することで、その国の標準的な日付フォーマットを取得できます。
localeが日本(`'ja-JP'`)だと「yyyy/MM/dd」の形式で表示されます。

```javascript
const dateTimeFormat = new Intl.DateTimeFormat('ja-JP');
console.log(dateTimeFormat.format(new Date(2020, 6, 3)));
// 2020/7/3
```

### localeを`en-US`にしてみる
localeをアメリカ(`en-US`)にすると、日付は「MM/dd/yyyy」の形式で表示されます。

```javascript
const dateTimeFormat = new Intl.DateTimeFormat('en-US');
console.log(dateTimeFormat.format(new Date(2020, 6, 3)));
// 7/3/2020
```

### localeを省略してみる 

locale引数を省略すると、ブラウザ既定のロケール(タイムゾーン)を使用することになります。
よって、日本にいるほとんどの方は、引数なしでも「yyyy/mm/dd」が得られると思います。

```javascript
const dateTimeFormat = new Intl.DateTimeFormat();
console.log(dateTimeFormat.format(new Date(2020, 6, 3)));
// 2020/7/3
```

### ブラウザ既定のロケールについて

ブラウザ既定のロケール(タイムゾーン)は以下で確認できます。

```JavaScript

console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
// Asia/Tokyo
```


## 📅 "西暦+年月日" (例: 2020年7月3日)

日付の区切り文字を`/`ではなく`「年月日」`にしてみます。

### コードと解説
Intl.DateTimeFormatの第2引数にオプションを渡すことで日付のフォーマットを定義できます。

```javascript

const dateTimeFormat = new Intl.DateTimeFormat('ja-JP', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
});
console.log(dateTimeFormat.format(new Date(2020, 6, 3)));
// 2020年7月3日
```

<font color="MediumVioletRed">**ポイントは`month`のフォーマット**</font>です。
`long`、`short`、`narrow`のいずれかを設定すると年月日表記になります(後述あり)。
yearやdayのオプションはなんでもOKですが、<font color="MediumVioletRed">**省略はできません**</font>(後述あり)。

### `en-US`にしてみる

第2引数でオプションを渡しているこの状態で、第1引数のlocaleを`en-US`にすると、月の表記が英文字に変わります。 

```javascript
const dateTimeFormat = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
});
console.log(dateTimeFormat.format(new Date(2020, 6, 3)));
// July 3, 2020
```

### monthのフォーマットについて
monthのフォーマットは`long`以外にも用意されています。
locale`ja-JP`でmonthに`numeric`や`2-digit`を使うと、<font color="MediumVioletRed">**年月日表記にならない**</font>ので注意してください。

|　　    |en-US       |ja-JP        |
|-------|------------|-------------|
|numeric|7/3/2020    |<font color="MediumVioletRed">**2020/7/3**</font> |
|2-digit|07/3/2020   |<font color="MediumVioletRed">**2020/07/3**</font>|
|long   |July 3, 2020|2020年7月3日  |
|short  |Jul 3, 2020 |2020年7月3日  |
|narrow |J 3, 2020   |2020年7月3日  |



### yearとdayを省略してみる

yearとdayを省略すると、その2つが出力されなくなります。
yearだけ省略すると、yearだけ出力されなくなります。dayも同様です。

```JavaScript
const dateTimeFormat = new Intl.DateTimeFormat('ja-JP', {
  // year: 'numeric',
  month: 'long',
  // day: 'numeric',
});
console.log(dateTimeFormat.format(new Date(2020, 6, 3)));
// 7月
```

<font color="MediumVioletRed">**オプションで年、月、日いずれかのフォーマットを1つでも定義した場合は、定義した項目しか戻しません。**</font>
なので、この方法で年月日を表示したい場合はyearとdayは省略できません。
逆に、オプションに何も指定しなければ前章の通り「yyyy/MM/dd」を返してくれます。


## 📅 "和暦+年月日" (例: 令和2年7月3日)

西暦(2020年)ではなく和暦(令和2年)にしてみます。

### コードと解説

前章のIntl.DateTimeFormatの引数に`era: 'long'`を追加するだけです。

```Javascript

const dateTimeFormat = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
  era: 'long',
  year: 'numeric',
  month: 'long',
  day: '2-digit',
});
console.log(dateTimeFormat.format(new Date(2020, 6, 3)));
// 令和2年7月03日
```

### year,month,dayを省略してみる

「令和」だけ表示されるのかな・・・と思ったら年月日も付いてきました。

```javascript
const dateTimeFormat = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
  era: 'long',
});
console.log(dateTimeFormat.format(new Date(2020, 6, 3)));
// 令和2/7/3
```

### long以外のフォーマットにしてみる

eraも複数のフォーマットを持っています。
`long`と`short`は「令和」になりますが、<font color="MediumVioletRed">**`narrow`だと頭文字(`R`)**</font>になるので注意してください。

```Javascript
const dateTimeFormat = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
  era: 'narrow',
});
console.log(dateTimeFormat.format(new Date(2020, 6, 3)));
// R2/7/3
```


|　　    |ja-JP        |
|-------|-------------|
|long   |令和2年7月3日  |
|short  |令和2年7月3日  |
|narrow |<font color="MediumVioletRed">R2年7月3日</font>    |



# 参考
- Intl.DateTimeFormatのオプション一覧
    - [MDN　-Intl.DateTimeFormat-](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)
- 日付操作の実例集
    - [Stack Overflow -How to format a JavaScript date-](https://stackoverflow.com/questions/3552461/how-to-format-a-javascript-date/33131823)

# まとめ

いろいろ検証しているうちに、JSの日付操作方法はIntl.DateTimeFormatのオプションを使えば大体どんな形式にもできることがわかってきました。
同時に、噂通りJSのDateTimeには落とし穴が多いこともよくわかりました。
タイムゾーンについてまだよくわかってないので、いつかまた勉強して記事書いてみようと思います。