PHP Datetime Createfromformat Functionality

php DateTime createFromFormat functionality

The thing about DateTime::createFromFormat is that there are two kinds of unexpected input it recognizes: the kind that generates errors, and the kind that generates warnings.

Input such as '56/56/fail' produces an error, so false is returned and everything is good. However, '56/56/2012' gives not an error but a warning, and is actually parsed as the 56th day of the 56th month of 2012. Since 2012 does not have 56 months, PHP internally changes this to 2016 + 8 months = Aug 2016. And since that month does not have 56 days, we have another compensation to Sep 2016 + (56 - 31) days = 25 Sep 2016. So while unexpected, this is in fact correct.

If you want to disallow this automatic adjustment, you have to wrap the DateTime factory method and use DateTime::getLastErrors as reference:

$dateTime = DateTime::createFromFormat('d/m/Y', '56/56/2012');
$errors = DateTime::getLastErrors();
if (!empty($errors['warning_count'])) {
echo "Strictly speaking, that date was invalid!\n";
}

See it in action.

PHP DateTime CreateFromFormat Issue

It's because you're not supplying a day, so it's using the current day by default. Current day is 31, but September only has 30 days, so it skips to October 1st.

Look at this example:

function validateDate($date, $format = 'm-Y') {
$d = DateTime::createFromFormat($format, $date);
echo $d->format("d-".$format); // added the day for debugging
return $d && $d->format($format) == $date;
}
var_dump(validateDate('08-2017', 'm-Y')); // 31-08-2017, true
var_dump(validateDate('09-2017', 'm-Y')); // 01-10-2017, there's no 31-09-2017, false

function was copied from this answer or php.net

This is a little rudimentary, but you can detect if there's no d in the format and manually set it to 1 to avoid this:

<?php
function validateDate($date, $format = 'm-Y') {
if (strpos($format, "d") === false) {
$format = "d ".$format;
$date = "01 ".$date;
}
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) === $date;
}
var_dump(validateDate('08-2017', 'm-Y')); // 31-08-2017, true
var_dump(validateDate('09-2017', 'm-Y')); // 01-09-2017, true

date_create_from_format AND DateTime::createFromFormat functions breaking on Server

From your comment: Your PHP Version ist 5.2.17

but DateTime::createFromFormat is avaible since PHP 5.3

Look at the doc: http://php.net/manual/en/datetime.createfromformat.php

PHP DateTime::createFromFormat behavoiur

By default, PHP will populate missing date values with those of the current date/time; so

$date = \DateTime::createFromFormat('m/Y', '02/2017');

will populate the missing day value with the current date; and as 31st February is an invalid date, it will roll forward into March. Likewise, hours/minutes/seconds will be populated with the missing time values based on the current time.

If you want to force the behaviour of forcing to the beginning of the month/time, then modify your mask with a leading !

$date = \DateTime::createFromFormat('!m/Y', '02/2017');

This will populate the missing day with the 1st of the month, and the time with 00:00:00

Alternatively, a trailing | will have the same effect

$date = \DateTime::createFromFormat('m/Y|', '02/2017');

php dateTime::createFromFormat in 5.2?

just include the next code

function DEFINE_date_create_from_format()
{

function date_create_from_format( $dformat, $dvalue )
{

$schedule = $dvalue;
$schedule_format = str_replace(array('Y','m','d', 'H', 'i','a'),array('%Y','%m','%d', '%I', '%M', '%p' ) ,$dformat);
// %Y, %m and %d correspond to date()'s Y m and d.
// %I corresponds to H, %M to i and %p to a
$ugly = strptime($schedule, $schedule_format);
$ymd = sprintf(
// This is a format string that takes six total decimal
// arguments, then left-pads them with zeros to either
// 4 or 2 characters, as needed
'%04d-%02d-%02d %02d:%02d:%02d',
$ugly['tm_year'] + 1900, // This will be "111", so we need to add 1900.
$ugly['tm_mon'] + 1, // This will be the month minus one, so we add one.
$ugly['tm_mday'],
$ugly['tm_hour'],
$ugly['tm_min'],
$ugly['tm_sec']
);
$new_schedule = new DateTime($ymd);

return $new_schedule;
}
}

if( !function_exists("date_create_from_format") )
DEFINE_date_create_from_format();

Using DateTime::createFromFormat() without rolling the (wrong) date

I'm not sure it's possible to disable this feature, but you can check if this happened:

$date = \DateTimeImmutable::createFromFormat($format, $dateString);

if(!$date || ($date->format($format) !== $dateString)) {
throw new InvalidDateException($dateString);
}

What we're doing here is checking the provided date string against the date that was created from that date string, this will indicate to us whether the 'rollover', as you put it, has happened.

This will need some adaption to work for your codebase but hopefully, that gives you some general approach to start working with?

PHP DateTime::createFromFormat() returns wrong year

$date = DateTime::createFromFormat('Y-m-d\TH:i:s.u\Z', '2015-08-30T07:56:28.000Z')->format('Y-m-d');

i is used for minutes, and s for seconds. m is for months. Therefore your string is being interpreted incorrectly.

For the correct format characters to use, see http://php.net/manual/en/datetime.createfromformat.php

Use DateTime::createFromFormat to get the + 1 day (Next Date)

Use DateTime::modify method:

$sdate = DateTime::createFromFormat('d/m/Y', '04/05/2014');
echo $sdate->modify('+1 day')->format('Y-m-d');


Related Topics



Leave a reply



Submit