Search code examples
phpdatedate-conversion

Wrong Date Conversation (ndY to Y-m-d H:i:s)


My code is returning the wrong date conversation

<?php
$date = '8312015';
$newDate = DateTime::createFromFormat('ndY', $date);
$convertedDate = $newDate->format('Y-m-d H:i:s');
echo $convertedDate;

Returns

0021-11-12 17:04:56

Expects:

2015-08-31 00:00:00

Questions:

  1. Why PHP can't convert ndY to Y-m-d H:i:s
  2. Why PHP append the current hours, instead of 00:00:00

Note: I tried with date(), date_create, date_format and I got same results (wrong date)


Solution

  • So close! m is actually :

    Numeric representation of a month, with leading zeros 01 through 12

    (http://php.net/manual/en/function.date.php)

    So, that means it expects it to be 2 characters, not one. If you do

    $date = '08312015';
    $newDate = DateTime::createFromFormat('ndY', $date);
    

    It works how you want it to

    When you do

    $date = '8312015';
    $newDate = DateTime::createFromFormat('ndY', $date);
    

    You get month=83, day=12, year=015

    83 months is 6 years+ 11 months so, 015+6=21 years +11 months=november 11th of year 21, ie (0021-11-12), which matches the output

    Edit: so apparantly you meant n not m, the problem being that you have no delimiter between date parts, so, as has been said, it is ambiguous as to whether the month should be 8 or 83...

    Edit Again My "answer" just explained the problem I guess without showing how to fix it, so...

    If the fields are not delimited either by a delimiting character (like a -) or by field length (ie, how m is always 2 characters) then the conversion is ambiguous. Given that apparantly php considers 83 a valid month, and that a month formatted as n may have 1 or more digits, when php sees 83, it really can't know if you mean "8th month and then something starting with a 3" or "the 83rd month".

    So, what you need to do is disambiguate the delimiting. One way to disambiguate is to pad with 0s on the left, since d (and for all intents and purposes Y) are always the same amount of digits (2 and 4, respectively)

    So, $date=str_pad($date, 8, "0", STR_PAD_LEFT); would turn 8312015 into 08312015, and then you could use m to format instead of n, and you should be OK from there. For months > 9, it would not change the input string, so it would be safe for all strings in that ndY format.