DateTime.ParseExact等效于VB6?

时间:2016-08-25 20:22:53

标签: datetime vb6

有没有人知道VB6 for .NET DateTime.ParseExact()方法中是否存在实际等效方法?我尝试过使用DateSerial()IsDate()CDate(),但是,由于所有VB6"有用性",我都是得出一些意想不到的结果。

更具体地说,我尝试从用户输入中解析文本字符串以验证它是否是实际日期。例如,我将使用日期8/25/16。通常的预期输入可能会也可能没有月,日和年之间的分隔符,因此可以输入为82516

以下是代码未按预期工作的示例(82516的值存储在TempStr变量中):

If IsDate(Format(TempStr, "#/##/##")) And IsDate(Format(TempStr, "##/#/##")) Then
    TempDate = #12:00:00 AM#
ElseIf IsDate(Format(TempStr, "#/##/##")) Then
    TempDate = CDate(Format(Tempstr, "#/##/##"))
ElseIf IsDate(Format(TempStr, "##/#/##")) Then
    TempDate = CDate(Format(TempStr, "##/#/##"))
End If

使用所述值,第一个条件触发。知道它是如何工作的,我理解为什么会发生这种情况(它会重新排列"尝试匹配有效日期的月,日和年),但我真的很了解试图让它按特定顺序解析日期。我知道.NET的DateTime.ParseExact()方法会让我在那里,但我必须在VB6中做这个(维护一些遗留代码)。

我尝试使用DateSerial()

If DateSerial(CInt(Right(TempStr, 2)), CInt(Left(TempStr, 1)), CInt(Mid(TempStr, 2, 2))) > #12:00:00 AM# Then
    If DateSerial(CInt(Right(TempStr, 2)), CInt(Left(TempStr, 2)), CInt(Mid(TempStr, 3, 1))) > #12:00:00 AM# Then
        TempDate = #12:00:00 AM#
    Else
        TempDate = DateSerial(CInt(Right(TempStr, 2)), CInt(Left(TempStr, 1)), CInt(Mid(TempStr, 2, 2)))
    End If
Else
    If DateSerial(CInt(Right(TempStr, 2)), CInt(Left(TempStr, 2)), CInt(Mid(TempStr, 3, 1))) > #12:00:00 AM# Then
        TempDate = DateSerial(CInt(Right(TempStr, 2)), CInt(Left(TempStr, 2)), CInt(Mid(TempStr, 3, 1)))
    Else
        TempDate = #12:00:00 AM#
    End If
End If

但如果任何参数的值超出可接受的范围,那么这也伴随着自动校正。

我还尝试了以上代码的以下变体:

If IsDate(Format(TempStr, "m/dd/yy")) And IsDate(Format(TempStr, "mm/d/yy")) Then
...

但是第一次测试会导致完全不同的3/12/26值,这与原始输入相反。

有没有办法在VB6中准确模拟.NET DateTime.ParseExact()方法,或者我只是不得不将这些类型的用户输入值抛弃为无效/模糊?

2 个答案:

答案 0 :(得分:1)

我将亲自编写一个函数来确保返回正确的日期 -

首先获取字符串/整数,将其分解为块并将值添加到这些块并返回组合日期...

Option Explicit

Public Function MakeCorrectDate()

Dim xMakeDate As Long, xDay As Integer, xMonth As Integer, xYear As Integer, xCentury As Integer, strCorrectDate As String
''xMake as long because of size, strCorrectDate as string to allow the /...

xMakeDate = txtInput.Text

''Assuming the format will ALWAYS be the same days, months and year (12/20/16) and length is ALWAYS 6...
xDay = Left$(xMakeDate, 2)
xMonth = Mid$(xMakeDate, 3, 2)
xYear = Right(xMakeDate, 2)

''First get the correct part to 1900 or 2000...
If xYear = "00" Then
    xCentury = 20
ElseIf xYear < 99 And xYear > 20 Then ''Year 2000 and year 2020
    xCentury = 19
        Else
    xCentury = 20
End If

strCorrectDate = xDay & "/" & xMonth & "/" & xCentury & xYear

txtYear.Text = strCorrectDate

End Function

Private Sub cmdGetCorrectDate_Click()

If Not Len(txtInput.Text) = 6 Then
    MsgBox "Incorrect information, must be 6 or more characters."

    Exit Sub
        Else
    Call MakeCorrectDate
End If
End Sub

Private Sub txtInput_Change()

''Ensure the user adds only numerical text...
Dim WshShell As Object

Set WshShell = CreateObject("WScript.Shell")

If Not IsNumeric(txtInput.Text) Then
    WshShell.SendKeys "{BackSpace}"
End If
End Sub

答案 1 :(得分:0)

好的,这就是我提出的解决当前需求的方法。与上面发布的@ Andre-Oosthuizen类似,我决定从以前的工作中彻底简化验证。此系列功能要求用户输入六位数日期(两位数月份,两位数日期和两位数年份)。我不相信这个世纪会成为这个特定应用的一个因素,所以我将把这个测试留下来。

这对我们的用户来说应该是可以接受的,因为他们在其他系统中有类似的限制。虽然我个人更喜欢更“防弹”的解决方案(例如使用DatePicker或其他UI操作),但我认为这对我们的环境来说是最有效的。

'----------------------------------------------------------------------
' LostFocus event handler for the txtEffectiveDate TextBox.
' Test for a valid date when the user attempts to leave the field.
'----------------------------------------------------------------------
Private Sub txtEffectiveDate_LostFocus()
    ' *********************************************************************
    ' ** Don't have the event handler try to do any parsing.  Just pass  **
    ' ** the .Text value to the validation function.  If a date comes    **
    ' ** back, reformat it to "look" like a date and move on.  Otherwise **
    ' ** pop up an "error" message and return focus to the TextBox for   **
    ' ** the user to correct their input.                                **
    ' *********************************************************************
    Dim TempDate As Date

    TempDate = CheckForValidDate(Me.txtEffectiveDate.Text)

    If TempDate > #12:00:00 AM# Then
        ' If a valid Date is returned, put the formatted String value
        ' into the TextBox and move on.
        Me.txtEffectiveDate.Text = Format(TempDate, "mm/dd/yy")
    Else
        ' If the Date value is not valid (#12:00:00 AM#), notify the
        ' user and refocus on the TextBox to force the user to
        ' correct the input before continuing.
        MsgBox "The date you entered was not valid." & vbCrLf & vbCrLf & _
               "Please enter two digits for the month, two digits for the day and" & vbCrLf & _
               "two digits for the year." & vbCrLf & vbCrLf & _
               "For example, today's date should be entered as either " & Format(Now, "mmddyy") & vbCrLf & _
               " or " & Format(Now, "mm/dd/yy") & ".", _
               vbOKOnly + vbExclamation, "INVALID INPUT FORMAT"
        Me.txtEffectiveDate.SetFocus
        Me.txtEffectiveDate.SelStart = 0
        Me.txtEffectiveDate.SelLength = Len(Me.txtEffectiveDate.Text)
    End If
End Sub

'----------------------------------------------------------------------
' Attempts to convert the String input to a Date value.  If the String
' value is already a Date (i.e., "1/1/16" or similar), go ahead and
' assume that the user wants that date and return it as a Date value.
' Otherwise, strip any non-numeric characters and break apart the input
' to pass along for further validation.
'----------------------------------------------------------------------
Private Function CheckForValidDate(ByVal DateStr As String) As Date
    Dim TempDate As Date

    If IsDate(DateStr) Then
        ' If the String value is already in a date format, 
        ' just return the Date value of the String.
        TempDate = CDate(DateStr)
    Else
        Dim TempStr As String
        Dim CurrentChar As String
        Dim TempYear As Integer
        Dim TempMonth As Integer
        Dim TempDay As Integer
        Dim I As Integer

        ' Strip all non-numeric characters to get a purely numeric string.
        For I = 1 To Len(DateStr)
            CurrentChar = Mid(DateStr, I, 1)

            If IsNumeric(CurrentChar) Then
                TempStr = TempStr & CurrentChar
            End If
        Next I

        ' The all-numeric string should be exactly six characters
        ' (for this application).
        If Len(Trim(TempStr)) = 6 Then
            Dim NewDateStr As String

            ' Break the numeric string into the component parts -
            ' Month, Day, and Year.  At six characters, there should
            ' be two characters for each element.
            TempMonth = CInt(Left(TempStr, 2))
            TempDay = CInt(Mid(TempStr, 3, 2))
            TempYear = CInt(Right(TempStr, 2))

            ' Now pass the individual values to the second part of
            ' the validation to ensure each of the individual values
            ' falls within acceptable ranges.
            NewDateStr = GetValidDateString(TempMonth, TempDay, TempYear)

            ' If the returned String value is not empty, then convert
            ' it to a Date value for returning to the calling method
            If Len(Trim(NewDateStr)) > 0 Then
                TempDate = CDate(NewDateStr)
            End If
        End If
    End If

    CheckForValidDate = TempDate
End Function

'----------------------------------------------------------------------
' Using numeric values for Month, Day, and Year, attempt to build a
' valid Date in mm/dd/yy format.
'----------------------------------------------------------------------
Private Function GetValidDateString(ByVal intMonth As Integer, ByVal intDay As Integer, ByVal intYear As Integer) As String
    Dim ReturnStr As String

    ReturnStr = ""

    If intMonth >= 1 And intMonth <= 12 Then
        Select Case intMonth
            Case 1, 3, 5, 7, 8, 10, 12
                ' January, March, May, July, August, October and December
                ' have 31 days.
                If intDay >= 1 And intDay <= 31 Then
                    ReturnStr = intMonth & "/" & intDay & "/" & intYear
                End If
            Case 4, 6, 9, 11
                ' April, June, September and November
                ' have 30 days
                If intDay >= 1 And intDay <= 30 Then
                    ReturnStr = intMonth & "/" & intDay & "/" & intYear
                End If
            Case 2
                ' Depending on whether it is a Leap Year (every four years),
                ' February may have 28 or 29 days.
                If intYear Mod 4 = 0 Then
                    If intDay >= 1 And intDay <= 29 Then
                        ReturnStr = intMonth & "/" & intDay & "/" & intYear
                    End If
                Else
                    If intDay >= 1 And intDay <= 28 Then
                        ReturnStr = intMonth & "/" & intDay & "/" & intYear
                    End If
                End If
        End Select
    End If

    ' Return the recombined string to the calling function.
    GetValidDateString = ReturnStr
End Function

显然仍然存在一些错误的余地,但我相信这将解决现在的问题。它并不完美,但希望我们能够很快摆脱这个VB6系统。感谢您提出的所有想法和建议。它们非常有助于缩小针对此特定实现的最佳解决方案。