我们有一个带有生成管理应用程序的 Symfony 项目,我们需要将日期时间字段显示为东部时间。现在,Symfony 设置为将所有日期时间值作为 UTC 处理。这是设计使然,因为与该项目挂钩的各种其他事物都处理 UTC 日期时间。我们只需要管理员显示和接受日期时间输入,就好像用户在东部时区一样。
以下是我们为尝试实现这一目标所做的事情的简短列表:
将应用程序 setting.yml 中的 default_timezone 设置更改为“America/New York”。首先,它似乎并没有真正改变日期时间字段在管理员中的显示方式;它似乎只设置 date_default_timezone_set()。其次,我们实际上需要 PHP 来处理 UTC 时间,因为我们的一些辅助函数被编写为假定 UTC。最后,我们需要将日期时间作为 UTC 存储在 MySQL 数据库中,并且因为我们已将它们全部定义为 DATETIME 列(而不是时间戳),据我所知,它们是时区天真的。(不过,我在这里可能是错的。)
修改相关的管理表单对象以在保存/编辑对象时将日期时间从 ET 转换为 UTC,并在编辑表单中预填充相同的值时创建自定义小部件以进行相反的转换。所以这实际上对我们有用,但这里存在重大问题。我们必须创建自定义小部件,例如;不过,这没什么大不了的。我们还必须为每个包含日期时间字段的类修改管理表单。这有点让人头疼。我们还必须向受影响的类添加辅助函数,因为虽然管理表单将显示正确的值,但如果这些日期时间列中的任何一个出现在管理列表中,它们仍将显示为 UTC 时间而不是 ET 时间。然后我们还必须扩展 Timestampable 行为,因为 THOSE 还需要以 UTC 格式显示在 ET/store 中。
覆盖受影响类的 save() 和 load() 函数。我们尝试将我们从管理表单中获得的 ET 日期时间字符串转换为 UTC,并使用内置的 setter 函数更改对象,然后调用父 save()。那工作得很好。然而,试图对 load() 函数做同样的事情却惨遭失败。调用父 load() 函数很好,但使用内置设置器将时间从 UTC 更改回 ET 失败。事实证明 load() 函数实际上并没有执行,据我们所知;当我们尝试为现有对象加载表单时,不会执行 var_dump() 和 exit() 命令。我们仍然不知道为什么这不起作用。
覆盖受影响类的 preSave() 和 postLoad() 函数。我们遇到了与 #4 相同的问题:preSave() 工作正常,但 postLoad() 失败。
覆盖受影响类的 preSave() 函数,然后覆盖类中日期时间字段的相关 getter 函数。这有效,但只有当我们通过访问对象的内部 $_data 数组而不是使用 getter 来获取原始日期时间值时。我们需要这样做,因为显然调用任何 setter 最终也会调用该字段的 getter,导致我们应用太多时区转换。所以这是可行的,但访问 $_data 数组感觉就像一个巨大的黑客,正在乞求被打破。
除此之外,我们只有尚未研究的理论方法。例如,我们可以在 Symfony 中的某个地方修改 datetime 字段本身的定义,无论是在 Doctrine 中还是在其他地方,但我们想不出一个不涉及深入挖掘 Doctrine 核心的地方。
在这一点上,我们有点卡住了。所有这一切似乎都是为了让管理员将日期时间显示为 ET 并将 ET 日期时间作为 UTC 保存在数据库中的大量工作,所以我们一定做错了什么——我们只是不知道我们应该做什么正在做。