Posted at

moment.jsで開始日~終了日のカレンダー配列を作る

More than 1 year has passed since last update.


やりたかったこと

開始日と終了日とを指定して、

各要素が 開始日 <= 要素 <= 終了日 となるようなカレンダー的な配列を作る。


最初に書いたコード

import moment from 'moment';

const startDate = moment('2020-07-24T15:00:00Z');
const endDate = moment('2020-08-09T08:00:00Z');
const days = moment.duration(endDate - startDate).days() + 1;

const dates = [...Array(days).keys()].map(v => startDate.add(v, 'days'));
console.log(dates);

このコードは2箇所ダメなところがある。

1. moment().add(Number, Object) は、返り値に計算結果を返すだけでなく、自身の日時も変更する

2. 時刻に関わらず開始日と終了日でその間の日数を計算したいが、開始日の時刻>終了日の時刻のとき、日数が1日少なくなる

1については公式ドキュメントにきちんと以下のように記述してあった。


Mutates the original moment by adding time.

https://momentjs.com/docs/#/manipulating/add/


対応策として、moment().clone() を使ってオブジェクトをコピーし、startDate の日時が変わらないようにする。

2については時刻を切り捨てることで対処する。

moment().startOf('day') を使うと、時刻を00:00:00にすることが出来るのでこれを利用する。

https://momentjs.com/docs/#/manipulating/start-of/


解決したコード

import moment from 'moment';

const startDate = moment('2020-07-24T15:00:00Z').startOf('day');
const endDate = moment('2020-08-09T08:00:00Z').startOf('day');
const days = moment.duration(endDate - startDate).days() + 1;

const dates = [...Array(days).keys()].map(v => startDate.clone().add(v, 'days'));
console.log(dates);


実行結果

[ moment("2020-07-24T00:00:00.000"),

moment("2020-07-25T00:00:00.000"),
moment("2020-07-26T00:00:00.000"),
moment("2020-07-27T00:00:00.000"),
moment("2020-07-28T00:00:00.000"),
moment("2020-07-29T00:00:00.000"),
moment("2020-07-30T00:00:00.000"),
moment("2020-07-31T00:00:00.000"),
moment("2020-08-01T00:00:00.000"),
moment("2020-08-02T00:00:00.000"),
moment("2020-08-03T00:00:00.000"),
moment("2020-08-04T00:00:00.000"),
moment("2020-08-05T00:00:00.000"),
moment("2020-08-06T00:00:00.000"),
moment("2020-08-07T00:00:00.000"),
moment("2020-08-08T00:00:00.000"),
moment("2020-08-09T00:00:00.000") ]

無事に所望の配列を得ることが出来ました。

ちなみに、2020/7/24~8/9は東京オリンピックの開催日です。