Jump to content
Sign in to follow this  
mrider

Is it time to update/refactor _DateIsValid in Date.au3?

Recommended Posts

mrider

Greetings - first a bit of background:

I am updating some code of my own where a user has to deal with a datetime in UTC format - namely yyyy-MM-ddTHH:mm:ss.SSS (using the definitions of the characters from Java's SimpleDateFormat).  I had two requirements that caused me to not use _DateIsValid:  1) I have to do an incremental log of what is wrong in the event there is a problem, and 2) It has to include milliseconds.

_DateIsValid does neither.

So I thought - no problem, I'll just see how that code works and modify it for my own use.  When I got there, I couldn't help but wonder if it couldn't be improved.  Almost certainly that version was written with a much older version of AutoIt without some of the modern conveniences we now love.  So I whipped up the version you see below - and I'm wondering if it is worthwhile to push this into the include instead of the current version.  You'll note that I left the leading underbar off the function name so that I could test this along side the current version:

#include <Date.au3>
; Obviously the previous line isn't needed if this code makes it into the include...

; Don't forget to change the function name to _DateIsValid...
Func DateIsValid($sDate)
    Local $iDateLen = StringLen($sDate)
    Local $sPattern
    Switch $iDateLen
        Case 10
            ; 'yyyy-MM-dd'
            $sPattern = "(\d{4})[-/.](\d{2})[-/.](\d{2})"
        Case 16
            ; 'yyyy-MM-dd HH:mm'
            $sPattern = "(\d{4})[-/.](\d{2})[-/.](\d{2})[ T](\d{2}):(\d{2})"
        Case 19
            ; 'yyyy-MM-dd HH:mm:ss'
            $sPattern = "(\d{4})[-/.](\d{2})[-/.](\d{2})[ T](\d{2}):(\d{2}):(\d{2})"
        Case 23
            ; 'yyyy-MM-dd HH:mm:ss.SSS'
            $sPattern = "(\d{4})[-/.](\d{2})[-/.](\d{2})[ T](\d{2}):(\d{2}):(\d{2})\.(\d{3})"
        Case Else
            ; Length is wrong, can't possibly be a date
            Return False
    EndSwitch
    Local $aiMatches = StringRegExp($sDate, $sPattern, 1)
    If @error Then
        ; Does not match RE, so it's invalid format
        Return False
    Else
        ; At this point we KNOW we have a year, month and day
        If $aiMatches[0] < 1000 Or $aiMatches[0] > 2999 Then Return False   ; year
        If $aiMatches[1] < 1 Or $aiMatches[1] > 12 Then Return False        ; month
         ; If we're here, then year and month are both valid so we can use them immediately
        $aiDaysInMonth = _DaysInMonth($aiMatches[0])
        If $aiMatches[2] < 1 Or $aiMatches[2] > $aiDaysInMonth[$aiMatches[1]] Then Return False ; day

        ; We may or may not have have hours and minutes
        If $iDateLen > 10 Then
            If $aiMatches[3] > 23 Then Return False ; hour
            If $aiMatches[4] > 59 Then Return False ; minute
            ; We may or may not have seconds or milliseconds
            If $iDateLen > 16 Then
                If $aiMatches[5] > 59 Then Return False ; seconds
                ; No point in testing milliseconds, since we know it's 3 digits...
            EndIf
        EndIf
    EndIf
    Return True
EndFunc

In addition to that, I cooked up some tests of both good and bad data and then tested for both speed and correctness.  Both pass the correctness tests.  I didn't doubt for a minute that the current version would pass, but I wanted to make sure the new algorithm had the same behavior as the old algorithm.  So far as speed goes - the new version is about 25% faster with valid dates, and a whopping 50% faster at recognizing bad dates.

Here are the tests that I used:

#include <Date.au3>

; test data
Local $timer
Local $good[15] = [ _
    '2014-02-28', '2014/02/28', '2014.02.28', _
    '2014-02-28 12:15', '2014/02/28 12:15', '2014.02.28 12:15', _
    '2014-02-28T12:15', '2014/02/28T12:15', '2014.02.28T12:15', _
    '2014-02-28 12:15:15', '2014/02/28 12:15:15', '2014.02.28 12:15:15', _
    '2014-02-28T12:15:15', '2014/02/28T12:15:15', '2014.02.28T12:15:15' _
]
Local $bad[15] = [ _
    '2014x02x28', '2014/02/30', '2014.13.28', _
    '0014-02-28 12:15', '2014/00/28 12:15', '2014.02.28 25:15', _
    '2014-02-28R12:15', '2014/02/28T12:65', '2014.02.28T12.15', _
    '2014-02-28 12:15:75', '2014/02/28 12:1x:15', '2014.02.28 12:15:', _
    '2014-02-28_12:15:15', 'Foo', '2014.02.28T99999999' _
]
; test data ends

; Speed tests
$timer = TimerInit()
For $i = 1 To 1000
    For $j = 0 To UBound($good) - 1
        _DateIsValid($good[$j])
    Next
Next
ConsoleWrite("Current good:" & @TAB & TimerDiff($timer) & @LF)
$timer = TimerInit()
For $i = 1 To 1000
    For $j = 0 To UBound($good) - 1
        DateIsValid($good[$j])
    Next
Next
ConsoleWrite("New good:" & @TAB & TimerDiff($timer) & @LF)

$timer = TimerInit()
For $i = 1 To 1000
    For $j = 0 To UBound($bad) - 1
        _DateIsValid($bad[$j])
    Next
Next
ConsoleWrite("Current bad:" & @TAB & TimerDiff($timer) & @LF)
$timer = TimerInit()
For $i = 0 To 1000
    For $j = 0 To UBound($bad) - 1
        DateIsValid($bad[$j])
    Next
Next
ConsoleWrite("New bad:" & @TAB & TimerDiff($timer) & @LF)
$timer = TimerInit()

; Correctness tests
For $i = 0 to UBound($good) - 1
    If Not _DateIsValid($good[$i]) Then
        ConsoleWriteError("_DateIsValid incorrectly flagged " & $good[$i] & " as a bad date" & @LF)
    EndIf
    If Not DateIsValid($good[$i]) Then
        ConsoleWriteError("DateIsValid incorrectly flagged " & $good[$i] & " as a bad date" & @LF)
    EndIf
Next
For $i = 0 to UBound($bad) - 1
    If _DateIsValid($bad[$i]) Then
        ConsoleWriteError("_DateIsValid incorrectly flagged " & $bad[$i] & " as a good date" & @LF)
    EndIf
    If DateIsValid($bad[$i]) Then
        ConsoleWriteError("DateIsValid incorrectly flagged " & $bad[$i] & " as a good date" & @LF)
    EndIf
Next
; Correctness tests end

I hereby release this code under the terms of the WTFPL (http://en.wikipedia.org/wiki/WTFPL) should you decide that the version I wrote is worthy of inclusion in Date.au3 .

[EDIT] OOPS! I didn't realize that I pasted a version with a bug that I had since corrected.  I guess my Ctrl + C didn't work the second time... :oops:

Edited by mrider

How's my riding? Dial 1-800-Wait-There

Trying to use a computer with McAfee installed is like trying to read a book at a rock concert.

Share this post


Link to post
Share on other sites
guinness

This is the regular expression I came up with sometime ago.

(?x)^\d{4}(?:[.\-/]\d{2}){2}   (?:     (?:T|\h)\d{2}:\d{2}     (?::\d{2})?     )?$

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Share this post


Link to post
Share on other sites
mrider

I kind of liked the switch by length version since 1) we get a much less complicated regex, and 2) the switch inherently tests for string length without invoking the regex, and 3) it's much clearer what we're testing with the regex.

