元号改正に関する話はアプリケーションから見ると、考慮すべき点がいろいろとあるかと思います。しかしそれは個々のアプリケーションごとに前提条件等が異なりますので一律に話を進めることは難しいです。
そこでここでは西暦と和暦の変換に絞った内容を記載いたします。
Windows OS側の対応
元号が改正された場合は、Windowsでは基本的にはレジストリへの新しい元号の登録によって対応しますDelphi/C++BuilderはOSの機能やAPIを使っており、暦の処理に独自の実装を行ってはいません。
レジストリ設定に関するマイクロソフトのドキュメントは以下のようなものがあります。
https://msdn.microsoft.com/en-us/library/windows/desktop/ee923790.aspx?f=255&MSPPError=-2147217396
これに基づくと、たとえば 2017年1月1日から元号が “改元” に変わるという設定は以下のように書けます。
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras]
"2017 01 01"="改元_改_Kaigen_K"
この設定の結果は PowerShell で以下のように実行することでも確認できます。
PS C:\> $path = "HKLM:\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras"
PS C:\> Get-ItemProperty $path
1868 01 01 : 明治_明_Meiji_M
1912 07 30 : 大正_大_Taisho_T
1926 12 25 : 昭和_昭_Showa_S
1989 01 08 : 平成_平_Heisei_H
2017 01 01 : 改元_改_Kaigen_K
PSPath :
Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras
PSParentPath :
Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese
PSChildName : Eras
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
PS C:\> $CultureInfo = New-Object system.Globalization.CultureInfo("ja-JP");
PS C:\> $CultureInfo.DateTimeFormat.Calendar = New-Object System.Globalization.JapaneseCalendar
PS C:\> $CurrentDate = Get-Date
PS C:\> $CurrentDate.ToString("ggyy年MM月dd日",$CultureInfo)
改元01年01月19日
PS C:\>
テストを終えたらレジストリの設定を元に戻すことをお忘れなく。このようにレジストリだけで新しい元号に対応できるので、改元の際には Windows Update によって新しい元号の情報が追加されることになるでしょう。
上記レジストリの値を利用可能な西暦→和暦変換
FormatDateTime, DateToStr, DateTimeToStr を実行すると、上記レジストリの値を参照しての西暦→和暦変換が行われます。
上記レジストリの値を利用可能な和暦→西暦変換
TFormatSettingsでShortDateFormatに元号を含む書式を指定した上で、StrToDate を使えば改元後の和暦の日付を西暦に変換できます。
var
JPNEraFormat: TFormatSettings;
strDate: String;
timestamp: TDateTime;
begin
strDate := '改元1年1月19日';
JPNEraFormat := TFormatSettings.Create('ja-JP');
JPNEraFormat.ShortDateFormat := 'ggee/m/d';
strDate := StringReplace(strDate, '年', '/', []);
strDate := StringReplace(strDate, '月', '/', []);
strDate := StringReplace(strDate, '日', '', []);
timestamp := StrToDate(strDate,JPNEraFormat);
end
このように日付の文字列に年、月、日を含む場合は / に置換するなどの前処理を行ってから StrToDate を実行することに注意が必要です。
なお、VarToDateTime で和暦→西暦変換を実装すればコードの量はもっと少なく済むのですが、ことに VarToDateTime は前述のレジストリを参照していません。改正後の元号を用いた日付を渡すと例外が発生します。ただしVarToDateTime の機能自体はOS側の機能に依存しています。Windows で日付文字列を内部データに変換する処理は複数の関数があるのですが、関数によって挙動が違うようです。これは今後の Windows Update によって対応がなされるかもしれません。
元号改正に関する話は2017年春の通常国会で法整備が進むものと考えられますので、その状況を見守りつつ、現時点では元号改正に伴うユースケースの洗い出しを行うことから始めればよいでしょう。
Read More