Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

【JavaScript】外部ライブラリに頼らないdateフォーマット【Intl.DateTimeFormat】

この記事について

new Intl.DateTimeFormatを使えば外部ライブラリを使わずに、ある程度自由に日付の書式を設定できます。
また、formatToParts()を使えば設定した値を項目ごとに(例えば秒だけ)取り出すことができて便利です。

この記事ではDateオブジェクト(2019-12-31T21:05:00.000Z)から0パディング時間(06時05分)を取得する方法を例に、上記関数の使い方を紹介します。
何らかの事情で、moment.jsなどのライブラリを使えない方の助けになれれば嬉しいです。

結論

Dateオブジェクトから 06時05分 という出力を得ます。

const time = new Date(2020, 0, 1, 6, 5)
const dateTimeFormat = new Intl.DateTimeFormat('jp', { hour: '2-digit', minute: '2-digit'});
const [{ value: hour }, , { value: minute }] = dateTimeFormat.formatToParts(time);
console.log(`${hour}${minute}分`); // → 06時05分

解説

上記のコードを一行一行解説します。

1行目:

const time = new Date(2020, 0, 1, 6, 5)

  • new Dateを使って、Dateオブジェクトを作成します。(例: 2020年1月1日 6時5分)
  • new Dateを使う時、月は1月なら0、2月なら1というように、番号が一つずれます。(詳細はこちら

2行目:

const dateTimeFormat = new Intl.DateTimeFormat('jp', { hour: '2-digit', minute: '2-digit' });

  • new Intl.DateTimeFormatを使ってフォーマッタを定義します。(詳細はこちら)
  • 引数の { hour: '2-digit', minute: '2-digit' } はoptionsと呼ばれます。
    このoptionsで時間と分の書式を2桁に設定します。

  • 例えば日付を出力したければ、{ month: 'short', day: '2-digit' } と定義します。(詳細はこちら)

3行目:

const [{ value: hour }, , { value: minute }] = dateTimeFormat.formatToParts(time);

  • DateTimeFormat.prototype.formatToParts()を使って、時間と分を別々に取得しています。
  • この中身をconsole.logで確認すると以下のようになっています。
console.log(dateTimeFormat.formatToParts(time));

// 出力結果
[
  { type: 'hour', value: '06' },
  { type: 'literal', value: ':' },
  { type: 'minute', value: '05' }
]

このように、2行目で設定したhourminuteはオブジェクトに格納されているので、各値を個々に取り出すことが可能です。(詳細はこちら)

  • ちなみに変数の代入には分割代入を使用しています。
     {オブジェクトのキー名 : 任意の変数名} = オブジェクトとすることで、該当キーの値がその変数名で定義されます。(詳細はこちら)

  • オブジェクトで個々に取り出す必要がない場合はformat()を使って以下のように書くこともできます。

const time = new Date(2020, 0, 1, 6, 5);
const dateTimeFormat = new Intl.DateTimeFormat('jp', { hour: '2-digit', minute: '2-digit' });
console.log(dateTimeFormat.format(time));
// 06:05

4行目:

console.log(`${hour}時${minute}分`)

  • テンプレートリテラルを使って、値と'時''分'を結合し、06時05分を出力しています。

落とし穴

1. minuteは0サプレスされない

0パディングとは逆の0サプレスをしたい場合、optionsで('jp', { hour: 'numeric', minute: 'numeric' })を設定すれば良さそうですが、minuteは0サプレスされません。
理由は不明。調べましたが、できないことをメモしている記事しか見つけられませんでした。

リファレンス メモ new Intl.DateTimeFormat()【コンストラクタ】

2. localeによって書式が設定されないことがある

Intl.DateTimeFormatのoptionsで{ weekday: 'long' })を指定すると、MDNの説明によればWednesdayが出力されるはずです。
しかし以下のコードでは、Wedと表示されてしまいます。

const time = new Date(2020, 0, 1, 6, 5);
const dateTimeFormat = new Intl.DateTimeFormat('jp', { weekday: 'long' });
console.log(dateTimeFormat.format(time))
// Wed

これはIntl.DateTimeFormatのlocaleがjpになっているのが原因です。
このようにlocaleによっては書式設定が適用されないこともあるので注意が必要です。
今回の場合は('en', { weekday: 'long' })とすれば期待通りになります。

const time = new Date(2020, 0, 1, 6, 5);
const dateTimeFormat = new Intl.DateTimeFormat('en', { weekday: 'long' }); // jp → enに修正
console.log(dateTimeFormat.format(time))
// Wednesday

 まとめ

optionsとformatToParts()を使えば自由に日時を取得できるので便利です。
日付の扱いや日本語表記についても、いつかまとめて記事にしておきたいです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
1
Help us understand the problem. What are the problem?