Moment.jsは非推奨だが安易にdate-fnsに変えるな。date-fnsのisValidではparseを活用せよ
問題点
面倒な日付処理をやってくれるMoment.jsですが、mutable設計が混乱を招くとして、今後は非推奨と発表しています。immutableに変更する作業も実施しないとのこと。
https://momentjs.com/guides/#/lib-concepts/mutability/
The moment object in Moment.js is mutable. This means that operations like add, subtract, or set change the original moment object.
var a = moment('2016-01-01');
var b = a.add(1, 'week');
a.format();
"2016-01-08T00:00:00-06:00" // aも変更されてしまう。a.clone().add(1, 'week');とする必要あり
代替案として date-fns
にする人が多いのですが、
結論から言うと 「安易にdate-fnsに変えるな」 です。そちらにも罠があるから。
Moment.jsにもdate-fnsにも isValid
がありますが、仕様が異なるので注意が必要です。
実在しない日付、例えば2022年2月29日を引数に与えるとどうなるでしょう?
Moment.jsのisValidでは false
になりますが、date-fnsのisValidは true
になります。
- Moment.js
moment('2022-13-01','YYYY-MM-DD',true).isValid() //false
moment('2022-01-32','YYYY-MM-DD',true).isValid() //false
moment('2022-02-29','YYYY-MM-DD',true).isValid() //false
moment('2022-04-31','YYYY-MM-DD',true).isValid() //false
- date-fns
各月31日までなら、実在しない日付でも true
を返してしまう。
2月や閏年、30日までの月の扱いには注意が必要。
dateFns.isValid(new Date('2022-13-01')) //false
dateFns.isValid(new Date('2022-01-32')) //false
dateFns.isValid(new Date('2022-02-29')) //true
dateFns.isValid(new Date('2022-04-31')) //true
対策1
32日や13月は false
を返すので、Moment.jsの isValid と同じ使い方をしたいのであれば、date-fns の次の特徴を利用します。
- 2022-02-29(閏年以外の2/29)は、2022-03-01として処理されてしまう。
- 31日までは無条件にtrue。
- 実在しない日付は自動で差分が加算される。
だから、次のようにします。
※コメントをいただきまして、修正しました
-
date-fns
のバージョンは1.28.5
です。
const isValidDateString = (str, format) => {
const formatString = dateFns.format(
dateFns.parse(str, format),
format
)
return formatString === str;
}
isValidDateString('2022-02-27', 'YYYY-MM-DD') // true
isValidDateString('2022-02-28', 'YYYY-MM-DD') // true
isValidDateString('2022-02-29', 'YYYY-MM-DD') // false
isValidDateString('2022-02-30', 'YYYY-MM-DD') // false
isValidDateString('2022-02-31', 'YYYY-MM-DD') // false
isValidDateString('2022-02-32', 'YYYY-MM-DD') // false
isValidDateString('2022-02-33', 'YYYY-MM-DD') // false
- CodePenで試した結果
-
date-fns
のバージョンは1.28.5
です。
-
これでdate-fnsを使用しながら、Moment.jsのisValidと同じ結果を得られます。
対策2
またはこちら。
※コメントをいただきました
- CodePenで試した結果
-
date-fns
のバージョンは2.28.0
です。
-
これでdate-fnsを使用しながら、Moment.jsのisValidと同じ結果を得られます。
その他の候補
date-fns以外の候補はこちらです。
全て試してください。今のプロジェクトに合うものを選ぶと良いと思います。
Author And Source
この問題について(Moment.jsは非推奨だが安易にdate-fnsに変えるな。date-fnsのisValidではparseを活用せよ), 我々は、より多くの情報をここで見つけました https://zenn.dev/hooyan/articles/c11a9171b60a89著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol