我将所有时间/日期时间存储在UTC时区中。我想允许用户指定他想在哪个时区查看小时/日期 - 比如在任何其他论坛(phpbb,ipb等等......)
到目前为止我做了什么:
在config.yml
我设置了新的学说类型:
types:
datetime: AppBundle\DoctrineExtensions\DBAL\Types\UTCDateTimeType
datetimetz: AppBundle\DoctrineExtensions\DBAL\Types\UTCDateTimeType
time: AppBundle\DoctrineExtensions\DBAL\Types\UTCTimeType
离。 UTDDateTime
:
<?php
namespace AppBundle\DoctrineExtensions\DBAL\Types;
use DateTime;
use DateTimeZone;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\DateTimeType;
class UTCDateTimeType extends DateTimeType
{
/** @var DateTimeZone */
private static $utc;
/** @var DateTimeZone */
private static $defaultTimeZone;
/**
* @param DateTime $dateTime
* @param AbstractPlatform $platform
*
* @return string|null
*/
public function convertToDatabaseValue($dateTime, AbstractPlatform $platform)
{
if ($dateTime instanceof DateTime) {
$dateTime->setTimezone(self::getUtc());
}
return parent::convertToDatabaseValue($dateTime, $platform);
}
/**
* @param string $dateTimeString
* @param AbstractPlatform $platform
*
* @throws ConversionException
*
* @return DateTime|null
*/
public function convertToPHPValue($dateTimeString, AbstractPlatform $platform)
{
if (null === $dateTimeString || $dateTimeString instanceof DateTime) {
return $dateTimeString;
}
$dateTime = DateTime::createFromFormat($platform->getDateTimeFormatString(), $dateTimeString, self::getUtc());
if (!$dateTime) {
throw ConversionException::conversionFailedFormat(
$dateTimeString,
$this->getName(),
$platform->getDateTimeFormatString()
);
}
// set time zone
$dateTime->setTimezone(self::getDefaultTimeZone());
return $dateTime;
}
/**
* @return DateTimeZone
*/
private static function getUtc()
{
return self::$utc ? self::$utc : self::$utc = new DateTimeZone('UTC');
}
/**
* @return DateTimeZone
*/
private static function getDefaultTimeZone()
{
return self::$defaultTimeZone
? self::$defaultTimeZone : self::$defaultTimeZone = new DateTimeZone(date_default_timezone_get());
}
}
我已成为onKernelRequest
听众:
class TimezoneListener
{
/**
* @var AppSettingsService
*/
private $settings;
/**
* @var \Twig_Environment
*/
protected $twig;
public function __construct(AppSettingsService $settings, \Twig_Environment $twig)
{
$this->twig = $twig;
$this->settings = $settings->getAppSettings();
}
public function onKernelRequest(GetResponseEvent $event)
{
date_default_timezone_set($this->settings->getDefaultTimeZone());
$this->twig->getExtension('Twig_Extension_Core')->setTimezone($this->settings->getDefaultTimeZone());
}
}
并将php.ini
配置为UTC
。现在出现了麻烦:
date_default_timezone_get()
之前的UTCDateTimeType::getDefaultTimeZone()
行动onKernelRequest
在UTC
之前设置为用户的时区,因此所有日期都在服务器的{{1}}时区内。任何想法如何使其有效?
答案 0 :(得分:0)
你非常接近。你实际上可以简化一下:
在config.yml
中,您只需覆盖datetime
:
doctrine:
dbal:
types:
utcdatetime:
name: datetime
class: AppBundle\Doctrine\DBAL\Types\UTCDateTimeType
在UTCDateTimeType
中,您只需确保将UTC日期时间存储在数据库中:
namespace AppBundle\Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\DateTimeType;
/**
* Class UTCDateTimeType
*
* @package AppBundle\Doctrine\DBAL\Types
*/
class UTCDateTimeType extends DateTimeType
{
/**
* @var \DateTimeZone
*/
private static $utc = null;
/**
* @param mixed $value
* @param AbstractPlatform $platform
*
* @return mixed
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if ($value instanceof \DateTime) {
$value->setTimezone(self::getUtc());
}
return parent::convertToDatabaseValue($value, $platform);
}
/**
* @param mixed $value
* @param AbstractPlatform $platform
*
* @return $this|mixed
* @throws ConversionException
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if (null === $value || $value instanceof \DateTime) {
return $value;
}
$converted = \DateTime::createFromFormat(
$platform->getDateTimeFormatString(),
$value,
self::$utc ? self::$utc : self::$utc = new \DateTimeZone('UTC')
);
if (!$converted) {
throw ConversionException::conversionFailedFormat(
$value,
$this->getName(),
$platform->getDateTimeFormatString()
);
}
return $converted;
}
/** @return \DateTimeZone */
private static function getUtc()
{
if (self::$utc === null) {
self::$utc = new \DateTimeZone('UTC');
}
return self::$utc;
}
}
最后,您的onKernelRequest
听众不需要设置服务器时区,只需要设置Twig时区:
class TimezoneListener
{
/**
* @var AppSettingsService
*/
private $settings;
/**
* @var \Twig_Environment
*/
protected $twig;
public function __construct(AppSettingsService $settings, \Twig_Environment $twig)
{
$this->twig = $twig;
$this->settings = $settings->getAppSettings();
}
public function onKernelRequest(GetResponseEvent $event)
{
$this->twig->getExtension('Twig_Extension_Core')->setTimezone($this->settings->getDefaultTimeZone());
}
}