Skip to content

Instantly share code, notes, and snippets.

@romaricdrigon
Created March 21, 2019 15:17
Show Gist options
  • Select an option

  • Save romaricdrigon/2b2345d5d1bbced5d1332fe110738532 to your computer and use it in GitHub Desktop.

Select an option

Save romaricdrigon/2b2345d5d1bbced5d1332fe110738532 to your computer and use it in GitHub Desktop.
Exemple de type Doctrine pour stocker des dates avec timezone sous MySQL
<?php
namespace App\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;
class DateTimeImmutableUtcType extends Type
{
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getDateTimeTypeDeclarationSQL($fieldDeclaration);
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if (null === $value) {
return $value;
}
if (!$value instanceof \DateTimeImmutable) {
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateTimeImmutable']);
}
if ('UTC' !== $value->getTimeZone()->getName()) {
throw new \Exception(sprintf('DateTime TimeZone should be set to UTC, got %s instead', $value->getTimeZone()->getName()));
}
return $value->format($platform->getDateTimeFormatString());
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === null || $value instanceof \DateTimeImmutable) {
return $value;
}
$utcValue = \DateTimeImmutable::createFromFormat($platform->getDateTimeFormatString(), $value, new \DateTimeZone('UTC'));
if (!$utcValue) {
throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeFormatString());
}
return $utcValue;
}
public function getName()
{
return 'datetime_immutable_utc';
}
}
# config/packages/doctrine.yaml ou bien app/config/config.yml
doctrine:
dbal:
types:
datetime_immutable_utc: App\Type\DateTimeImmutableUtcType
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
*/
class Event
{
// ...
/**
* @ORM\Column(type="datetime_immutable_utc")
*/
private $datetimeUtc;
/**
* @ORM\Column(type="string")
*/
private $timezone;
public function setLocalDateTime(\DateTimeImmutable $dateTime): self
{
// On doit toujours convertir!
$dateTimeUtc = $dateTime->setTimezone(new \DateTimeZone('UTC'));
$this->datetimeUtc = $dateTimeUtc;
$this->timezone = $dateTime->getTimezone()->getName();
}
public function getLocalDateTime(): \DateTimeImmutable
{
// On doit toujours repasser par un timestamp pour convertir.
$timestampUtc = $this->datetimeUtc->getTimestamp();
return \DateTimeImmutable::create('@'.$timestampUtc, new \DateTimeZone($this->timezone));
}
// Pas besoin de getter/setter sur $timezone, c'est même déconseillé.
// Par contre on peut autoriser l'accès à la date UTC brute, sans risque de mauvaises manipulations.
public function getDateTimeUtc(): \DateTimeImmutable
{
return $this->datetimeUtc;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment