diff --git a/src/Drivers/Mysqli/MysqliDriver.php b/src/Drivers/Mysqli/MysqliDriver.php index caff3112..f66fe497 100644 --- a/src/Drivers/Mysqli/MysqliDriver.php +++ b/src/Drivers/Mysqli/MysqliDriver.php @@ -226,15 +226,23 @@ public function convertToSql($value, $type) case self::TYPE_DATETIME: if ($value->getTimezone()->getName() !== $this->connectionTz->getName()) { - $value = clone $value; - $value->setTimezone($this->connectionTz); + if ($value instanceof \DateTimeImmutable) { + $value = $value->setTimezone($this->connectionTz); + } else { + $value = clone $value; + $value->setTimezone($this->connectionTz); + } } return "'" . $value->format('Y-m-d H:i:s') . "'"; case self::TYPE_DATETIME_SIMPLE: if ($value->getTimezone()->getName() !== $this->simpleStorageTz->getName()) { - $value = clone $value; - $value->setTimeZone($this->simpleStorageTz); + if ($value instanceof \DateTimeImmutable) { + $value = $value->setTimezone($this->simpleStorageTz); + } else { + $value = clone $value; + $value->setTimeZone($this->simpleStorageTz); + } } return "'" . $value->format('Y-m-d H:i:s') . "'"; diff --git a/src/Drivers/Pgsql/PgsqlDriver.php b/src/Drivers/Pgsql/PgsqlDriver.php index 4a48bcc0..22cf8c53 100644 --- a/src/Drivers/Pgsql/PgsqlDriver.php +++ b/src/Drivers/Pgsql/PgsqlDriver.php @@ -220,15 +220,23 @@ public function convertToSql($value, $type) case self::TYPE_DATETIME: if ($value->getTimezone()->getName() !== $this->connectionTz->getName()) { - $value = clone $value; - $value->setTimezone($this->connectionTz); + if ($value instanceof \DateTimeImmutable) { + $value = $value->setTimezone($this->connectionTz); + } else { + $value = clone $value; + $value->setTimezone($this->connectionTz); + } } return "'" . $value->format('Y-m-d H:i:s') . "'"; case self::TYPE_DATETIME_SIMPLE: if ($value->getTimezone()->getName() !== $this->simpleStorageTz->getName()) { - $value = clone $value; - $value->setTimezone($this->simpleStorageTz); + if ($value instanceof \DateTimeImmutable) { + $value = $value->setTimezone($this->simpleStorageTz); + } else { + $value = clone $value; + $value->setTimezone($this->simpleStorageTz); + } } return "'" . $value->format('Y-m-d H:i:s') . "'"; diff --git a/tests/cases/integration/datetime.mysql.phpt b/tests/cases/integration/datetime.mysql.phpt index fbcb6035..a4d9b85d 100644 --- a/tests/cases/integration/datetime.mysql.phpt +++ b/tests/cases/integration/datetime.mysql.phpt @@ -8,7 +8,10 @@ namespace NextrasTests\Dbal; use DateTime; +use DateTimeImmutable; use Tester\Assert; +use Tester\Environment; + require_once __DIR__ . '/../../bootstrap.php'; @@ -61,6 +64,55 @@ class DateTimeMysqlTest extends IntegrationTestCase } + public function testWriteStorageTZUTCImmutable() + { + if (PHP_VERSION_ID < 50500) { + Environment::skip('DateTimeImmutable tested only in PHP >= 5.5'); + } + + $connection = $this->createConnection([ + 'simpleStorageTz' => 'UTC', + 'connectionTz' => 'Europe/Prague', + ]); + + $connection->query('DROP TABLE IF EXISTS dates_write2'); + $connection->query(' + CREATE TABLE dates_write2 ( + a datetime, + b timestamp + ); + '); + + $connection->query( + 'INSERT INTO dates_write2 VALUES (%dts, %dt)', + new DateTimeImmutable('2015-01-01 12:00:00'), // 11:00 UTC + new DateTimeImmutable('2015-01-01 12:00:00') // 11:00 UTC + ); + + $result = $connection->query('SELECT * FROM dates_write2'); + $result->setValueNormalization(FALSE); + + $row = $result->fetch(); + Assert::same('2015-01-01 11:00:00', $row->a); + Assert::same('2015-01-01 12:00:00', $row->b); + + + $connection->query('DELETE FROM dates_write2'); + $connection->query( + 'INSERT INTO dates_write2 VALUES (%dts, %dt)', + new DateTimeImmutable('2015-01-01 12:00:00'), // 11:00 UTC + new DateTimeImmutable('2015-01-01 12:00:00 Europe/Kiev') // 10:00 UTC + ); + + $result = $connection->query('SELECT * FROM dates_write2'); + $result->setValueNormalization(FALSE); + + $row = $result->fetch(); + Assert::same('2015-01-01 11:00:00', $row->a); + Assert::same('2015-01-01 11:00:00', $row->b); + } + + public function testReadStorageTZUTC() { $connection = $this->createConnection([ diff --git a/tests/cases/integration/datetime.pgsql.phpt b/tests/cases/integration/datetime.pgsql.phpt index 89895a5d..bdc30779 100644 --- a/tests/cases/integration/datetime.pgsql.phpt +++ b/tests/cases/integration/datetime.pgsql.phpt @@ -8,7 +8,10 @@ namespace NextrasTests\Dbal; use DateTime; +use DateTimeImmutable; use Tester\Assert; +use Tester\Environment; + require_once __DIR__ . '/../../bootstrap.php'; @@ -61,6 +64,55 @@ class DateTimePostgreTest extends IntegrationTestCase } + public function testWriteStorageTZUTCImmutable() + { + if (PHP_VERSION_ID < 50500) { + Environment::skip('DateTimeImmutable tested only in PHP >= 5.5'); + } + + $connection = $this->createConnection([ + 'simpleStorageTz' => 'UTC', + 'connectionTz' => 'Europe/Prague', + ]); + + $connection->query('DROP TABLE IF EXISTS dates_write2'); + $connection->query(' + CREATE TABLE dates_write2 ( + a timestamp, + b timestamptz + ); + '); + + $connection->query( + 'INSERT INTO dates_write2 VALUES (%dts, %dt)', + new DateTimeImmutable('2015-01-01 12:00:00'), // 11:00 UTC + new DateTimeImmutable('2015-01-01 12:00:00') // 11:00 UTC + ); + + $result = $connection->query('SELECT * FROM dates_write2'); + $result->setValueNormalization(FALSE); + + $row = $result->fetch(); + Assert::same('2015-01-01 11:00:00', $row->a); + Assert::same('2015-01-01 12:00:00+01', $row->b); + + + $connection->query('DELETE FROM dates_write2'); + $connection->query( + 'INSERT INTO dates_write2 VALUES (%dts, %dt)', + new DateTimeImmutable('2015-01-01 12:00:00'), // 11:00 UTC + new DateTimeImmutable('2015-01-01 12:00:00 Europe/Kiev') // 10:00 UTC + ); + + $result = $connection->query('SELECT * FROM dates_write2'); + $result->setValueNormalization(FALSE); + + $row = $result->fetch(); + Assert::same('2015-01-01 11:00:00', $row->a); + Assert::same('2015-01-01 11:00:00+01', $row->b); + } + + public function testReadStorageTZUTC() { $connection = $this->createConnection([