timostamm/doctrine-fixed-timezone

在 Doctrine 数据库中规范化时区。

v1.1.2 2021-04-29 20:25 UTC

This package is auto-updated.

Last update: 2024-08-29 04:37:45 UTC


README

问题

如果你的应用程序处理不同时区的日期,你有两种选择

1) 将每个日期的时区保存到数据库中

如果你以后需要知道时区,这是唯一的选择。

不幸的是,这使得对日期的查询几乎不可能: SELECT * FROM x WHERE x.date > CURRENT_TIMESTAMP() 将导致意外结果。CURRENT_TIMESTAMP 将使用数据库服务器的当前时间,而你提供的日期将被错误地解释为错误的时区。

2) 将数据库中保存的所有日期转换为同一时区

如果你将所有日期转换为数据库服务器的时区,你的查询将按预期工作。

不幸的是,Doctrine 并没有提供这样的转换选项。

本库提供的解决方案

本库提供了对 DBAL 类型 datetimedatetime_immutable 的替换,这些类型将自动将日期转换为数据库时区。

当读取 datetimedatetime_immutable 时,时区 不会转换为 PHP 时区。日期将指代正确的时间点,但具有数据库时区。

关于独立的日期和时间

没有时间的日期或没有日期的时间都不指代一个绝对的时间点。由于 PHP 没有表示独立时间或日期的类型,开发者使用 DateTime 对象来表示这些,但它们的时区应该被忽略。

因此,使用标准的 datetime doctrine 类型应该是没有问题的。

如何使用

Symfony

doctrine:
  dbal:
    # ...
    types:
      datetime: TS\DoctrineExtensions\DBAL\FixedDbTimezone\DateTimeType
      datetime_immutable: TS\DoctrineExtensions\DBAL\FixedDbTimezone\DateTimeImmutableType

要设置数据库时区,定义一个常量 define('DATABASE_TIMEZONE', 'Europe/Berline'); 或设置环境变量 DATABASE_TIMEZONE

否则,将使用 PHP 时区。

背景

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/cookbook/working-with-datetime.html#handling-different-timezones-with-the-datetime-type