PHP DateTime gives incorrect value

466 Views Asked by At

I wonder why this php code gives incorrect output value.

dd(new \DateTime("1397/02/29", new \DateTimeZone('Asia/Tehran')));

It outputs below object:

DateTime @-18076965944 {#1256 ▼
  date: 1397-03-01 00:00:00.0 Asia/Tehran (+03:25)
}

As you see the date is incorrect and must be 1397-02-01. The output for values 1397/02/30 && 1397/02/31 is incorrect also.

Can anyone help please. thanks.

3

There are 3 best solutions below

1
On BEST ANSWER

PHP store date object internal as struct https://github.com/php/php-src/blob/master/ext/date/php_date.h#L137 https://github.com/php/php-src/blob/master/ext/date/lib/timelib.h#L204

But DateTime init have no validating and only converts given date string to timestamp. https://github.com/php/php-src/blob/master/ext/date/php_date.c#L2647

Before creating date object you should check it using http://php.net/manual/en/function.checkdate.php

var_dump(
    checkdate(2,20,1000), // bool(true)
    checkdate(2,30,1000) // bool(false)
);
0
On

Thank you everybody for your responses.

As i was going to convert a Jalali date to a Gregorian date, i was trying to make a PHP DateTime object of my Jalali date string ("1397/02/29") and then convert the date object to the Gregorian date object using this package. I fixed the issue by directly converting my Jalali date string to what i want using morilog/jalali like below:

$jalali_date = explode("/", request()->to);

$gregorian_date_time = \jDateTime::toGregorianDate($jalali_date[0], $jalali_date[1], $jalali_date[2])->setTime(23, 55)->format("Y-m-d H:i");
return $gregorian_date_time;

Thank you all again.

0
On

The DateTime leap year code applies the Gregorian calendar rules, and they do not work for the Persian calendar.

The "divide by 4 but not 100 except 400" rule is not valid for Persian calendar, which follows a different algorithm:

https://www.timeanddate.com/date/iran-leap-year.html

Basically, you cannot use DateTime for Persian dates. See also here. You might perhaps adapt some other code.

Update: actually, it appears different calendars and sources do not agree on leap years. Jalali has 1397 as a leap year but Persian calendar does not?