もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

jsで日付入力フォームのために年・月・日の値を作成したい

はじめに

こんばんは。

生年月日の入力フォームを作成する要件がありまして、最初はデザイン的に適した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-fnsisValid() を使えばいいのかと思ったのですが、 2023-02-31 とかでも true を返してくるので使えません。

色々調べてたら以下の方法が良さそうでした。

chaika.hatenablog.com

参考にしながら対応したのが以下です。

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() というめちゃめちゃぽいメソッドの動きでちょいハマりました。

現場からは以上です。