KNOWLEDGE BASE
Log In    |    Knowledge Base    |    4D Home
Tech Tip: Date validation in multiple formats
PRODUCT: 4D | VERSION: 15.x | PLATFORM: Mac & Win
Published On: November 28, 2016

Dates can be introduced to a 4D database in numerous formats . Add to the challenge is accounting for leap years. Formates can be any of the following...

MM/DD/YYYY, MM-DD-YYYY, MM.DD.YYYY
DD/MM/YYYY, DD-MM-YYYY, DD.MM.YYYY
YYYY/MM/DD, YYYY-MM-DD, YYYY.MM.DD

The method included below uses the 4D command Match regex to return True or False regarding validity of the date submitted. The date can be contained within a string or not. Format number 3 should be used to validate date strings in the formate of ISO Date (2006-12-29T00:00:00) and ISO Date GMT (2010-09-13T16:11:53Z).

The RegEx patterns not only account for date format they also account for leap years.

If (True)
    If (False)
       Begin SQL
         /*
         Name: RGX_ValidDate
         Path: RGX_ValidDate
        
         Purpose: Validate a date in string format including leap years
      
         $0 - BOOL - True if valid date
         $1 - TEXT - Date string
         $2- LONG - Date format 1 (MM/DD/YYYY) = DEFAULT, 2 (DD/MM/YYYY), 3 (YYYY/MM/DD)
       */
       End SQL
    End if
    //===================== Declare Variables ==================================
    //method_parameters_declarations
    C_BOOLEAN($0;$Found_B)
    C_TEXT($Date_T;$1)
    C_LONGINT($Format_L;$2)
    //--------------------------------------------------------------------------
    //local_variable_declarations
    C_LONGINT($End_L;$Params_L)
    C_TEXT($RgxPat_T)
End if
//====================== Initialize and Setup ================================

$Params_L:=Count parameters
$Found_B:=False

If ($Params_L>=1)
    $Date_T:=$1
    If ($Params_L>1)
       If ($2<=3)
          $Format_L:=$2
       Else
          $Format_L:=1
       End if
    Else
       $Format_L:=1
    End if
   
    //======================== Method Actions ==================================
   
    Case of
       : ($Format_L=1) // MM/DD/YYYY
          $RgxPat_T:="((0[13578]|1[02])[\\/|\\-|\\.](0[1-9]|[12][0-9]|3[01])[(\\/|\\-|\\.](18|19|20)[0-9]{2})|((0[469]|11)[\\/|\\-|\\.](0[1-9]|[12][0-9]|30)[(\\/|\\-|\\.](18|19|20)[0-9]{2})|((02)[(\\/|\\-|\\.](0[1-9]|1[0-9]|2[0-8])[(\\/|\\-|\\.](18|19|20)[0-9]{2})|((02)[(\\/|\\-|\\.]29[(\\/|\\-|"+"\\.](((18|19|20)(04|08|[2468][048]|[13579][26])"+")|2000))"
   
       : ($Format_L=2) // DD/MM/YYYY
          $RgxPat_T:="(?:(?:31(\\/|\\-|\\.)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/|\\-|\\.)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})|(?:29(\\/|\\-|\\.)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))|(?:0?[1-9]|1\\d|2["+"0-8"+"])(\\/|\\-|\\.)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})"
   
       Else // YYYY/MM/DD
          $RgxPat_T:="((18|19|20)[0-9]{2}[\\/|\\-|\\.](0[13578]|1[02])[\\/|\\-|\\.](0[1-9]|[12][0-9]|3[01]))|(18|19|20)[0-9]{2}[\\-.](0[469]|11)[\\/|\\-|\\.](0[1-9]|[12][0-9]|30)|(18|19|20)[0-9]{2}[\\/|\\-|\\.](02)[\\/|\\-|\\.](0[1-9]|1[0-9]|2[0-8])|(((18|19|20)(04|08|[2468][048]|[13579]["+"26]))|2000)[\\/|\\-|\\.](02)[\\/|\\-|\\.]29"
   
    End case
   
    //======================== Clean up and Exit =================================
   
    $Found_B:=Match regex($RgxPat_T;$Date_T;1)
   
End if

$0:=$Found_B