7

我们来看看日期:

1.9.2p320 :008 > Date.today
 => Wed, 03 Oct 2012 
1.9.2p320 :009 > Time.now
 => 2012-10-03 22:32:55 -0400

现在,考虑到午夜是什么时候?

1.9.2p320 :005 > Date.today.midnight
 => Wed, 03 Oct 2012 00:00:00 UTC +00:00 

说得通。但是昨天呢?

1.9.2p320 :006 > Date.yesterday.midnight
 => Wed, 03 Oct 2012 00:00:00 UTC +00:00 

呃,这完全没有意义。今天的午夜和昨天的午夜一样吗?你不能是认真的!

1.9.2p320 :026 > Date.today.midnight == Date.yesterday.midnight
 => true 
1.9.2p320 :033 > 1.day.ago.midnight == Date.yesterday.midnight
 => true 
1.9.2p320 :034 > 1.day.ago.midnight == Date.today.midnight
 => true 

哦,你是认真的。明天怎么样?

1.9.2p320 :007 > Date.tomorrow.midnight
 => Fri, 05 Oct 2012 00:00:00 UTC +00:00 

等等,如果今天午夜是 3 日 00:00,昨天午夜是 3 日 00:00,但明天午夜是 5 日 00:00,那么 4 日 00:00 呢?

这里是:

1.9.2p320 :010 > 0.days.ago
 => Thu, 04 Oct 2012 02:34:58 UTC +00:00 
1.9.2p320 :011 > 0.days.ago.midnight
 => Thu, 04 Oct 2012 00:00:00 UTC +00:00

但今天不是零天前吗?显然不是。

是我,还是这根本不是内部一致的?在我看来 Date.today 应该与 0.days.ago 相同。

我知道这days.ago实际上是在使用 Time 对象,这是一个时区问题:

1.9.2p320 :030 > Date.today
 => Wed, 03 Oct 2012 
1.9.2p320 :021 > Time.now
 => 2012-10-03 22:40:09 -0400 
1.9.2p320 :023 > 0.days.ago
 => Thu, 04 Oct 2012 02:40:22 UTC +00:00 
1.9.2p320 :022 > Time.zone.now
 => Thu, 04 Oct 2012 02:40:14 UTC +00:00 

但似乎,鉴于这些是便利函数,将时区假设扔到一个便利函数中而不是将其扔到另一个便利函数中是一种意思,从所有角度来看,两者都意味着同一件事。

即使撇开这一点不谈,它似乎也无法解释这样一个事实Date.today.midnight == Date.yesterday.midnight,即——很简单——狂吠。

既然我知道我不可能是第一个被这个咬伤的人,我问我错过了什么?

4

2 回答 2

8

Rails 将基于相对日期计算,例如yesterday,tomorrowmidnightoffDate.current其中将尝试使用配置的Time.zonehttps ://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/calculations.rb #L46

由于您Time.zone设置为 UTC,因此您不会得到与基于 off 的计算相同的结果Date.today,后者将使用您计算机的时钟时间,除非您实际上处于 UTC 时间。

所以,如果你和UTC的时间差大于到午夜的时间,Date.yesterday实际上Date.today返回的是同一个日期!

尝试使用您所在的任何时区设置 Rails 时区Time.zone = 'Eastern Time (US & Canada)',然后重试您的示例。

于 2012-10-04T03:14:02.247 回答
1

rossta确定了罪魁祸首。Time.now.to_date如有必要,您可能会更好地使用并指定时区:

> Time.now.in_time_zone("Asia/Tokyo")
  => Thu, 04 Oct 2012 12:54:43 JST +09:00 
> Time.now.in_time_zone("Asia/Tokyo").to_date.midnight
 => Thu, 04 Oct 2012 00:00:00 JST +09:00 
Time.now.in_time_zone("Asia/Tokyo").to_date.yesterday.midnight
 => Wed, 03 Oct 2012 00:00:00 JST +09:00 

> Time.zone = "America/Los_Angeles"
 => "America/Los_Angeles" 
> Time.now.in_time_zone
 => Wed, 03 Oct 2012 20:55:35 PDT -07:00 

> Time.now.to_date # using the system time
 => Wed, 03 Oct 2012 
> Time.now.to_date.midnight
 => Wed, 03 Oct 2012 00:00:00 PDT -07:00 
> Time.now.to_date.yesterday.midnight
 => Tue, 02 Oct 2012 00:00:00 PDT -07:00 
于 2012-10-04T04:03:14.313 回答