江戸時代の元号をレジストリィに足したが.NETのJapaneseCalendar Classの下限値は西暦1868年9月8日だったので和暦変換できなかった話
タイトルが全ての出落ち記事です
何がやりたかったのか
令和のレジストリィがWindows Updateで提供されたりされなかったり、一緒に文字幅が変わる修正が提供されてGUIがぶっ壊れたりしている今日この頃、皆様いかがお過ごしでしょうか
自分は思い付きでトラブルを増やすべく、江戸時代の元号をWindows 10のレジストリィに追加してどうなるか試してみることにしました
レジストリィの場所とデータの形式
元号の情報を持っているレジストリィは HKLM:\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras
にあります
内容をPowerShellで取得するとこんな感じです
PS > Get-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras'; Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese Name Property ---- -------- Eras 1868 01 01 : 明治_明_Meiji_M 1912 07 30 : 大正_大_Taisho_T 1926 12 25 : 昭和_昭_Showa_S 1989 01 08 : 平成_平_Heisei_H 2019 05 01 : 令和_令_Reiwa_R
このレジストリィの仕様は見当たらなかったのですが、直感的に値の名前を開始年月日を yyyy MM dd
の形で持ち、値は元号の漢字表記、漢字表記の1文字目、ヘボン式ローマ字表記、ヘボン式ローマ字表記1文字目を _
を区切り子として持っているようです
江戸時代まで遡って元号をレジストリィに登録してみる
元号一覧 (日本) - Wikipedia を参考に江戸時代までのCSVを用意して取り込んでみることにします
[String] $registryKeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras'; [String] $csvPath = '.\JapanseEraInEdo.csv'; Get-Content -Path $csvPath | ConvertFrom-CSV | Where-Object { $null -ne ($_.StartDate -as [DateTime]) } | ForEach-Object { Add-Member -InputObject $_ -MemberType NoteProperty -Name 'Name' -Value ($_.StartDate -as [DateTime]).ToString('yyyy MM dd'); Add-Member -InputObject $_ -MemberType NoteProperty -Name 'Value' -Value (($_.KanjiEraName, $_.KanjiEraName[0], $_.RomanAlphabetEraName, $_.RomanAlphabetEraName[0]) -join '_'); Write-Output $_; } | Where-Object { $_.Name -notin (Get-Member -InputObject (Get-ItemProperty -Path $registryKeyPath) | ForEach-Object {$_.Name}) } | New-ItemProperty -Path $registryKeyPath > $null;
PS > Get-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras'; Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese Name Property ---- -------- Eras 1868 01 01 : 明治_明_Meiji_M 1912 07 30 : 大正_大_Taisho_T 1926 12 25 : 昭和_昭_Showa_S 1989 01 08 : 平成_平_Heisei_H 2019 05 01 : 令和_令_Reiwa_R 1615 09 05 : 元和_元_Genna_G 1624 04 17 : 寛永_寛_Kan'ei_K 1645 01 13 : 正保_正_Shouhou_S 1648 04 07 : 慶安_慶_Keian_K 1652 10 20 : 承応_承_Jouou_J 1655 05 18 : 明暦_明_Meireki_M 1658 08 21 : 万治_万_Manji_M 1661 05 23 : 寛文_寛_Kanbun_K 1673 10 30 : 延宝_延_Enpou_E 1681 11 09 : 天和_天_Tenna_T 1684 04 05 : 貞享_貞_Joukyou_J 1688 10 23 : 元禄_元_Genroku_G 1704 04 16 : 宝永_宝_Houei_H 1711 06 11 : 正徳_正_Shoutoku_S 1716 08 09 : 享保_享_Kyouhou_K 1736 06 07 : 元文_元_Genbun_G 1741 04 12 : 寛保_寛_Kanpou_K 1744 04 03 : 延享_延_Enkyou_E 1748 08 05 : 寛延_寛_Kan'en_K 1751 12 14 : 宝暦_宝_Houreki_H 1764 06 30 : 明和_明_Meiwa_M 1772 12 10 : 安永_安_An’ei_A 1781 04 25 : 天明_天_Tenmei_T 1789 02 19 : 寛政_寛_Kansei_K 1801 03 19 : 享和_享_Kyouwa_K 1804 03 22 : 文化_文_Bunka_B 1818 05 26 : 文政_文_Bunsei_B 1831 01 23 : 天保_天_Tenpou_T 1845 01 09 : 弘化_弘_Kouka_K 1848 04 01 : 嘉永_嘉_Kaei_K 1855 01 15 : 安政_安_Ansei_A 1860 04 08 : 万延_万_Man'en_M 1861 03 29 : 文久_文_Bunkyuu_B 1864 03 27 : 元治_元_Genji_G 1865 05 01 : 慶応_慶_Keiou_K
JapaneseCalendar classを使って江戸時代の日付を元号表示 (しようと) する (がエラーになる)
PS > [CultureInfo] $culture = [CultureInfo]::New("ja-JP"); PS > [Globalization.JapaneseCalendar] $culture.DateTimeFormat.Calendar = [System.Globalization.JapaneseCalendar]::new(); PS > ([Datetime]'1865/05/01').ToString('ggy年', $culture); "2" 個の引数を指定して "ToString" を呼び出し中に例外が発生しました: "指定された引数は、有効な値の範囲内にありません。 パラメーター名:時間値が年号の範囲を超えています。" 発生場所 行:3 文字:1 + ([Datetime]'1865/05/01').ToString('ggy年', $culture); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : ArgumentOutOfRangeException
エラーになりました
指定された引数は、有効な値の範囲内にありません。パラメーター名:時間値が年号の範囲を超えています。
とのことなのでこの期に及んでJapaneseCalendar Classの仕様を調べます
JapaneseCalendar Class (System.Globalization) | Microsoft Docs
This class handles dates from September 8 in the year Meiji 1 (in the Gregorian calendar, September 8, 1868). Although the Japanese calendar was switched from a lunar calendar to a solar calendar in the year Meiji 6 (1873 of the Gregorian calendar), this implementation is based on the solar calendar only.