江戸時代の元号をレジストリィに足したが.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.