如何使用symfony3时区

时间:2017-03-22 06:46:16

标签: php symfony

我将所有时间/日期时间存储在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()行动onKernelRequestUTC之前设置为用户的时区,因此所有日期都在服务器的{{1}}时区内。任何想法如何使其有效?

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());
    }
}