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
How to Get Info on Sent PHP Curl Request
Check If String Contains Word in Array
How to Use File_Get_Contents() to Compare Two Files
Codeigniter Model Error: Undefined Property
Making a Http Get Request with Http-Basic Authentication
Best Way to Autoload Classes in PHP
PHP - Time Remaining Until Specific Time from Current Time of Page Load
PHP Soap Client That Understands Multi-Part Messages
How to Store JavaScript Variable Output into a PHP Variable
How to Declare a Method Static and Nonstatic in PHP
Laravel Pluck Fields from Relations
How to? Form Post to Multiple Locations
Sort an Array with Special Characters in PHP
Connection Reset by Peer: Mod_Fcgid: Error Reading Data from Fastcgi Server