diff --git a/core/lib/Drupal/Component/Datetime/DateTimePlus.php b/core/lib/Drupal/Component/Datetime/DateTimePlus.php index 56bd92f..3a9b386 100644 --- a/core/lib/Drupal/Component/Datetime/DateTimePlus.php +++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php @@ -226,18 +226,26 @@ public static function createFromFormat($format, $time, $timezone = NULL, $setti // re-creating the date/time formatted string and comparing it to the input. For // instance, an input value of '11' using a format of Y (4 digits) gets // created as '0011' instead of '2011'. - if ($date instanceof DateTimePlus) { - $test_time = $date->format($format, $settings); - } - elseif ($date instanceof \DateTime) { - $test_time = $date->format($format); - } - $datetimeplus->setTimestamp($date->getTimestamp()); - $datetimeplus->setTimezone($date->getTimezone()); + $test_time = $date->format($format); if ($settings['validate_format'] && $test_time != $time) { throw new \Exception('The created date does not match the input value.'); } + + // We now know we have a valid date. We build up the internal \DateTime + // object without going through a Unix timestamp by using the individual + // parts of the date. + $parts = date_parse($date->format(static::FORMAT)); + + // If the 'U' format is specified, then the time zone parameter is + // ignored, and we need to explicitly set the internal timezone to UTC + // before setting the individual parts. + // @see http://php.net/manual/en/datetime.createfromformat.php + if ($format === 'U') { + $datetimeplus->setTimezone(new \DateTimeZone('UTC')); + } + $datetimeplus->setDate($parts['year'], $parts['month'], $parts['day']) + ->setTime($parts['hour'], $parts['minute'], $parts['second']); } return $datetimeplus; } diff --git a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php index b8be130..fc19a13 100644 --- a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php +++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php @@ -303,6 +303,10 @@ public function providerTestDates() { array('2009-03-07 10:30', 'Australia/Canberra', '2009-03-07T10:30:00+11:00'), // Same during daylight savings time. array('2009-06-07 10:30', 'Australia/Canberra', '2009-06-07T10:30:00+10:00'), + // Create a date object in the distant past. + array('1809-02-12 10:30', 'America/Chicago', '1809-02-12T10:30:00-06:00'), + // Create a date object in the far future. + array('2345-01-02 02:04', 'UTC', '2345-01-02T02:04:00+00:00'), ); } @@ -326,6 +330,10 @@ public function providerTestDateArrays() { array(array('year' => 2010, 'month' => 2, 'day' => 28), 'Europe/Berlin', '2010-02-28T00:00:00+01:00'), // Create date object from date array with hour. array(array('year' => 2010, 'month' => 2, 'day' => 28, 'hour' => 10), 'Europe/Berlin', '2010-02-28T10:00:00+01:00'), + // Create a date object in the distant past. + array(array('year' => 1809, 'month' => 2, 'day' => 12), 'America/Chicago', '1809-02-12T00:00:00-06:00'), + // Create a date object in the far future. + array(array('year' => 2345, 'month' => 1, 'day' => 2), 'UTC', '2345-01-02T00:00:00+00:00'), ); }