有没有人知道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()
方法,或者我只是不得不将这些类型的用户输入值抛弃为无效/模糊?
答案 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系统。感谢您提出的所有想法和建议。它们非常有助于缩小针对此特定实现的最佳解决方案。