Reactで和暦と西暦の表示切り替えをする関数を書いた
すでに令和も4年。平成まではギリ西暦⇔和暦の変換ができていたけれど、令和になってからは覚えるのもめんどくさくなり、ググらないと今は令和何年なのかもわからないという人もいるのでは?
前職は病院の事務員だったので、様々な行政の書類や日々の業務の中で和暦にふれる機会が多かったのですが、、IT業界へ転職し、書類を処理したり患者様の対応をすることもないので、わざわざ和暦で年を数えることもなくなりました。
ただし、役所や医療機関など行政書類を扱ったり、保険情報などを扱う場合は和暦が標準になっているケースが多く、そういった業務アプリの開発には和暦対応も要求されると思っています。
今回は、和暦⇔西暦で相互変換する関数を実装してみました。
やりたいこと
やりたいことをざっと書き出してみたのが以下
-
和暦⇔西暦の切り替えボタンにより、表示形式の切り替えができる
-
ページ内に存在する日付データの形式がまとめて切り替わる
-
あくまで表示を切り替えるだけで元データには影響を与えない
実装イメージ
-
親コンポーネント(Page)でboolean型の表示形式の状態を持つ
-
親コンポーネント(Page)でstring型の日付データを持つ。
-
日付データは必須項目である
-
関数は日付情報と表示形式の状態を引数として受け取る
-
表示形式の状態によって、和暦と西暦の表示切り替えをする
結論
まずは結論として、Codesandboxを御覧ください。
https://codesandbox.io/embed/date-he-li-xi-li-og86ng?fontsize=14&hidenavigation=1&theme=dark
表示切り替えのボタンをクリックすると、BirthDayの一覧すべての項目に対し、表示形式の切り替えができます。
メインとなるのは utils.ts
に定義している関数 conversionBetweenJpAndAd
です。
dummy.ts
は単なるダミーデータなので割愛。
実装方法
utils.ts
import { parse } from "date-fns";
import ja from "date-fns/locale/ja";
export const conversionBetweenJpAndAd = (date: string, jpFormat: boolean) => {
if (jpFormat) {
const jp = new Intl.DateTimeFormat("ja-JP-u-ca-japanese", {
era: "long",
year: "numeric",
month: "long",
day: "numeric"
}).format(
new Date(parse(date, "yyyy年M月d日", new Date(), { locale: ja }))
);
return jp;
}
return date;
};
日付ライブラリは date-fnsを使いました。
date-fns
は日付データのパースに使用している程度で、本命は Intl.DateTimeFormat
です。
Intl
は国際化APIの名前空間で、数値フォーマットや表示名の翻訳など国ごとの表記に変換するAPIが用意されています。
その中の一つが今回使用したIntl.DateTimeFormat()
で、言語に依存した日時のフォーマットができるAPIです。
Intl オブジェクトは、 ECMAScript の国際化 API の名前空間で、言語に依存した文字列の比較、数値の書式化と、日付の書式化を提供します。 Intl オブジェクトは、いくつかのコンストラクターに加え、国際化コンストラクターや他の言語に関する関数に共通する機能へのアクセスを提供します。
-
第一引数 ... locale(日本であればja-JP-u-ca-japanese)
-
第二引数 ... options(年、月、日の表記形式やタイムゾーンの表記形式など)
第二引数にera
を指定すると、元号を付与して表示させることができます。
今回はstring
形式の日付データを扱うため、フォーマットする際は、string
形式の日付データをdate-fns
でDate
型にパースして渡してあげる必要があります。
あとは、表示形式の状態を定義したjpFormat
を受け取って条件分岐させ、jpFormat
でない場合は日付データをそのままreturnするようにしました。
親コンポーネントApp.tsx
親コンポーネント側では、jpFormat
として表示形式の状態をboolean
型で定義し、Buttonをクリックした際にstateを更新するようにします。これによって、和暦⇔西暦の切り替えを実現させます。
users
データを表示させる際、conversionBetweenJpAndAd
を呼び出してuser.birthDate
とjpFormat
を引数として渡してあげれば完成です。
App.tsx
import { useState, useCallback } from "react";
import { conversionBetweenJpAndAd } from "./utils";
import { users } from "./dummy";
import "./styles.css";
export default function App() {
const [jpFormat, setJpFormat] = useState<boolean>(false);
const onChangeDateViewType = useCallback(() => {
setJpFormat((prevState) => !prevState);
}, []);
return (
<div className="App">
<div className="button">
<button onClick={onChangeDateViewType} type="button">
{jpFormat ? "西暦表示" : "和暦表示"}
</button>
</div>
<ul className="list">
<li className="listHead">
<span>ID</span>
<span>UserName</span>
<span>BirthDay</span>
</li>
{users.map((user) => (
<li key={user.id}>
<span>{user.id}</span>
<span>{user.name}</span>
<span>{conversionBetweenJpAndAd(user.birthDate, jpFormat)}</span>
</li>
))}
</ul>
</div>
);
}
所感
和暦って、正規表現で処理マッチさせて処理を書いていくイメージだったのですが、Intl.DateTimeFormat
とdate-fns
を使うことで簡単に実装できました。
ググっても和暦⇔西暦の切り替え機能を作っている人はあまりいなく、こういった実装方法で問題がないのかは不安ではありますが、イメージどおりの動きをしてくれていると思います。
「平成6年って、西暦何年だっけ?」みたいなケースにサクッと切り替えられるのは個人的には嬉しい。使える機会があれば業務アプリの開発で使ってみようと思います。