【问题标题】:Writing my own IsDate function in VB在 VB 中编写我自己的 IsDate 函数
【发布时间】:2015-04-23 14:35:14
【问题描述】:

我在使用 VB.NET IsDate 函数时遇到了问题 - 它在不是有效日期的字符串值上返回 true,例如“367 7”和“10,600”等。所以我决定编写自己的函数并想要听取有关可能改进的一些反馈。非常感谢您提供宝贵的意见。

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

我处理了数字字符串中可能存在的空格(例如:“367 7”,然后我确保如果该值是数字或什么都没有,它会返回 false。我还删除了所有字母数字的字符串。请让我知道你怎么想。谢谢

P.S> 编辑:我在开头注释掉了几行,因为我觉得它们可以被删除,因为如果字符串与其中一个正则表达式不匹配,它无论如何都会返回 false

【问题讨论】:

  • 您不允许某些人可能认为有效的一些格式。如果您是唯一的用户,这不是问题,但是如果其他人可以使用该功能,则需要考虑一些问题。您不允许使用“”作为分隔符的格式(例如 12 31 2014),并且您不允许拼写月份(完整或缩写 - 例如 Apr 或 April)。
  • 这不是问题...

标签: vb.net validation datetime


【解决方案1】:

尝试过这样的事情吗?

   Function IsValidDate(ByVal str As String) As Boolean
Dim test As Date
        If Date.TryParseExact(str, "yyyy/MM/dd HH:mm:ss", System.Globalization.CultureInfo.CurrentCulture, Globalization.DateTimeStyles.None, test) Then
                Return True
            Else
                Return False
            End If
    End Function

从这里您可以更改引号中的格式。

!编辑!

由于我的声誉,我无法添加 cmets,但如果在您的评论中有您的格式数组并使用我的代码,而不是我在那里的格式,请将您的数组格式放在它的位置。它对我来说很好。

Dim test As Date
Dim formats As String() = {"MM/dd/yyyy", "MM-dd-yyyy", "MM/dd/yy", "MM-dd-yy", "M-d-yyyy", "M/d/yyyy", "M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", "MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss", "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", _
                               "M/d/yyyy h:mm", "M/d/yyyy h:mm", "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"}



If Date.TryParseExact(str, formats, System.Globalization.CultureInfo.CurrentCulture, Globalization.DateTimeStyles.None, test) Then
   Return True
Else
   Return False
End If

这不会重新组织您的输入,而只是一个布尔返回以查看它是否与您指定的格式匹配,这就是您最初想要的正确格式?

【讨论】:

    【解决方案2】:

    在我自己的代码中遇到这种情况,我发现“TryParseExact”函数比使用一系列“Regex.Match”调用慢得多。

    这是我编写的用于检查我正在寻找的格式的函数,它的运行速度比 TryParseExact 快大约 10 倍。

    与 TryParseExact 相比,它的缺点是它不会检查所有边缘情况,例如“31 不是 11 月的有效日期”或“29 在某些年份不是 2 月的有效日期”。所以只要你愿意放弃那些捕获,那就更快了。

            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
    

    【讨论】:

      【解决方案3】:

      您是否查看过DateTime.ParseExact,而不是使用正则表达式?它可以让您定义您支持的确切格式。

      【讨论】:

      • Hans,我尝试了 ParseExact,如果有问题的字符串不是有效的日期时间,它会引发异常。不确定这是否是处理事情的最佳方式......我在这里做错了吗?暗淡格式 As String() = {"MM/dd/yyyy", "MM-dd-yyyy", "MM/dd/yy", "MM-dd-yy", "M-d-yyyy", "M/d /yyyy”、“M/d/yyyy h:mm:ss tt”、“M/d/yyyy h:mm tt”、“MM/dd/yyyy hh:mm:ss”、“M/d/yyyy h :mm:ss", "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", _ "M/d/yyyy h:mm", "M/d/yyyy h:mm" , "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"} dt = DateTime.ParseExact(str, formats, New CultureInfo("en-US"), DateTimeStyles.None)
      • @ElenaDBA 如果你想避免异常,你可以使用 TryParseExact 代替。哪个最合适取决于情况,如果输入来自另一个应用程序或存储的数据,我可能会坚持抛出异常,但如果你想检查用户输入是否是有效日期,那么在某些情况下我可能会选择返回 false 的那个。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多