かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Day.js 日付が期間内かどうか判定したい

day.js の isBetween プラグインを使う

IsBetween
IsBetween adds .isBetween() API to returns a boolean indicating if a date is between two other dates.
cf. IsBetween · Day.js

npm i datjs で既にインストールされているので、別途プラグインを import して dayjs.extend するだけで使うことができる。

import dayjs from 'dayjs';
import isBetween from 'dayjs/plugin/isBetween';

dayjs.extend(isBetween); // これがないとエラーになる

// dayjs(対象日).isBetween(期間開始日, 終了日)`  
dayjs('2021-11-07').isBetween('2021-01-01', '2021-12-31'); // => true

dayjs.isBetween はデフォルトでは開始日・終了日は範囲にならない

import dayjs from 'dayjs';
import isBetween from 'dayjs/plugin/isBetween';
dayjs.extend(isBetween);

dayjs('2021-01-01').isBetween('2021-01-01', '2021-12-31'); // => false
dayjs('2021-12-31').isBetween('2021-01-01', '2021-12-31'); // => false

dayjs(対象日).isBetween(開始日, 終了日)開始日 < 対象日 < 終了日 な時 true となる。

第4引数の記号で開始日、終了日を含めるかどうか変更できる。

第4引数に [, ], (, ) を使って開始日・終了日を含めるかどうか指定できる

含める 含めない
開始日 [ (
終了日 ] )

isBetween('2021-01-01', '2021-12-31', null, '[]') → 対象日が2021年中なら true
第4引数は記号なので [], () のようなセットで書く必要はなく、開始日だけ含まない・終了日だけ含まないのような書き方もできる。

dayjs('2021-01-01').isBetween('2021-01-01', '2021-12-31', null, '[]');  // => true
dayjs('2021-12-31').isBetween('2021-01-01', '2021-12-31', null, '[]');  // => true

// 開始日を含まない '(]'
dayjs('2021-01-01').isBetween('2021-01-01', '2021-12-31', null, '(]');  // => false
// 終了日を含まない '[)'
dayjs('2021-12-31').isBetween('2021-01-01', '2021-12-31', null, '[)');  // => false

開始日・終了日が null, undefined の時

TypeScript で dayjs.isBetween の型を見ていると開始日と終了日の型は次のようになっていました。

type ConfigType = string | number | Date | Dayjs | null | undefined;

declare module 'dayjs' {
  interface Dayjs {
    isBetween(a: ConfigType, b: ConfigType, c?: OpUnitType | null, d?: '()' | '[]' | '[)' | '(]'): boolean
  }
}

開始日・終了日は nullundefined を含むことができるようです。その場合範囲として成り立たないのでどう判定されるのか気になるところです。

null と undefined で挙動が異なる

null の時 デフォルトでは範囲外 false になり 第4引数で含める指定があれば範囲内 true になる

const d = dayjs('2021-11-08');

d.isBetween(null, '2021-12-31');
// => false
d.isBetween(null, '2021-12-31', null, '[]');
// => true
d.isBetween('2021-01-01', null));
// => false
d.isBetween('2021-01-01', null, null, '[]');
// => true
d.isBetween(null, null);
// => false
d.isBetween(null, null, null, '[]');
// => true

第4引数が [] なら null, は無限のような意味合いで扱われる

undefined が開始日の時は終了未満として扱われ、終了日の時は全て範囲外となる

const d = dayjs('2021-11-08');

d.isBetween(undefined, '2021-12-31');
// => true
d.isBetween(undefined, '2021-12-31', null, '[]');
// => true
d.isBetween(undefined, '2021-01-01');
// => false
d.isBetween('2021-01-01', undefined);
// => false
d.isBetween('2021-01-01', undefined, null, '[]');
// => false
d.isBetween(undefined, undefined);
// => false
d.isBetween(undefined, undefined, null, '[]');
// => false

範囲が undefined の時は 0 の様な挙動になる

所管

dayjs 便利。date-fns も気になるところだけど、dayjs の方が軽量っぽい?
isBetween の範囲が nullundefined で挙動が異なるのは罠だな〜と思いました。それと第三引数説明に To useyeargranularity pass the third parameter とあるけどよく分かってない。月日は無視して年だけでしか判定しないとか?必要になったらまた調べようと思いました。

モダンなフロントエンドでガリガリできるお仕事がしたい…


[参考]