元号が改正された場合の西暦と和暦の相互変換について [JAPAN]

Posted by on in Programming

旧バージョンの開発環境で作成したアプリのWindows10対応やマイグレーションを行う場合に、そのアプリで和暦を取り扱っている場合には、元号改正に伴う対応を考える必要があります。しかし元号改正に伴う対応は個々のアプリケーションごとに前提条件等が異なりますので一律に話を進めることができません。

また、アプリケーション側以外の部分での対応が必要なものもあります。たとえば、1文字で元号を表す文字(㍾、㍽、㍼、㍻)の対応が挙げられます。新しい元号が収録されるかどうかはUnicodeに関わる話ですし、それを実際に取り扱う場合にはフォントの対応やIME辞書への収録が必要となります。

このようにアプリケーション側だけでは対応できない部分については一旦置いておき、この記事ではターゲットをもっと絞りって西暦と和暦の変換に関する内容をご案内致します。

 

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 によって対応がなされるかもしれません。

元号改正に関する話は元号改正に伴うユースケースの洗い出しを行うことから始めておき、アプリケーション側で対応できない箇所が存在した場合に備えて対応方針を計画して頂くのがよいでしょう。

 



About
Gold User, No rank,
Sales Consultant at Embarcadero Technologies, in Japan.

Comments

Check out more tips and tricks in this development video: