Symfony + JMS Serializer:如何设置默认时区?

I am working on a Symfony webapp project and have a problem with the timezone used by the JMS Serializer.

Short version:

How can I set a global default timezone that is used all over my symfony project, not matter if the project is used in the browser or on the command line?

(very) Long Version:

  • In the global sever php.ini timezone is set as date.timezone = "America/Chicago"
  • The webapp however should use UTC as default timezone.

To achieve this I simply added ini_set("date.timezone", "UTC"); to the app.php and app_dev.php FrontControllers. Since every access to the app is routed through these files, this solutions works quite well.

However there is one big problem with this solution: It only works when the app is being used through these FrontControllers / in the browser.

When ever I use the console or any other commandline access to the project the Frontcontrollers are not uses and thus the timezone setting is not applied.

This is a problem for example when clearing and warming up the cache:

php app/console cache:clear --env=dev

Since php is used directly on the commandline the global php.ini is used. Thus the global date.timezone = "America/Chicago" is applied.

It seems that the default timezone is stored in appDevDebugProjectContainer.xml cache file and additionally the timezone is cached for the JMS Serializer as well in:

$ cd ...../app/cache/dev
$ grep -rnw .'/' -e "America/Chicago"
./appDevDebugProjectContainer.xml:4125:      <argument>America/Chicago</argument>
./appDevDebugProjectContainer.php:3083:        return $this->services['jms_serializer.datetime_handler'] = new \JMS\Serializer\Handler\DateHandler('Y-m-d\\TH:i:sO', 'America/Chicago', true);

Thus every time an object is (de)serialized using JMS the wrong timezone is applied to all dates. This is even the case when the app is running the browser (using the FrontControllers with changed default timezone).

Of course the problem is the same for all other console commands, since they all use the global php.ini. How can I solve this?

Possible Solutions:

  • Change timezone in global php.ini: Not possible because I have not root access to the server and the same php.ini is shared between different domains/project. Other domains/projects need America/Chicago as default time zone
  • Use local php.ini for the project: Not possible because a php.ini only applies to the php files within the same folder. Creating and maintaining a php.ini in every project folder is not possible.
  • Use local php.ini for command line php calls: The Frontontrollers would still set the time zone for all "browser" calls to the app. Additionally I would create one php.ini for the project that is being uses as parameter when using php on the commandline:

Code:

// in ./.bashrc
alias phpx='php -c /path/to/project/php.ini'

// use phpx instead of php
phpx app/console cache:clear --env=dev

This solution would work but I do not like it:

  • I have to maintain two php.ini files. The global php.ini and the project php.ini. Since the INIs are not combined (take one option from iniA and all other options form iniB) this possible but cumbersome.
  • I am still not 100% sure if there are not any internal php calls that might not be routed through the FrontControllers and thus might use the wrong timezone:

Conclusion:

Is there any option that will set the default timezone globally for the complete Symfony project? So far I only found an option that was used in Symfony 1.x but no equivalent solution for Symfony 2.x

Any idea?

Well, sometimes an answer is so obvious that one cannot see it. At least not before writing a long question here... :-)

Right after I send the question I found the answer: The default timezone should be applied globally, all over Symfony, no matter how it is being used (browser, console, etc.)? So, which part of Symfony is beeing use every time and every where? The Kernel!!

I simply modified the AppKernel and it works fine:

class AppKernel extends Kernel
{   
    public function __construct($environment, $debug)
    {
        // Two is better than one...
        ini_set("date.timezone", "UTC");
        date_default_timezone_set('UTC');

        parent::__construct($environment, $debug);
    }
}