skip to Main Content

Following code doesn’t returns correct response

DateTime::createFromFormat('Ymd', '19992323')

returns:

date: 2000-11-23 10:01:41.000000
timezone_type: 3
timezone: America/Toronto

I was expecting it to return false. Please suggest

2

Answers


  1. The m format allows number superior than 12 (php.net).

    m: 01 through 12 or 1 through 12. (2 digit numbers higher than 12 are accepted, in which case they will make the year overflow. For example using 13 means January in the next year)

    That’s what happening with your date which overflows to the next year.

    Example:

    DateTime::createFromFormat('Ymd', '19991223')
    //Expected date: 1999-12-23
    
    DateTime::createFromFormat('Ymd', '19991323')
    //Overflow to next year: 2000-01-23
    
    DateTime::createFromFormat('Ymd', '19991423')
    //Overflow to next year: 2000-02-23
    
    Login or Signup to reply.
  2. PHP’s DateTime functions and class methods are somewhat forgiving and are not meant to be used for strict validation. However, given you just have a simple year, month, and day smashed together, it is trivial to write a validation function:

    $inputDateString = '19992323';
    
    $date = DateTime::createFromFormat(
        'Ymd',
        filter_var(
            $inputDateString,
            FILTER_CALLBACK,
            [
                'options' => function($date) {
                    // Does the input string have the correct date format?
                    if(!preg_match('/^(?<Y>[0-9]{4})(?<m>[0-9]{2})(?<d>[0-9]{2})$/', $date, $parts)) {
                        return false;
                    }
                    // Is the year within a given range?
                    // Current range is between 0 and the current server year.
                    if(
                        !filter_var(
                            $parts['Y'],
                            FILTER_VALIDATE_INT,
                            [
                                'options' => [
                                    // Minimum year
                                    'min_range' => 0,
                                    // Maximum year
                                    'max_range' => date('Y')
                                ]
                            ]
                        )
                    ) {
                        return false;
                    }
                    // Is the month between 1 and 12?
                    if(
                        !filter_var(
                            $parts['m'],
                            FILTER_VALIDATE_INT,
                            [
                                'options' => [
                                    // January
                                    'min_range' => 1,
                                    // December
                                    'max_range' => 12
                                ]
                            ]
                        )
                    ) {
                        return false;
                    }
                    $lastDayOfMonth =
                        (DateTime::createFromFormat('Ymd', $parts['Y'] . $parts['m'] . '01'))
                            ->modify('last day of this month');
                    // Is the day between 1 and the last day of the
                    //     given month and year?
                    if(
                        !filter_var(
                            $parts['d'],
                            FILTER_VALIDATE_INT,
                            [
                                'options' => [
                                    // First day of month
                                    'min_range' => 1,
                                    // Last day of month
                                    'max_range' => $lastDayOfMonth->format('d')
                                ]
                            ]
                        )
                    ) {
                        return false;
                    }
                    return $date;
                }
            ]
        )
    );
    
    var_dump($date); // $date is false since month is greater than 12
    // $date would be a DateTime object if the input date string were valid.
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search