【问题标题】:Propel timestampable behavior in UTC推动 UTC 中的时间戳行为
【发布时间】:2013-01-16 14:11:32
【问题描述】:

我正在使用带有 MySql 的 Propel 1.6。我在所有表上设置了时间戳行为,如下所示:

<database name="default" >
    <behavior name="timestampable">
        <parameter name="create_column" value="creation_date" />
        <parameter name="update_column" value="last_modified" />
    </behavior>

    <table name="book" phpName="Book">
        <!-- table colums omitted -->
    </table>
</database>

根据Propel时间戳行为的documentation,没有指定时区的参数。

我注意到时间戳行为默认情况下不会设置 UTC 时间。例如,在我的例子中,它设置 UTC+1。

做了一些调查,我发现如果我使用 preInsert() 钩子来设置时间而不是行为并且我传递了 Unix 时间戳:

public function preInsert(PropelPDO $con = null)
{
    $this->setCreationDate(time());
    return true;
}

结果时间仍然是 UTC+1。如果我使用 DateTime 对象而不是 Unix 时间戳来设置时间:

public function preInsert(PropelPDO $con = null)
{
    $this->setCreationDate(new DateTime('now', new DateTimeZone('UTC')));
    return true;
}

我在数据库中得到了正确的 UTC 时间。

我检查了代码,发现 bahavior 设置了通过 Unix 时间戳的时间,因此导致数据库上的 UTC+1。

我的问题是:

  1. 是否可以在 UTC 中配置 Propel 时间戳行为?
  2. 如果不是,Propel 在哪里设置日期格式/时区?使用 pre 挂钩并传递指定时区的 DateTime 对象是在数据库中获取 UTC 时间的唯一方法(实现自定义行为除外)吗?
  3. 另外,如果我无法配置 Propel 可时间戳行为的时区,那么它的全部目的首先是什么? (在数据库中设置 UTC 时间戳是一种很常见的做法)

【问题讨论】:

    标签: php mysql timestamp propel utc


    【解决方案1】:

    文档没有特别提到时区,但你应该能够设置它做这样的事情......

    $objSourceTimezone = new DateTimeZone('America/Los_Angeles');
    $objDestinationTimezone = new DateTimeZone('UTC');
    
    $objTime = new DateTime([some date], $objSourceTimezone);
    $objTime->setTimeZone($objDestinationTimezone);
    
    $objPropel->setTimestamp($time->format('Y-m-d H:i:s'));
    

    我正在使用我当地的太平洋时区(但你可以使用任何你想要的)并将其转换为与 MySQL 和 Propel 的 TIMESTAMP 列兼容的 UTC 格式。

    您可以通过相反的方式检索此数据并在不同的时区显示它...

    $objSourceTimezone = new DateTimeZone('UTC');
    $objDestinationTimezone = new DateTimeZone('America/New_York');
    
    $objTime = new DateTime($objPropel->getTimestamp(), $objSourceTimezone);
    $objTime->setTimeZone($objDestinationTimezone);
    
    print $time->format('Y-m-d H:i:s').”\n”;
    

    【讨论】:

    • 您能否澄清几点... 第一个代码块应该在哪里执行?例如,如果它应该在 preInsert() 挂钩中执行,这与我在问题中提到的类似,并且没有使用可时间戳行为。 $objPropel 是什么?它是一个 ActiveRecord 模型对象吗?
    【解决方案2】:

    根据this questionphp documentation for time(),很明显time() 应该返回自 Unix 纪元以来的秒数,该秒数始终为 UTC。事实上,在我所有使用 Propel 和可时间戳行为的项目中都是如此。如果你的项目没有这样做,那么可能存在更深层次的问题(也就是说,这不是 Propel 中的问题)。也就是说,我对您的问题的回答是:

    1. 该行为使用time(),根据 PHP 文档,它始终采用 UTC。
    2. 见(1),不,Propel没有这样的时区设置(虽然PHP does,但它不用于time(),而是用于mktime())。我认为你的 preInsert() 钩子应该可以作为一种解决方法,如果你必须这样做的话。
    3. 见(1),时间戳行为超级简单,只用time(),但你总是可以自己写!事实上,您只需复制 existing behavior file,然后将其添加到您的构建属性 (Propel doc for custom behaviors)。

    祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-16
      • 2019-08-15
      • 2017-04-27
      • 2021-03-05
      • 1970-01-01
      相关资源
      最近更新 更多