IsDate関数の問題について

VB.NETの関数に「IsDate」関数というのがあります。

VBAの関数にも同様のものがありますが、サンプルコードなどはVB.NETで作成しています。)

この関数は対象の変数が日付になりうるかチェックすることができるもの。

しかしデータによってはエラーにならず、チェック処理をすり抜けるものがいます。

 

VB.NET実行プログラム

プログラムを用意しました。

Sub Main()

    Dim chkDate As String

    chkDate = "2018/03/04"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "2018/3/4"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "18/03/04"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "18/3/4"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "2018/3/814"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "50/3/14"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "14/3/50"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "3/814"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "1/3/814"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "昭和99年5月10日"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "平成99年5月10日"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "平成99年5月"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "5月平成99年"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

    chkDate = "3.1415"
    Debug.WriteLine(chkDate & " : " & IsDate(chkDate))

End Sub

いろんなバリエーションの日付、もしくは日付風なデータをIsDate関数で日付かどうかチェックします。

 

   

VB.NETの実行結果

日付 VB.NET
2018/03/04 True
2018/3/4 True
18/03/04 True
18/3/4 True
2018/3/814 False
50/3/14 True
14/3/50 False
3/814 True
1/3/814 True
昭和99年5月10日 True
平成99年5月10日 True
平成99年5月 True
5月平成99年 False
3.1415 True

Trueは「日付と認識しました」、Falseは「日付ではありません」という意味です。

 

ここで気を付けないといけないのが、赤太字にした部分。

3/814」とか「3.1415」みたいな円周率の冒頭なども日付として扱われています。

 

 

この事象が発生する原因は?

事の発端ですが、ユーザーがパソコンのテンキーで

「3/14」という日付を入力しようとしました。

しかし、「3/814」と「/」の下にある8も

同時に打ってしまったがためにこの数字が生まれました。

この入力値は日付として認識され、そのまま後続処理でエラーになったのです。

 

 

いろんな日付表記に対応したため

上記の入力値を日付として認識された理由は、

海外に「日月年」という日付表記があり、「814年3月」と解釈されたからでした。

「3.1415」も「1415年3月」と認識されているからだと思います。

 

   

昭和や平成が「99年」って異常?

ちなみに、実行結果比較で昭和と平成が99年まで

表示されていることにお気づきでしょうか?

これはMicrosoftが例外エラーにはせず処理を通すようにしているからです。

元号に関しては今回は割愛しますが、

対応をしたい人はレジストリを書き換えてチェックする方法がよさそうです。

 

アプリケーションの新元号対応

 

日本語圏で使われている日付のチェックをしたい

話を戻します。

今回発生した「3/814」や「3.1415」は日付としては不適切です。 ですので、正規表現を使って日付のチェックをしたいと思います。

 

VB.NET実行プログラム(正規表現版)


''' <summary>
''' 日付の正規表現チェック
''' </summary>
''' <param name="inputDate"></param>
''' <returns></returns>
Public Function DateRegularExpression(inputDate As String) As Boolean

  Const Regular As String = "^(?<year>[0-9]{4}|[0-9]{2})(?<datesep>\/|-|\.)(?<month>0?[1-9]|1[012])\k<datesep>(?<day>0?[1-9]|[12][0-9]|3[01])$"

  If System.Text.RegularExpressions.Regex.IsMatch(inputDate, Regular) Then
    Return True
  End If

  Return False

End Function

正規表現によって「yyyy/MM/dd」や「yy/MM/dd」は許可してそれ以外を拒否します。

これを以下のように呼び出して使います。

Debug.WriteLine(chkDate & " : " & DateRegularExpression(chkDate))

 

VB.NETの実行結果(正規表現版)

日付 VB.NET
2018/03/04 True
2018/3/4 True
18/03/04 True
18/3/4 True
2018/3/814 False
50/3/14 True
14/3/50 False
3/814 False
1/3/814 False
昭和99年5月10日 False
平成99年5月10日 False
平成99年5月 False
5月平成99年 False
3.1415 False

明らかにデータとしておかしいものはすべてFalseになりました。

西暦表示がメインですので、和暦表示は日付ではないことになります。

お役所系は和暦表示が重要なので、

この辺りが必要な方は別途調整する必要がありますね。

 

今回はVB.NETで正規表現をしましたが、VBAでも正規表現ができます。

VBAを勉強している方も日付チェックで困っている方も

一度正規表現を試してみてください。

 

 

以上