Browse Source

Fixing bug in the Date::parseDate() method

When using a different timezone it would return different dates
because of the timezone changes.
Jose Lorenzo Rodriguez 10 years ago
parent
commit
0aaf232bc9
3 changed files with 33 additions and 18 deletions
  1. 0 16
      src/Database/Type/DateType.php
  2. 18 2
      src/I18n/DateFormatTrait.php
  3. 15 0
      tests/TestCase/I18n/DateTest.php

+ 0 - 16
src/Database/Type/DateType.php

@@ -99,20 +99,4 @@ class DateType extends DateTimeType
         $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));
-    }
 }

+ 18 - 2
src/I18n/DateFormatTrait.php

@@ -14,6 +14,8 @@
  */
 namespace Cake\I18n;
 
+use Cake\Chronos\Date as ChronosDate;
+use Cake\Chronos\MutableDate;
 use IntlDateFormatter;
 
 /**
@@ -55,6 +57,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.
      *
      * The format to be used is stored in the static property `Time::niceFormat`.
@@ -263,18 +272,25 @@ trait DateFormatTrait
             $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;
     }

+ 15 - 0
tests/TestCase/I18n/DateTest.php

@@ -52,6 +52,7 @@ class DateTest extends TestCase
         parent::tearDown();
         Date::$defaultLocale = $this->locale;
         FrozenDate::$defaultLocale = $this->locale;
+        date_default_timezone_set('UTC');
     }
 
     /**
@@ -489,4 +490,18 @@ class DateTest extends TestCase
         $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'));
+    }
 }