skip to Main Content

Why does the following code return 12-2023? It should be 11-2023, right?

$datetime = DateTime::createFromFormat('m-y', '11-23');
echo $datetime->format('m-Y');

This only happens when I run it on the 31st day of a month, like October 31st or December 31st. It seems that when we provide ’11/23′ as the date, and today is October 31st, PHP interprets it as November 1st. When today is December 31st, it interprets it as January 1st of the following year.

So 11-23 will be intepreted as 31-11-23, and below code will return as 01-12-2023:

$datetime = DateTime::createFromFormat('d-m-y', '31-11-23');
echo $datetime->format('d-m-Y');

I want to use this code to parse the month and year from a credit/debit card. How can I safely parse the month using PHP?

I also tried

echo date('m-Y',strtotime("10-23"));

But it returned 01-1970.

Do I really need to prepend the input string with the date? For example, if the input is ’11-23,’ do I need to add ’01-‘ in front of it to make it work with DateTime::createFromFormat?

2

Answers


  1. When you feed it with incomplete dates, PHP fills the gaps with current date/time. When that creates an invalid date, PHP helpfully "fixes" it for you.

    At the time of writing, it’s 31st October. But November only has 30 days, so it moves forward to next month.

    $datetime = DateTime::createFromFormat('m-y', '11-23');
    $now = new DateTime();
    var_dump($datetime, $now)
    
    object(DateTime)#1 (3) {
      ["date"]=>
      string(26) "2023-12-01 09:48:48.000000"
      ["timezone_type"]=>
      int(3)
      ["timezone"]=>
      string(16) "Europe/Amsterdam"
    }
    object(DateTime)#2 (3) {
      ["date"]=>
      string(26) "2023-10-31 09:48:48.010803"
      ["timezone_type"]=>
      int(3)
      ["timezone"]=>
      string(16) "Europe/Amsterdam"
    }
    

    To answer your question, yes, you have to specify a specific day of month (and even time) if you don’t want it to be populated dinaymically (and potentially wrong).

    Login or Signup to reply.
  2. Just prepend a ! or | to the format string

    DateTime::createFromFormat('!m-y', '11-23');
    

    Explanation in the document:

    If format does not contain the character ! then portions of the
    generated date/time which are not specified in format will be set to
    the current system time.

    If format contains the character !, then portions of the generated
    date/time not provided in format, as well as values to the left-hand
    side of the !, will be set to corresponding values from the Unix
    epoch.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search