2019年5月1日から元号が平成から令和へと変わりますが、2019/4/20時点で、Windowsや.NetFrameworkが新元号にまだ対応していません。
5月1日まで残り僅かで、元号を取り扱うアプリでは修正作業が必要な場合があります。
VB.NETでは、CType(expression, typename)を利用してオブジェクトをDate
型にする変換する際、和暦から西暦に変換する事が出来ます。
変換例
頭文字に平成
、H
、h
文字があり尚且つ/
、-
などの区切り文字があると和暦から西暦へ変換します。
Console.WriteLine(CType("平成31年4月21日", Date).Date.ToString("yyyy/MM/dd"))
' 2019/04/21
Console.WriteLine(CType("H31/4/21", Date).Date.ToString("yyyy/MM/dd"))
' 2019/04/21
Console.WriteLine(CType("H31.4.21", Date).Date.ToString("yyyy/MM/dd"))
' 2019/04/21
Console.WriteLine(CType("H31-4-21", Date).Date.ToString("yyyy/MM/dd"))
' 2019/04/21
Console.WriteLine(CType("H31 4 21", Date).Date.ToString("yyyy/MM/dd"))
' 2019/04/21
Console.WriteLine(CType("h31-4-21", Date).Date.ToString("yyyy/MM/dd"))
' 2019/04/21
###問題点
CType
による変換ですが、殆どのケースで期待する和暦→西暦変換になり大変便利なのですが、新元号の登場により取扱方によっては問題が発生します。
1.Windows Update前に、令和(R01)を入力した場合、変換エラーになる。
2.Windows Update後に、来年以降の平成(H32)を入力した場合、変換エラーになる可能性が高い。
###変換範囲
CType
による変換では、昭和・平成が混在する年については新旧どちらでも期待する西暦に変換出来ます。
しかし、翌年以降は旧和暦(昭和)を西暦変換出来ません。
また、R(令和)については未対応なので必ず変換エラーになります!※2019/4/20時点 近日中にWindows Updateで改善する筈。。。
入力する和暦をGgg/mm/dd
フォーマットと仮定して、変換結果を調べてみました。
入力 | 期待する西暦 | 結果 | 備考 |
---|---|---|---|
S64/01/01 | 1989/01/01 | ○ | |
S64/12/31 | 1989/12/31 | ○ | 昭和は1月7日迄ですが年内は変換可能 |
S65/01/01 | 1990/01/01 | × | 翌年以降は昭和の変換が不可能 |
H01/01/01 | 1989/01/01 | ○ | 平成元年は1月8日からですが年内は変換可能 |
H01/12/31 | 1989/12/31 | ○ | 年内は平成・昭和どちらでも変換可能 |
H02/01/01 | 1990/01/01 | ○ | 翌年からは平成のみ変換可能 |
H31/05/01 | 2019/05/01 | ○ | |
H32/01/01 | 2020/01/01 | ○ | 本来は令和2年ですが、平成でも変換可能 ※ |
H99/01/01 | 2087/12/31 | ○ | 本来は令和69年ですが、平成でも変換可能 ※ |
R01/05/01 | 2019/05/01 | × | 現時点ではR を元号と認識しません |
※令和対応のWindows Update後、変換エラーになる可能性大 |
###対応策
ファンクションに和暦を投げて、西暦に変換して返します。
変換出来ない場合は、1900/01/01
になります。
尚、和暦はアルファベットのみ対応なので、元号gg年mm月dd日
のフォーマットの場合はもう少し修正が必要です。
Sub Main()
Dim obj As Object = "H31/5/1"
Debug.Print(GengoToDate(obj).ToString("yyyy/MM/dd"))
End Sub
Function GengoToDate(ByVal obj As Object) As Date
Dim rslt As Date
If obj Is DBNull.Value OrElse obj = "" Then
rslt = CType("1900/01/01", Date)
Else
' 頭文字を取得
Dim hc As String = CType(obj, String).Substring(0, 1)
If IsNumeric(hc) Then
' 西暦
If hc = "1" OrElse "2" Then
rslt = CType(obj, Date)
Else
rslt = CType("1900/01/01", Date)
End If
Else
' 和暦
' 区切り文字で年・月・日に分割
Dim arr As String() = {"/", ".", "-", " ", ""}
Dim ggmmdd As String() = {""}
For Each a As String In arr
If CType(obj, String).Contains(a) Then
ggmmdd = Split(CType(obj, String), a)
Exit For
End If
Next
If ggmmdd.Length = 3 And hc.ToUpper = "H" Then
' 平成
If CType(ggmmdd(0).Remove(0, 1), Int16) >= 30 Then
'来年以降は変換エラーになる可能性があるため、当年も含め手動で変換する
rslt = CType(String.Join("/", {ggmmdd(0).Remove(0, 1) + 1988, ggmmdd(1), ggmmdd(2)}), Date)
Else
' 昨年以下は、そのまま変換
rslt = CType(obj, Date)
End If
ElseIf ggmmdd.Length = 3 And hc.ToUpper = "R" Then
' 令和
' MS側の対応より先回りして対応
rslt = CType(String.Join("/", {ggmmdd(0).Remove(0, 1) + 2018, ggmmdd(1), ggmmdd(2)}), Date)
Else
rslt = CType("1900/01/01", Date)
End If
End If
End If
Return rslt
End Function
###最後に
和暦なんて関係無いと思っても意外なケースでシステムに関係してくるので注意しましょう〜