However, I'm totally willing to release this into the wild without even acknowledgement, so feel free to modify it if it looks better. :)

[EDIT] I didn't realize that sticking "B" and ")" together produced this -> B)

Edited by mrider

How's my riding? Dial 1-800-Wait-There

Trying to use a computer with McAfee installed is like trying to read a book at a rock concert.

Share this post


Link to post
Share on other sites
guinness

A couple of comments would alleviate the regexp understanding issue. You can make a Trac request if you feel this should be added to the UDFs.


UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Share this post


Link to post
Share on other sites
mrider

Well - this will be my 89th post when I'm done, despite having created my account years ago.  So I'm kind of soliciting the opinions of others before I add this to Trac, seeing as how I don't have any "street cred" (for want of a better term). :)

[EDIT]

I should also add that your regex correctly identifies the pattern of characters, but it does not capture the digits.  So one would have to take additional steps to check e.g.: '2014-12-29'.

Local $sPattern = '(?x)^d{4}(?:[.-/]d{2}){2}   (?:     (?:T|h)d{2}:d{2}     (?::d{2})?     )?$'

Local $sDate = '2014-02-28'

Local $aMatches = StringRegExp($sDate, $sPattern, 1) ; '3' also produces the same result

ConsoleWrite(UBound($aMatches) & @LF)

