生年月日と出生地から命式や運勢を確認できる「四季の命式」を作りました。 出生時刻がわからない場合にも使える、ブラウザ内で計算する四柱推命サイトです。

作ろうと思ったきっかけ

最近タロット占いを受けたことがきっかけでした。 占いには統計的な面もあったなと思い、四柱推命なら蓄積された情報を使って、デジタルでもある程度占いを再現できるのではないかと考えました。

四柱推命の規則をプログラムにし、生年月日などの入力から命式と鑑定文を返すサイトとして作ったのが「四季の命式」です。

TypeScriptとViteでブラウザ内に計算を収める

画面はHTMLとCSS、入力の検証や命式の計算はTypeScriptで書いています。 TypeScriptから画面の要素を直接操作する構成です。 Viteで配信用ファイルを作り、GitHub Pagesへ配置しています。

担当使用している技術や仕組み
入力画面と結果表示HTML、CSS、TypeScript
開発用サーバーと配信用ファイルの生成Vite
節入り時刻の一覧の生成lunar-javascript
出生地の経度Geoloniaの住所情報をもとに作成した市区町村の一覧
自動検証Node.jsのテスト機能、tsx
公開GitHub Actions、GitHub Pages
共有用画像の生成SVG、sharp

生年月日、出生時刻、出生地、性別はブラウザ内の計算に使います。 入力内容を外部APIへ送ったり、URLやブラウザの保存領域へ残したりする実装はありません。

鑑定文も外部へ問い合わせて生成する仕組みではありません。 日干と通変星に応じて、あらかじめ用意した性格、仕事、恋愛などの文章を組み合わせています。 文章を確認したい場合は、ソースコードの src/content.ts を読めます。

暦の境界と出生時刻の扱い

四柱推命の計算では、年や月が切り替わる境界を決める必要があります。 「四季の命式」では年柱を立春、月柱を各節入りの瞬間で切り替えています。 日柱の切り替えは出生地の地方平均太陽時の午前0時です。

節入り時刻は lunar-javascript から1899〜2101年分を生成し、JSONファイルとして同梱しています。 ライブラリが返す時刻をUTC+8として読み取り、UTCの時刻へ変換して収録しています。 サイトの閲覧時や公開用のビルド時に、外部から暦を取得する構成ではありません。

出生地には国内1,892市区町村の代表経度を収録しています。 町丁目の経度の平均を使い、未収録の市区町村と浜松市の区再編分は国土地理院の代表地点で補っています。 市区町村の代表経度なので、出生施設の経度とは差が生じます。

時刻の補正は、東経135度との差1度につき4分です。 1948〜1951年の日本の夏時間も考慮しています。 節入りは全地点で共通の瞬間として扱い、経度補正で動かさない実装です。

出生時刻が不明な場合は正午を仮の基準とし、時柱を省いて表示します。 出生日の最初と最後、節入り前後も調べ、時刻によって変わる命式の候補と大運の開始年齢の幅を表示しています。 時刻不明時の鑑定文が確定結果ではないことも画面で案内しています。

なお、鑑定には格局、用神、身強身弱、合冲の総合判断を含めていません。 五行の数も強弱や吉凶の点数として扱わず、計算規則と鑑定の範囲をサイトに掲載しています。

構成を選んだ理由

構成を選ぶときに重視したのは、軽量でわかりやすく、無料で公開できることでした。 TypeScriptは自分が理解できる言語であることも採用の理由です。

命式の計算をブラウザ内に収め、Viteで作った配信用ファイルをGitHub Pagesへ置く構成を採用しました。

公開を支える自動検証

GitHub Actionsは main ブランチへのプッシュをきっかけに動きます。 pnpmで依存ライブラリをインストールし、テスト、型検査、Viteのビルドを経て、生成した dist/ をGitHub Pagesへ配置する構成です。

命式計算のテストには、立春、小寒、午前0時、23時台、経度補正による日付変更、夏時間、出生時刻不明時の候補を含めています。 テストは24件あり、pnpm test で実行できます。

日柱には暦ライブラリの参照値と照合するテストもあります。 ただし、節入り時刻の全収録年を公的な暦表と照合したわけではありません。

文字サイズとデザインの両立が難しかった

制作で難しかったのは、スマホとPCで文字を読みやすくしながらデザインを保つことでした。 一度は画面全体の文字サイズを変更しましたが、PC向けの指定を幅601px以上に限定し、スマホのレイアウトを戻しました。 その後、スマホの構成を保ちながら鑑定本文を14pxへ調整しました。 PCの鑑定本文は1.0625remで指定しています。 ブラウザの基準文字サイズが16pxなら17pxに相当します。

おしゃれなサイトは、文字サイズとデザインの関係までよく考えて作られているのだと感じました。 デザイナーのありがたさを改めて感じた部分です。

印刷したい理由からレイアウトを練り直した

印刷では、なぜ印刷したいのか、紙でどのような情報が欲しいのかに着目して練り直しました。 鑑定結果がA4縦一枚に収まるよう、命式や性格などを左側、年運や大運を右側にまとめています。 注意文を含めた紙面の高さを測り、必要に応じて縮尺を調整する作りです。 出生時刻不明などの注意文も紙面に残しています。

画面表示と印刷表示は別のファイルに分けています。 画面の文字サイズを調整するCSSは、A4印刷へ適用しない構成です。

印刷したい理由から考え直した結果、良い印刷ページになったと思います。

共有時の紹介画像も用意した

Slackなどでサイトを共有するときに表示される紹介画像も用意しました。 HTMLにOGPとTwitter Cardの設定を加え、幅1200px、高さ630pxのPNGを同梱しています。 画像のURLには絶対URLを指定しています。

画像はサイトの草花のSVGを使い、sharpで生成する作りです。 生成済みのPNGをリポジトリへ置いているので、GitHub Actionsでの公開時に画像を作る必要はありません。