From 0aaf232bc9e919cf8f968cb27f3e5291d3b8418a Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Tue, 16 Feb 2016 22:45:51 +0100 Subject: [PATCH] Fixing bug in the Date::parseDate() method When using a different timezone it would return different dates because of the timezone changes. --- src/Database/Type/DateType.php | 16 ---------------- src/I18n/DateFormatTrait.php | 20 ++++++++++++++++++-- tests/TestCase/I18n/DateTest.php | 15 +++++++++++++++ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/Database/Type/DateType.php b/src/Database/Type/DateType.php index 11bc441ee35..25ddc5209b4 100644 --- a/src/Database/Type/DateType.php +++ b/src/Database/Type/DateType.php @@ -99,20 +99,4 @@ protected function _parseValue($value) $class = $this->_className; return $class::parseDate($value, $this->_localeFormat); } - - /** - * Test that toImmutable changes all the methods to create frozen time instances. - * - * @return void - */ - public function testToImmutableAndToMutable() - { - $this->type->useImmutable(); - $this->assertInstanceOf('DateTimeImmutable', $this->type->marshal('2015-11-01')); - $this->assertInstanceOf('DateTimeImmutable', $this->type->toPhp('2015-11-01', $this->driver)); - - $this->type->useMutable(); - $this->assertInstanceOf('DateTime', $this->type->marshal('2015-11-01')); - $this->assertInstanceOf('DateTime', $this->type->toPhp('2015-11-01', $this->driver)); - } } diff --git a/src/I18n/DateFormatTrait.php b/src/I18n/DateFormatTrait.php index 2dab76df397..21f40f8e699 100644 --- a/src/I18n/DateFormatTrait.php +++ b/src/I18n/DateFormatTrait.php @@ -14,6 +14,8 @@ */ namespace Cake\I18n; +use Cake\Chronos\Date as ChronosDate; +use Cake\Chronos\MutableDate; use IntlDateFormatter; /** @@ -54,6 +56,13 @@ trait DateFormatTrait */ protected static $_jsonEncodeFormat = "yyyy-MM-dd'T'HH:mm:ssZ"; + /** + * Caches whehter or not this class is a subclass of a Date or MutableDate + * + * @var boolean + */ + protected static $_isDateInstance; + /** * Returns a nicely formatted date string for this object. * @@ -263,18 +272,25 @@ public static function parseDateTime($time, $format = null) $dateFormat = null; } + if (static::$_isDateInstance === null) { + static::$_isDateInstance = + is_subclass_of(static::class, ChronosDate::class) || + is_subclass_of(static::class, MutableDate::class); + } + + $defaultTimezone = static::$_isDateInstance ? 'UTC' : date_default_timezone_get(); $formatter = datefmt_create( static::$defaultLocale, $dateFormat, $timeFormat, - date_default_timezone_get(), + $defaultTimezone, null, $pattern ); $time = $formatter->parse($time); if ($time !== false) { $result = new static('@' . $time); - return $result->setTimezone(date_default_timezone_get()); + return static::$_isDateInstance ? $result : $result->setTimezone($defaultTimezone); } return null; } diff --git a/tests/TestCase/I18n/DateTest.php b/tests/TestCase/I18n/DateTest.php index 085515942e4..829b28817ff 100644 --- a/tests/TestCase/I18n/DateTest.php +++ b/tests/TestCase/I18n/DateTest.php @@ -52,6 +52,7 @@ public function tearDown() parent::tearDown(); Date::$defaultLocale = $this->locale; FrozenDate::$defaultLocale = $this->locale; + date_default_timezone_set('UTC'); } /** @@ -489,4 +490,18 @@ public function testDateAgoInWordsNegativeValues($class) $result = $date->timeAgoInWords(['accuracy' => 'day']); $this->assertEquals('today', $result); } + + /** + * Tests that parsing a date in a timezone other than UTC + * will not alter the date + * + * @dataProvider classNameProvider + * @return void + */ + public function testParseDateDifferentTimezone($class) + { + date_default_timezone_set('Europe/Paris'); + $result = $class::parseDate('25-02-2016', 'd-M-y'); + $this->assertEquals('25-02-2016', $result->format('d-m-Y')); + } }