Skip to content

日付項目の和暦・多暦表示 ​

第1版作成 最終更新 (日本時間)
確認バージョン1.5.1.01.5.8.1

日付項目を和暦(令和 8 年 3 月 6 日など)で表示・入力できるようにする設計メモです。本体の標準機能ではありません。 保存する値(DB・API)は西暦のまま、画面の表示と入力だけを変えます。年月・年だけの入力モードや一覧の表示形式の拡張は 日付項目の入力モードと表示形式の拡張 にあります。調査は 1.5.1.0 で行い、前提にした部分を 1.5.8.1 のソースで確かめています。

前提にした現行実装 ​

date-field の作り ​

2 世代目のテーマ(UseOldDatepicker が false)では、日付項目は <date-field> カスタム要素で、中の input に flatpickr 4.6.13 を付けています(datefield.ts)。

項目1.5.8.1 の実装
Shadow DOM使う(mode: 'open')。ただし Shadow DOM の中にあるのは枠と「現在日時」ボタンだけで、input は <slot> に入る通常の子要素(datefield.ts#L18-L26、#L178-L186)
flatpickr のインスタンスflatpickr(this.inputElm, …) で作る。flatpickr の決まりで input._flatpickr から外部のスクリプトでも取れる
カレンダーの置き場所appendTo でダイアログの中、なければ document.body
dateFormatinput の data-format(s は S に置き換え)。無ければ Y/m/d H:i(datefield.ts#L44-L46)
「現在日時」ボタンmoment で input.value を書き、setDate(value, false) でピッカーに反映する(datefield.ts#L116-L127)
送信される値input の値そのもの

date-field は Shadow DOM を使いますが、input は Shadow DOM の中ではなく通常の子要素で、this.querySelector('input') で取っています。そのため外部のスクリプトからも input._flatpickr に触れます。既存のレシピでも input._flatpickr を使って flatpickr を付け直しています(入力支援)。

言語ごとの書式 ​

data-format は言語ごとの表示文字列 YmdDatePickerFormat などから決まります(YmdDatePickerFormat.json)。

言語flatpickr の書式
既定(英語)m/d/Y
ja・zh・es・vnY/m/d
deY.m.d
koY.m.d.

西暦以外の書式はありません。

暦の変換 ​

Intl.DateTimeFormat(推奨) ​

ブラウザ標準の Intl.DateTimeFormat は、ロケールに -u-ca-japanese を付けると和暦で書式化します。元号のデータは CLDR に従うので、新しい元号にはブラウザの更新で追従します。

js
function toWareki(date) {
  var parts = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
    era: 'long', year: 'numeric', month: 'numeric', day: 'numeric'
  }).formatToParts(date);
  var get = function (type) {
    var p = parts.find(function (x) { return x.type === type; });
    return p ? p.value : '';
  };
  return get('era') + get('year') + '年' + get('month') + '月' + get('day') + '日';
  // 例: 令和8年3月6日
}

同じ方法で、ほかの暦にも書式化できます。

暦ロケールの例表示の例
和暦ja-JP-u-ca-japanese令和8年3月6日
仏暦th-TH-u-ca-buddhist2569年3月6日
中華民国暦zh-TW-u-ca-roc民國115年3月6日
ヒジュラ暦ar-SA-u-ca-islamic6 Rabiʻ II 1447 AH
ペルシャ暦fa-IR-u-ca-persian1404/12/15
ヘブライ暦he-IL-u-ca-hebrew6 Adar 5786

元号の表を持つ方法 ​

元号の開始日の表を自前で持つ方法もあります。テストはしやすくなりますが、新しい元号ができたら表を直す必要があります。Intl が使えない環境の予備として使います。

和暦から西暦への変換 ​

Intl.DateTimeFormat には逆の変換(文字列 → 日付)がありません。入力を受け付けるなら、正規表現で自前で解析します。

入力の形難しさ例
完全な形低令和8年3月6日
略した形中R8.3.6
元年中令和元年5月1日
時刻付き中令和8年3月6日 14:30
元号の切り替わり高平成31年4月30日
js
var ERA_OFFSETS = { 令和: 2018, 平成: 1988, 昭和: 1925, 大正: 1911, 明治: 1867 };

function fromWareki(str) {
  var m = str.match(/(令和|平成|昭和|大正|明治)(\d+|元)年(\d+)月(\d+)日/);
  if (!m) return null;
  var year = ERA_OFFSETS[m[1]] + (m[2] === '元' ? 1 : Number(m[2]));
  return new Date(year, Number(m[3]) - 1, Number(m[4]));
}

送信する値を西暦のままにする ​

flatpickr の formatDate を差し替えると、ピッカーが input に書く値そのものが変わります。input の値はそのまま送信されるので、和暦の文字列がサーバーに送られて日付として読めなくなります。表示と送信を分けるには altInput を使います。

オプション役割
dateFormat元の input(送信される値)の書式。西暦のまま
altInput: true表示用の input を別に作り、元の input を隠す
altFormat表示用の input の書式
formatDate(date, format)書式化の関数。format が altFormat のときだけ和暦にする
parseDate(str, format)入力の解析。和暦として読めたらその日付、読めなければ flatpickr の既定の解析

図を読み込み中…

実装の方法 ​

A. 拡張スクリプトで flatpickr を付け直す ​

本体を改修せずに、date-field の input._flatpickr を destroy() して、altInput などを付けたオプションで作り直します。年月モードのレシピ(入力支援)と同じやり方です。

  • 送信する値は西暦の dateFormat のままにし、altFormat 側だけ和暦にします。
  • 「現在日時」ボタンは元の input に西暦を書いて setDate を呼ぶので、altInput を使っていれば表示用の欄にも和暦で反映されます。
  • date-field は後から追加されることがある(ダイアログで開いた編集画面など)ので、MutationObserver で新しい date-field にも適用します。

B. date-field に暦の設定を持たせる(本体改修) ​

datefield.ts に暦の種類(gregorian・japanese・buddhist・roc など)を持たせ、西暦以外なら上の altInput・formatDate・parseDate を付けます。

ts
private initDatePicker() {
    const calendar = this.inputElm.dataset.calendar ?? 'gregorian';
    const fpOptions: Options = {
        dateFormat: this.dateFormat, // 送信は西暦のまま
        ...(calendar !== 'gregorian'
            ? {
                  altInput: true,
                  altFormat: 'CAL', // 表示用の目印(formatDate で差し替える)
                  formatDate: (date: Date, format: string) =>
                      format === 'CAL'
                          ? this.formatByCalendar(date, calendar)
                          : flatpickr.formatDate(date, format),
                  parseDate: (str: string, format: string) =>
                      this.parseByCalendar(str, calendar) ?? flatpickr.parseDate(str, format)
              }
            : {}),
        // …既存のオプション
    };
    this.dataPicker = flatpickr(this.inputElm, fpOptions);
}

サーバー側は、暦の種類を項目の設定に持たせて data-calendar 属性で出すだけで済みます。

対象変更
Column.cs暦の種類のプロパティを足す
HtmlControls.csdate-field の input に data-calendar を出す
SiteSettings(保存)既定値と違うときだけ保存される仕組みに乗せる
DB変更なし(値は西暦)
Displays/*.json変更なし

日付ピッカー以外の表示 ​

表示箇所現行和暦にするには
編集画面の入力欄flatpickr の dateFormat上の altInput 方式
一覧画面サーバー(C#)で GridFormat の書式で文字列にするC# で和暦のカレンダーを使って書式化する
API の応答西暦変更不要
カレンダー(FullCalendar)西暦別に対応が要る
CSV エクスポートサーバーで書式化出力の書式の設定を足す

C# では JapaneseCalendar を使うと和暦で書式化できます。

csharp
using System.Globalization;

var culture = new CultureInfo("ja-JP");
culture.DateTimeFormat.Calendar = new JapaneseCalendar();
var text = date.ToString("ggyy年MM月dd日", culture); // 令和08年03月06日

関連ページ ​

変更履歴

第1版Markdown の描画の仕組み・ショートカットキー・アイコン・公式マニュアルに無い $p 関数の解説と、Markdown 拡張・画像形式・ファビコン・テーマ・和暦などの改修・設計メモを追加