HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Function to check if a date is correct

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
checkfunctioncorrectdate

Problem

I have a method that checks if a date is correct or not, which returns a boolean if it is or not. In the method, I first check the format, then the date by using the function checkdate, then I check that time is of the format His.

/**
  * Function that checks the format, date, and time of a given timestamp.
  * @author : somar
  * @param string $date timestamp ex: 20161230154523
  * @return boolean resultat de check
  */
public function validateDate($date)
{
    if (preg_match("/^(((\d{4}((0[13578]|1[02])(0[1-9]|[12]\d|3[01])|(0[13456789]|1[012])(0[1-9]|[12]\d|30)|02(0[1-9]|1\d|2[0-8])))|((\d{2}[02468][048]|\d{2}[13579][26]))0229)){0,8}$/", substr($date, 0, 8))) {
        $formatCheck = true ;
    } else {
        $formatCheck = false ;
    }
    $dateCheck = checkdate(substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4));
    $timeCheck = substr($date, 8, 2) <= 23 && substr($date, 10, 2) <= 59 && substr($date, 12, 2) <= 59;
    if ($dateCheck == true && $timeCheck == true && $formatCheck == true) {
        return true;
    } else {
        return false;
    }
}


I want to improve the performance, by reducing the amount of function calls and by using less checking instructions. Moreover, PHP prefers to not use regex, and I don't know how a workaround.

Solution

The reason PHP dislikes the use of Regex is because some people don't know how to use it.
You, for example, don't.
Regex is for matching input, not for validation.
And so you'd use it to change say your date format to ISO 8601:

> $date = '19700101000000';
> preg_replace('/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', '$1-$2-$3T$4:$5:$6Z', $date);
=> "1970-01-01T00:00:00Z"


The regex is simple as we know the data should be there. Not that it's correct.

Your code is also long-winded, rather than manually checking if the code is alright make PHP do it for you with strptime.
You know the format the date is in, %Y%m%d%H%M%S, and so you can use it:

> strptime($date, '%Y%m%d%H%M%S');
=> {"tm_sec":0,"tm_min":0,"tm_hour":0,"tm_mday":1,"tm_mon":0,"tm_year":70,"tm_wday":4,"tm_yday":0,"unparsed":""}


And so you could change the function to just use:

/**
  * Function that checks the format, date, and time of a given timestamp.
  * @author : somar
  * @param string $date timestamp ex: 20161230154523
  * @return boolean resultat de check
  */
public function validateDate($date)
{
    return (bool)strptime($date, '%Y%m%d%H%M%S');
}


To note, strptime seems to have a bug with %S:

> strptime('19700101000070', '%Y%m%d%H%M%S');
=> {"tm_sec":7,"tm_min":0,"tm_hour":0,"tm_mday":1,"tm_mon":0,"tm_year":70,"tm_wday":4,"tm_yday":0,"unparsed":"0"}


To fix this you could change the function to take ISO 8601 dates, and have a function that converts to this format.

/**
  * Function that checks the format, date, and time of a given ISO 8601 timestamp.
  * @author : somar
  * @param string $date timestamp ex: 2016-12-30T15:45:23Z
  * @return boolean resultat de check
  */
public function validateDate($date)
{
    return (bool)strptime($date, '%Y-%m-%dT%H:%M:%SZ');
}

public function compactDateToISO($date)
{
    return preg_replace('/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', '$1-$2-$3T$4:$5:$6Z', $date);
}

Code Snippets

> $date = '19700101000000';
> preg_replace('/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', '$1-$2-$3T$4:$5:$6Z', $date);
=> "1970-01-01T00:00:00Z"
> strptime($date, '%Y%m%d%H%M%S');
=> {"tm_sec":0,"tm_min":0,"tm_hour":0,"tm_mday":1,"tm_mon":0,"tm_year":70,"tm_wday":4,"tm_yday":0,"unparsed":""}
/**
  * Function that checks the format, date, and time of a given timestamp.
  * @author : somar
  * @param string $date timestamp ex: 20161230154523
  * @return boolean resultat de check
  */
public function validateDate($date)
{
    return (bool)strptime($date, '%Y%m%d%H%M%S');
}
> strptime('19700101000070', '%Y%m%d%H%M%S');
=> {"tm_sec":7,"tm_min":0,"tm_hour":0,"tm_mday":1,"tm_mon":0,"tm_year":70,"tm_wday":4,"tm_yday":0,"unparsed":"0"}
/**
  * Function that checks the format, date, and time of a given ISO 8601 timestamp.
  * @author : somar
  * @param string $date timestamp ex: 2016-12-30T15:45:23Z
  * @return boolean resultat de check
  */
public function validateDate($date)
{
    return (bool)strptime($date, '%Y-%m-%dT%H:%M:%SZ');
}

public function compactDateToISO($date)
{
    return preg_replace('/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', '$1-$2-$3T$4:$5:$6Z', $date);
}

Context

StackExchange Code Review Q#155218, answer score: 5

Revisions (0)

No revisions yet.