【.NET】ParseExact関数に渡す文字列から元号を省略したときの挙動
"300110"
この数列が何を表しているか分かりますか?
そう、日付です。平成30年01月10日です。分かりませんね。
今回諸般の事情でこのような形のデータを処理しなければならなくなり、また改元にも対応しなくてはということでJapaneseCalendarクラスについて色々と調べてみたのですが、標題の疑問が解決しなかったので自分でテストしてみました。
テスト1
さくっと書きます(System.Globalization名前空間を使います)。
Dim ConvertJapaneseDate = Function(targetDate As String, targetFormat As String) As Date Dim cultureJapan As CultureInfo = New CultureInfo("ja-JP", True) cultureJapan.DateTimeFormat.Calendar = New JapaneseCalendar() Return DateTime.ParseExact(targetDate, targetFormat, cultureJapan) End Function Debug.Print(ConvertJapaneseDate("30/01/10", "yy/MM/dd"))
結果:
ちゃんと変換されてる。ちゃんとというか指定してないのに平成扱いされました。
テスト2
さて、JapaneseCalendarクラスが何を元に元号を処理しているかと言えば、レジストリです。
regeditで下記のフォルダを覗いてみましょう。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras
ありました。
試しにここに新しい値を追加して…
先ほどのコードを走らせると…
結果が変わりました。
最終テスト
ここで冒頭の疑問に立ち返りますが、では一体この中からどんな基準で元号を補完しているのでしょうか。
考えられるのはシステム日付でしょう。つまり「レジストリとシステム日付から現在の元号を取得し補完している」という仮説です。
レジストリに未来日付を登録し…
Debug.Print(ToDay)を加えて実行します。
今日は2018年の1月25日です。
結果:
はい。というわけでシステム日付は関係ありませんでした。常に最新の元号が補完されるようです。
補足
これでデフォルトの挙動は掴めましたが、やはり自分で元号を明示的に補完した方が圧倒的に安心です。
よほど楽がしたいでもなければ
Dim regKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras", False) Dim eraDic As New Dictionary(Of Date, String) For Each eName In regKey.GetValueNames eraDic.Add(CDate(eName.Replace(" ", "/")), regKey.GetValue(eName)) Next
等で元号の一覧を拾って自分で日付に加えてあげるといいんじゃないかと思います。