Просмотр исходного кода

Merge pull request #274 from alcaeus/fix-dst-shenanigans

Fix wrong handling of timezones when converting UTCDateTime
Andreas Braun 5 лет назад
Родитель
Сommit
cdc54b06dc
2 измененных файлов с 31 добавлено и 3 удалено
  1. 2 3
      lib/Mongo/MongoDate.php
  2. 29 0
      tests/Alcaeus/MongoDbAdapter/Mongo/MongoDateTest.php

+ 2 - 3
lib/Mongo/MongoDate.php

@@ -88,15 +88,14 @@ class MongoDate implements TypeInterface
     public function toDateTime()
     {
         $datetime = new \DateTime();
+        $datetime->setTimezone(new \DateTimeZone("UTC"));
         $datetime->setTimestamp($this->sec);
 
         $microSeconds = $this->truncateMicroSeconds($this->usec);
         if ($microSeconds > 0) {
-            $datetime = \DateTime::createFromFormat('Y-m-d H:i:s.u', $datetime->format('Y-m-d H:i:s') . '.' . str_pad($microSeconds, 6, '0', STR_PAD_LEFT));
+            $datetime = \DateTime::createFromFormat('Y-m-d H:i:s.u e', $datetime->format('Y-m-d H:i:s') . '.' . str_pad($microSeconds, 6, '0', STR_PAD_LEFT) . ' UTC');
         }
 
-        $datetime->setTimezone(new \DateTimeZone("UTC"));
-
         return $datetime;
     }
 

+ 29 - 0
tests/Alcaeus/MongoDbAdapter/Mongo/MongoDateTest.php

@@ -95,4 +95,33 @@ class MongoDateTest extends TestCase
         $this->assertSame(1234567890, $dateTime->getTimestamp());
         $this->assertSame('012000', $dateTime->format('u'));
     }
+
+    public function testDSTTransitionDoesNotProduceWrongResults()
+    {
+        $initialTZ = ini_get("date.timezone");
+
+        ini_set("date.timezone", "Europe/Madrid");
+
+        $date = new \MongoDate(1603584000);
+        $dateTime = $date->toDateTime();
+
+        $this->assertSame(1603584000, $dateTime->getTimestamp());
+
+        ini_set("date.timezone", $initialTZ);
+    }
+
+    public function testDSTTransitionDoesNotProduceWrongResultsWithMicroSeconds()
+    {
+        $initialTZ = ini_get("date.timezone");
+
+        ini_set("date.timezone", "Europe/Madrid");
+
+        $date = new \MongoDate(1603584000, 123456);
+        $dateTime = $date->toDateTime();
+
+        $this->assertSame(1603584000, $dateTime->getTimestamp());
+        $this->assertSame('123000', $dateTime->format('u'));
+
+        ini_set("date.timezone", $initialTZ);
+    }
 }