Writes out "1"

Edited by mrider

How's my riding? Dial 1-800-Wait-There

Trying to use a computer with McAfee installed is like trying to read a book at a rock concert.

Share this post


Link to post
Share on other sites
guinness

My regexp is just to check, I didn't add any capturing groups.


UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Share this post


Link to post
Share on other sites
mrider

Well, it took me a while to cook up a regex that would validate, capture, and add the ability to test milliseconds all on one line.  I used the following (which may not be optimal):

(?x)^(\d{4})[-/.](\d{2})[-/.](\d{2})  (?:   (?:T|\h)(\d{2}):(\d{2})   (?::(\d{2})  (?:\.(\d{3}))? )?  )?$

Using that versus the one that I wrote I got the following timings (where "complex" means the complex regex) on my admittedly underpowered computer:

Current good:    1134.98372218279
Complex good:    884.724858009665
Simple good:    840.117068884218

Current bad:    877.502325158039
Complex bad:    538.502495566972
Simple bad:    453.490679863207
 

So my version is a bit faster, but your regex is all together in one line...

Edited by mrider

How's my riding? Dial 1-800-Wait-There

Trying to use a computer with McAfee installed is like trying to read a book at a rock concert.

Share this post


Link to post
Share on other sites
guinness

You should have asked. I would have added capturing for you as well. 

Cheers for testing by the way. I am hoping people will join in the discussion as well and it just won't be you vs me.


UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Share this post


Link to post
Share on other sites
mrider

You should have asked. I would have added capturing for you as well. 

Cheers for testing by the way. I am hoping people will join in the discussion as well and it just won't be you vs me.

 

I didn't mind adding the capturing.  I don't use regular expressions as often as I would like, so it was good practice.  [EDIT] I should add that what kept tripping me up was that I had to make sure the milliseconds were non-greedy, otherwise the regex would fail on yyyy-MM-dd?HH:mm:ss .  Not quite sure I understand that one.

I also hope others will chime in with some opinions.  For one thing, it wouldn't surprise me in the least to have someone come up with even better code still.  BTW, here's the latest version with the more complex but all-in-one regex:

#include <Date.au3>
; Obviously the previous line isn't needed if this code makes it into the include...

; Don't forget to change the function name to _DateIsValid...
Func DateIsValid($sDate)
    Local $iDateLen = StringLen($sDate)
    Local $sPattern = '(?x)^(\d{4})[-/.](\d{2})[-/.](\d{2})  (?:   (?:T|\h)(\d{2}):(\d{2})   (?::(\d{2})  (?:\.(\d{3}))? )?  )?$'
    Local $aiMatches = StringRegExp($sDate, $sPattern, 1)
    If @error Then
        ; Does not match RE, so it's invalid format
        Return False
    Else
        ; At this point we KNOW we have a year, month and day
        If $aiMatches[0] < 1000 Or $aiMatches[0] > 2999 Then Return False   ; year
        If $aiMatches[1] < 1 Or $aiMatches[1] > 12 Then Return False        ; month
         ; If we're here, then year and month are both valid so we can use them immediately
        $aiDaysInMonth = _DaysInMonth($aiMatches[0])
        If $aiMatches[2] < 1 Or $aiMatches[2] > $aiDaysInMonth[$aiMatches[1]] Then Return False ; day

        ; We may or may not have have hours and minutes
        If $iDateLen > 10 Then
            If $aiMatches[3] > 23 Then Return False ; hour
            If $aiMatches[4] > 59 Then Return False ; minute
            ; We may or may not have seconds or milliseconds
            If $iDateLen > 16 Then
                If $aiMatches[5] > 59 Then Return False ; seconds
                ; No point in testing milliseconds, since we know it's 3 digits...
            EndIf
        EndIf
    EndIf
    Return True
EndFunc
Edited by mrider

How's my riding? Dial 1-800-Wait-There

Trying to use a computer with McAfee installed is like trying to read a book at a rock concert.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.