帮助在Rails 3中获取时间和时区

Chr*_*oom 8 comparison timezone datetime ruby-on-rails-3

我知道那里有几十个类似的问题,更不用说关于Interwebs的一般文章,但我仍然很难理解Rails如何在内部与Time Zones一起工作.

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

那么我目前的问题:

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

  2. 一个当将使用Time.nowTime.zone.nowTime.now.in_time_zoneDateTime.nowDateTime.now.in_time_zone

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

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

  5. (新问题)如果我改变,会发生什么config.time_zone,以UTC在以后的日子?我是否必须在数据库中重置所有时间,否则会影响旧时代?

Fre*_*ung 8

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

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

Q2.所有这些都返回一个代表'now'的对象.DateTime与时间的选择与时区无关.例如,如果您需要能够表示unix时期之外的时间,请使用DateTime.Time.now和之间的区别在于Time.zone.now您是否返回Time的实例(将在服务器的本地时区中作为控制器).这可以控制例如什么to_s返回但不表示什么时刻表示:

SomeModel.create(:time_attribute => Time.now)
SomeModel.create(:time_attribute => Time.zone.now)
Run Code Online (Sandbox Code Playgroud)

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

Q3.TimeWithZone通过比较日期的utc版本来实现比较方法,因此您可以安全地比较不同区域中的时间 - 您无需将它们转换为某个公共时区.您还可以将TimeWithZone实例与普通时间对象进行比较.

Q4.你通常不需要做任何事情.实现这一点的常用方法是published_at在模型上使用属性.显示列表文章的页面将添加一个

where('published_at <= ?', Time.now)
Run Code Online (Sandbox Code Playgroud)

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

这可能会因为纯粹的时间(例如'4pm')而变得复杂,因为时区转换只能在您知道日期时才能正确完成(即您知道确切的时间点),这取决于DST(或政治)像国家/地区更改时区的事件)与UTC更改的偏移量.在这种情况下,您通常只想存储一天中的时间,并且只有在您知道日期时才将其转换为尽可能晚的全时.

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