2

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

以下是我们为尝试实现这一目标所做的事情的简短列表:

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

  2. 修改相关的管理表单对象以在保存/编辑对象时将日期时间从 ET 转换为 UTC,并在编辑表单中预填充相同的值时创建自定义小部件以进行相反的转换。所以这实际上对我们有用,但这里存在重大问题。我们必须创建自定义小部件,例如;不过,这没什么大不了的。我们还必须为每个包含日期时间字段的类修改管理表单。这有点让人头疼。我们还必须向受影响的类添加辅助函数,因为虽然管理表单将显示正确的值,但如果这些日期时间列中的任何一个出现在管理列表中,它们仍将显示为 UTC 时间而不是 ET 时间。然后我们还必须扩展 Timestampable 行为,因为 THOSE 还需要以 UTC 格式显示在 ET/store 中。

  3. 覆盖受影响类的 save() 和 load() 函数。我们尝试将我们从管理表单中获得的 ET 日期时间字符串转换为 UTC,并使用内置的 setter 函数更改对象,然后调用父 save()。那工作得很好。然而,试图对 load() 函数做同样的事情却惨遭失败。调用父 load() 函数很好,但使用内置设置器将时间从 UTC 更改回 ET 失败。事实证明 load() 函数实际上并没有执行,据我们所知;当我们尝试为现有对象加载表单时,不会执行 var_dump() 和 exit() 命令。我们仍然不知道为什么这不起作用。

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

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

除此之外,我们只有尚未研究的理论方法。例如,我们可以在 Symfony 中的某个地方修改 datetime 字段本身的定义,无论是在 Doctrine 中还是在其他地方,但我们想不出一个不涉及深入挖掘 Doctrine 核心的地方。

在这一点上,我们有点卡住了。所有这一切似乎都是为了让管理员将日期时间显示为 ET 并将 ET 日期时间作为 UTC 保存在数据库中的大量工作,所以我们一定做错了什么——我们只是不知道我们应该做什么正在做。

4

2 回答 2

1

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

我们所做的另一件事是$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
  }
}
于 2013-04-28T00:16:13.180 回答
0

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

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

于 2016-12-05T21:40:48.403 回答