ElenaDBA ElenaDBA - 1 month ago 24
Vb.net Question

Writing my own IsDate function in VB

I have had problems with VB.NET IsDate function - it returns true on string values that are not a valid date, such as "367 7" and "10,600" etc. So I have decided to write my own function and wanted to hear some feedback on possible improvements. Would really appreciate valuable input.

Function IsValidDate(ByVal str As String) As Boolean
str = str.Replace(" ", "").Trim()
'If (str Is Nothing) Then
' Return False
'End If
'If IsNumeric(str) Then
' Return False
'End If
'If Regex.IsMatch(str, "^[A-Za-z ]+$") Then
' Return False
'End If
If Regex.IsMatch(str, "^(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d$") Then
''mm/dd/yyyy or mm-dd-yyyy
Return True
ElseIf Regex.IsMatch(str, "^(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]\d\d$") Then
''mm/dd/yy or mm-dd-yy
Return True
ElseIf Regex.IsMatch(str, "^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$") Then
''dd-mm-yyyy or dd/mm/yyyy
Return True
ElseIf Regex.IsMatch(str, "^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$") Then
''yyyy-mm-dd or yyyy/mm/dd

Return True
End If

Return False
End Function


I took care of a possible space in the numeric string (ex.: "367 7", then I made sure it returns false if the value is numeric or nothing. I also eliminated strings that are all alphanumeric. Please let me know what do you think. Thank you

P.S> Edit: I commented out a few lines in the beginning as I felt they could be eliminated since if the string does not match one of the regexes, it will return false anyway

Answer

Running into this situation in my own code, I found that the 'TryParseExact' function is significantly slower than using a series of 'Regex.Match' calls.

This is the function that I wrote to check the formats I am looking for and it ran about 10x faster than TryParseExact.

The downside of this over TryParseExact is that it does not check all of the edge cases, such as '31 is not a valid day in November' or '29 is not a valid day in Feb on certain years'. So as long as you are willing to give up those catches, then this is faster.

        Public Shared Function ChkDate(ByVal Value As Object) As Boolean
            If Value.GetType().Name = "DateTime" Then
                Return True
            ElseIf Not String.IsNullOrWhiteSpace(Value.ToString()) Then
                Dim TempStr As String = Value.ToString()
                ' Please speed test before making any changes to this function, the below version is much faster than Date.TryParse or Date.TryParseExact

                If InStr(TempStr, ".") <> 0 AndAlso TempStr.Split({"."c}).Length = 3 Then ' d.M.yyyy
                    Dim TempArray() As String = TempStr.Split({"."c})
                    Dim NewString As String = TempArray(1) & "/" & TempArray(0) & "/" & TempArray(2)
                ElseIf InStr(TempStr, "/") <> 0 AndAlso RegularExpressions.Regex.IsMatch(TempStr, "\A[01]{0,1}[0-9]{1}/[0123]{0,1}[0-9]{1}/[0-9]{4}\z") Then ' M/d/yyyy
                    Return True
                ElseIf InStr(TempStr, "-") <> 0 AndAlso RegularExpressions.Regex.IsMatch(TempStr, "\A[0-9]{4}-[01]{0,1}[0-9]{1}-[0123]{0,1}[0-9]{1}\z") Then ' yyyy-M-d
                    Return True
                ElseIf InStr(TempStr, "-") <> 0 AndAlso InStr(TempStr, ":") <> 0 AndAlso RegularExpressions.Regex.IsMatch(TempStr, "\A[0-9]{4}-[01]{0,1}[0-9]{1}-[0123]{0,1}[0-9]{1} [01]{0,1}[0-9]{1}:[01]{0,1}[0-6]{1}:[01]{0,1}[0-6]{1}\z") Then ' yyyy-M-d H:mm:ss
                    Return True
                ElseIf InStr(TempStr, "/") <> 0 AndAlso InStr(TempStr, ":") <> 0 AndAlso RegularExpressions.Regex.IsMatch(TempStr, "\A[01]{0,1}[0-9]{1}/[0123]{0,1}[0-9]{1}/[0-9]{4} [01]{0,1}[0-9]{1}:[01]{0,1}[0-6]{1}\z") Then ' M/d/yyyy h:mm
                    Return True
                ElseIf RegularExpressions.Regex.IsMatch(TempStr, "\A[0-9]{4}[01]{1}[0-9]{1}[0123]{1}[0-9]{1}\z") Then ' yyyyMMdd
                    Return True
                ElseIf RegularExpressions.Regex.IsMatch(TempStr, "\A[0-9]{4}[01]{0,1}[0-9]{1}[0123]{0,1}[0-9]{1}[01]{0,1}[0-9]{1}[01]{0,1}[0-6]{1}\z") Then ' yyyyMMddHHmm
                    Return True
                Else
                    Return IsDate(TempStr)
                End If
            End If
            Return False
        End Function