はじめに
こんばんは。
生年月日の入力フォームを作成する要件がありまして、最初はデザイン的に適したdate pickerライブラリを使おうと思っていました。
ただ、提案したどのライブラリも 入力側がミスしすそう、または操作しづらそうという意見が多く、極力シンプルに 年・月・日がすべて分かれたプルダウンメニューを作るという形になりました。
今まで生年月日入力は date pickerとかに任せちゃってたので、作ろうとしたちょっとだけハマりました。
めちゃめちゃ簡単な実装なんですが、いつものように備忘録しときます。
本題
年の実装
1980年 〜 今年までの年の情報を作るスクリプトです。
0から始まるので+1して作ってます。
import { format } from "date-fns"; export const selectYears = (): string[] => { const START_YEAR = 1980 const currentYear = parseInt(format(new Date(), 'yyyy')) return Array.from({ length: currentYear - START_YEAR + 1 }, (_, i) => (START_YEAR + i).toString()) }
月の実装
月の実装です。 1〜12までループして、0埋めして数字を作ってます。
export const selectMonths = (): string[] => { return [...Array(12).keys()].map(i => (i + 1).toString().padStart(2, '0')) }
日の実装
日の実装です。
ここは年と月の情報から日が存在するか確認しないとだめです。
date-fns
の isValid()
を使えばいいのかと思ったのですが、 2023-02-31
とかでも true
を返してくるので使えません。
色々調べてたら以下の方法が良さそうでした。
参考にしながら対応したのが以下です。
29日以降だけチェックくして、作ろうとしている年月日とズレなければそのまま作成されるという方法にしました。
export const selectDays = (year: string, month: string): string[] => { const result: string[] = []; [...Array(31).keys()].map((i: number) => { const day = i + 1 const formatDay = day.toString().padStart(2, '0') if (day >= 29) { const date = `${year}-${month}-${formatDay}` const formatDate = format(new Date(date), 'yyyy-MM-dd'); if (date !== formatDate) { return } } result.push(formatDay) }) return result }
終わりに
楽勝楽勝と思ったら、 isValid()
というめちゃめちゃぽいメソッドの動きでちょいハマりました。
現場からは以上です。