getTimestamp没有给出正确的小时

I have this PHP code:

$from_date = new DateTime('April-22-2016');
$from_date->format( 'Y-m-d 00:00:00' );
$from_date->setTime(0,0,0);
print ' / '. $from_date_unix = $from_date->getTimestamp();

The above code prints a Unix timestamp of 1461356160, which means GMT: Fri, 22 Apr 2016 20:16:00 GMT

The hours are 20:16:00 - which is strange, since I already set the time to 00:00:00 via

  $from_date->setTime(0,0,0);

Is my code wrong? Do I need to check something in php.ini?

The date you provided as first argument to DateTime::__construct() does not use any of the standard date and time formats understood by PHP. Therefore, it tries to identify the date and time components in the string you provided.

A print_r($from_date) immediately after it was created reveals what PHP (mis-)understood from your date:

DateTime Object
(
    [date] => 2016-04-22 00:00:00.000000
    [timezone_type] => 1
    [timezone] => -20:16
)

Before anything else, when it starts parsing a string for date & time, PHP initialize the new DateTime object with the current date, time and timezone. Then it overwrites the components it identifies in your string as follows:

  • April was correctly identified as the month name;
  • 22 is the day of the month;
  • for some reason I don't know now, it set the time of the new object to 00:00:00;
  • the rest of the string (-2016) was used as timezone offset; i.e. -20:16 hours.

Maybe the way it works sounds silly to you but since you provided it a random string, this is the best it could get out of it.

The next line of your code ($from_date->format( 'Y-m-d 00:00:00' );) produces a string and doesn't modify the DateTime object. Because you don't do anything with the string returned by DateTime::format(), the entire line is a no-op.

The next line ($from_date->setTime(0,0,0);) also doesn't have any effect on $from_date because it's time already is 00:00:00.

Now it's clear why $from_date->getTimestamp() returns the time 20:16 GMT: when it's 00:00 at the timezone with offset -20:16, on the GMT timezone there already is 20:16.


In order to get what you want you need to use the DateTime::createFromFormat() static function:

$from_date = DateTime::createFromFormat(
    '!F-d-Y',
    'April-22-2016',
    new DateTimeZone('GMT')
);
print ' / '. $from_date_unix = $from_date->getTimestamp();

Remark the exclamation mark (!) at the start of the format specifier. It tells PHP to reset all the date and time components to the Unix Epoch. This way the generated date already has the time 00:00:00 and there is no need to set it.

Its output is:

1461283200

You can parse the DateTime object with the right format with DateTime::createFromFormat

Use it like this:

$from_date = DateTime::createFromFormat('!F-d-Y', 'April-22-2016');
$from_date->format( 'Y-m-d 00:00:00' );
print ' / '. $from_date_unix = $from_date->getTimestamp();