Symfony 1.4 / Doctrine:将日期时间存储为UTC,但在生成的admin中将所有时间显示为Eastern Time

时间:2013-01-04 22:43:22

标签: php doctrine timezone symfony-1.4 symfony-forms

我们有一个带有生成管理应用程序的Symfony项目,我们需要datetime字段显示为东部时间。现在,Symfony设置为将所有日期时间值处理为UTC。这是设计,因为挂钩到这个项目的各种其他事情处理UTC日期时间。我们只需要管理员显示和接受日期时间输入,就像用户在东部时区一样。

以下是我们为完成此任务而尝试完成的简短列表:

  1. 将应用的setting.yml中的default_timezone设置更改为“America / New York”。首先,它似乎并没有真正改变日期时间字段在管理中显示的方式;它似乎只设置date_default_timezone_set()。其次,我们实际上需要PHP来处理UTC时间,因为我们的一些辅助函数被编写为假设UTC。最后,我们需要将日期时间作为UTC存储在MySQL数据库中,因为我们将它们全部定义为DATETIME列(而不是时间戳),正如我所理解的那样,它们是时区的。 (不过我在这里错了。)

  2. 修改相关的管理表单对象,以便在保存/编辑对象时将日期时间从ET转换为UTC,并在编辑表单中预先填充相同的值时创建自定义窗口小部件以执行相反的转换。所以这实际上对我们有用,但这里有重大问题。我们必须创建一个自定义小部件;不过,这并不是什么大不了的事。我们还必须修改包含datetime字段的每个类的管理表单。这对屁股来说有点痛苦。我们还必须向受影响的类添加辅助函数,因为虽然管理表单将显示正确的值,但如果任何这些日期时间列显示在管理列表中,它们仍将显示为UTC时间而不是ET时间。然后我们还必须扩展Timestampable行为,因为THOSE还需要以UTC格式显示在ET / store中。这只是让管理员在ET中显示时间的大量工作,这不仅是脆弱的,而且如果我们引入带有datetime字段的新类(或将datetime字段添加到当前类),还需要添加。

  3. 覆盖受影响类的save()和load()函数。我们尝试将从admin表单获得的ET datetime字符串转换为UTC并使用内置的setter函数更改对象,然后调用父save()。这工作得很好。然而,尝试对反向的load()函数做同样的事情,失败了。调用父load()函数很好,但是使用内置的setter来改变从UTC到ET的时间失败。事实证明,就我们所知,load()函数实际上根本没有执行;当我们尝试加载现有对象的表单时,var_dump()和exit()命令不会执行。我们仍然不知道为什么这不起作用。

  4. 覆盖受影响的类上的preSave()和postLoad()函数。我们遇到了与#4相同的问题:preSave()工作正常,但postLoad()失败了。

  5. 覆盖受影响类的preSave()函数,然后覆盖类中datetime字段的相关getter函数。这是有效的,但只有通过访问对象的内部$ _data数组而不是使用getter来获取原始日期时间值。我们需要这样做,因为显然调用任何setter也最终也会调用该字段的getter,导致我们应用了太多的时区翻译。所以这样可行,但是访问$ _data数组感觉就像是一个乞求破坏的巨大黑客。

  6. 过去,我们只有理论方法,我们尚未研究过。例如,我们可以在Symfony的某个地方修改日期时间字段本身的定义,无论是在Doctrine还是其他地方,但是我们想不到一个不需要深入研究Doctrine核心的地方。< / p>

    此时,我们有点陷入困境。所有这些似乎只是为了让管理员将日期时间显示为ET并将ET日期时间保存为数据库中的UTC,所以我们必须做错事 - 我们无法弄清楚我们应该做什么正在做。

2 个答案:

答案 0 :(得分:1)

我们基本上已经完成了(2) - 数据库和系统时区是UTC正确和自然的,我们有自定义时区感知日期时间小部件&amp;验证器。

我们做的另一件事是在我们的学说模型基类中添加$model->getDateTimeObject($fieldName)方法(参见http://oldforum.symfony-project.org/index.php/m/96066/),该方法将返回DateTime及相关的DateTimeZone abstract class ourDoctrineRecord extends sfDoctrineRecord { /** * @param string $fieldName * @return DateTime */ public function getDateTimeObject($fieldName) { // chose a relevant timezone based on user/app etc, or throw } } } set。

例如:

{{1}}

答案 1 :(得分:0)

问题在于Doctrine,当它使用getter时,它会在默认的symphony时区获得新的日期时间,因此必须通过向ORM添加自定义日期时间类型来更改,类似于本教程;你可以用它来设置和获取UTC

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/working-with-datetime.html