【问题标题】:Help grokking Time and Time Zones in Rails 3帮助了解 Rails 3 中的时间和时区
【发布时间】:2011-09-23 15:51:40
【问题描述】:

我知道那里有几十个类似的问题,更不用说 Internet 上的无数文章了,但我仍然很难理解 Rails 如何在内部使用时区。

我目前在我的应用程序文件中配置了config.time_zone = 'Eastern Time (US & Canada)',因为这是我和其他项目管理员所在的位置。拥有该站点的公司位于加利福尼亚州,因此他们将在太平洋时间。该应用程序拥有全球用户,虽然我们还没有这样做,但我们最终将实施用户首选时区。

所以我目前的问题:

  1. 我知道 Rails 在分别存储和检索时会神奇地将 datetime 列值转换为 UTC 和从 UTC 转换,但是查看给定 datetime 属性的本地版本的正确方法是什么?

  2. 什么时候会使用Time.nowTime.zone.nowTime.now.in_time_zoneDateTime.nowDateTime.now.in_time_zone

  3. 将给定的日期时间属性与上面列出的方法或相对于当前配置的时区的其他特定时间进行比较的正确方法是什么?与UTC?

  4. 我们会有一些时间敏感的东西,比如需要根据应用程序的时区在特定时间发布的文章,那么我如何让应用程序在我们指定的时区而不是当前配置的一个(假设实现了用户时区?)

  5. 新问题)如果我以后将config.time_zone 更改为UTC 会怎样?我是否必须重置数据库中的所有时间,否则会影响旧时间吗?

【问题讨论】:

  • 这是个好问题;我还没有找到关于正确实施时区的好文档。我会在列表中添加两个问题:6. Is Rails sensitive to Daylight Savings Time and/or how do you implement time zone support that is sensitive?7. Is there a difference between how Rails handles time zones and DST for date columns vs. datetime columns?,也许还有 8. Is this database agnostic or does it need to be handled differently for SQLite vs. MySQL vs. others?
  • @Clay:你能找到关于这些问题的更多信息吗?我仍在寻找有关该主题的更多信息。
  • 我没有找到太多好的信息。使用时区很容易成为我正在使用的爱好应用程序中最令人沮丧和最耗时的部分。我问的这个问题有一个很好的回答:stackoverflow.com/questions/8466903/… 但它只与 postgres 相关。

标签: ruby-on-rails-3 datetime comparison timezone


【解决方案1】:

首先,重要的是要了解 Rails 的时区内容主要是关于演示的。在幕后,一切都发生在 UTC。

第一季度。在控制台,Rails 将在您的默认时区显示时间,因此 Something.last.created_at 在 Time.zone 给出的区域中显示该时间戳

第二季度。所有这些都返回一个代表“现在”的对象。 DateTime 与 Time 的选择与时区无关。例如,如果您需要能够表示 unix 纪元之外的时间,请使用 DateTime。 Time.nowTime.zone.now 之间的区别在于您是否返回一个 Time 实例(它将在服务器的本地时区作为控制器)。例如,这控制 to_s 返回的内容,但不控制表示的即时时间:

SomeModel.create(:time_attribute => Time.now)
SomeModel.create(:time_attribute => Time.zone.now)

将同一行插入数据库。如果您只是向用户显示时间(例如,如果您的站点在标题中显示当前时间),那么您应该使用 Time.zone.now 以便它显示在正确的时区中。如果您只是将它存储在数据库中,那么它并不重要 - 无论如何,activerecord 会将其转换为 TimeWithZone。

第三季度。 TimeWithZone 上的比较方法是通过比较日期的 utc 版本来实现的,因此您可以安全地比较不同时区的时间 - 您不需要将它们转换为某个公共时区。您还可以将 TimeWithZone 实例与普通时间对象进行比较。

第四季度。你通常不需要做任何事情。实现这一点的一种常见方法是在模型上添加published_at 属性。显示列表文章的页面将添加一个

where('published_at <= ?', Time.now)

查询条件。当您创建文章时,Rails 从表单中获取日期时间并将其转换为 utc,因此数据库中存储的是 published_at 时间的 utc 版本。比较与时区无关,因此无论时区是什么,查询都可以正常工作。

这可能会因纯时间(例如“下午 4 点”)而变得复杂,因为只有在您也知道日期(即您知道准确的时间)时才能正确完成时区转换,这取决于 DST (或改变时区的国家等政治事件)与 UTC 变化的偏移量。在这种情况下,您通常只想存储一天中的时间,并且尽可能晚地将其转换为完整时间,前提是您也知道日期。

Q5。 Rails 总是将 UTC 存储在数据库中。这样做的直接后果是更改config.time_zone 不需要您更改存储在数据库中的数据。您甚至可以为每个用户设置Time.zone,以便用户查看其时区的时间 - config.time_zone 仅控制 Time.zone 的默认值

【讨论】:

  • 非常全面的解释。谢谢。
  • 我一直对此感到困惑,你的回答太棒了。
猜你喜欢
  • 2011-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多