Rails:在时区中获得#beginning_of_day

时间:2011-03-24 12:33:12

标签: ruby-on-rails date timezone activesupport ruby-on-rails-2

我为rails应用程序设置了默认时区。 和Date对象的一个​​实例。

如何让Date#beginning_of_day返回指定时区内的一天的开头,而不是我当地的时区。

是否有其他方法可以在给定日期的指定时区内开始白天时间?

date = Date.new(2014,10,29)

zone = ActiveSupport::TimeZone.new('CET')
date.foo(zone) # should return "Wed, 29 Oct 2014 00:00:00 CET +01:00"

zone = ActiveSupport::TimeZone.new('UTC')
date.foo(zone) # should return "Wed, 29 Oct 2014 00:00:00 UTC +00:00"

8 个答案:

答案 0 :(得分:38)

DateTime.now.in_time_zone(Time.zone).beginning_of_day

答案 1 :(得分:20)

答案 2 :(得分:9)

Date#beginning_of_day将始终返回00:00。

但据我了解,您想知道其他时区的时间,而当前时区是当天的开始。

因此。让我们在你当前的地方找到一天的开始。想象一下,它是法国巴黎:

bd = DateTime.now.in_time_zone('Paris').beginning_of_day
# or just
bd = DateTime.now.in_time_zone(1).beginning_of_day
#=> Thu, 24 Mar 2011 00:00:00 WET +01:00

现在让我们了解莫斯科的时间:

moscow_time = bd.in_time_zone("Moscow") # or in_time_zone(3)
#=> Thu, 24 Mar 2011 02:00:00 AST +03:00
london_time = bd.in_time_zone("London")
#=> Wed, 23 Mar 2011 23:00:00 GMT +00:00
kyiv_time = bd.in_time_zone("Kyiv")
#=> Thu, 24 Mar 2011 01:00:00 EET +02:00 

对于不同形式的now天:

# You even shouldn't call now, because it by default will be 00:00
date = DateTime(2011, 1, 3).in_time_zone("-10")
# or
date = DateTime.new(2011,1,3,0,0,0,"-10")
# and same way as above
moscow_time = date.in_time_zone("Moscow") # or in_time_zone(3)

并将Date转换为DateTime

date = Date.new(2011,1,3).to_datetime.change(:offset => "EST")

答案 3 :(得分:2)

关闭Peder的回答,这是我为PST时区做的事情:

DateTime.now.in_time_zone("Pacific Time (US & Canada)").beginning_of_day

答案 4 :(得分:1)

may2 = Date.new(2012,5,2)
midnight = Time.zone.local(may2.year,may2.month,may2.day).beginning_of_day

2012年5月2日星期三00:00:00 UTC +00:00

midnight = Time.zone.local(may2.year,may2.month,may2.day).in_time_zone("Moscow").beginning_of_day

=> 2012年5月2日星期三00:00:00 MSK +04:00

midnight = Time.zone.local(may2.year,may2.month,may2.day).in_time_zone("Alaska").beginning_of_day

=>星期二,01五月2012 00:00:00 AKDT -08:00

通知,这是错误的一天。

我们需要一种在正确的时区内构建TimeWithZone的方法。

Time.zone="Alaska"
midnight = Time.zone.local(may2.year,may2.month,may2.day)

我真的不喜欢这个,因为据我所见,我刚刚更改了我所在区域的系统概念。我的想法是更改我的数据库搜索以匹配客户区... 所以,我必须保存区域并恢复它:

foo = Time.zone; Time.zone="Alaska"; midnight = Time.zone.local(may2.year,may2.month,may2.day); Time.zone = foo

好像我应该能够调用TimeWithZone.new(),但我没弄清楚如何。

答案 5 :(得分:1)

我知道这篇文章很老了,但是呢:

Time.zone.parse("12am")

答案 6 :(得分:0)

ActiveSupport::TimeZone['Europe/London'].parse('30.07.2013') # 2013-07-29 23:00:00 UTC 
ActiveSupport::TimeZone['Asia/Magadan'].parse('30.07.2013') # 2013-07-29 12:00:00 UTC

答案 7 :(得分:0)

正如Leonid Shevtsov所说,Date.beginning_of_day不尊重ActiveSupport 2.3中的Time.zone

我使用的替代方法,如果您使用Rails 4.0或ActiveSupport 2.3,并且您需要使用自定义日期:

date = Date.new(2014,10,29)
date.to_time.change(hour: 0, min: 0, sec: 0).in_time_zone  #.beginning_of_day
date.to_time.change(hour: 23, min: 59, sec: 59).in_time_zone #.end_of_day

结果:

2.0.0-p247 :001 > date = Date.new(2014,10,29)
 => Wed, 29 Oct 2014 

2.0.0-p247 :002 > date.to_time.change(hour: 0, min: 0, sec: 0)
 => 2014-10-29 00:00:00 -0500 

2.0.0-p247 :003 > date.to_time.change(hour: 0, min: 0, sec: 0).in_time_zone
 => Wed, 29 Oct 2014 05:00:00 UTC +00:00 

2.0.0-p247 :004 > date.to_time.change(hour: 23, min: 59, sec: 59)
 => 2014-10-29 23:59:59 -0500 

2.0.0-p247 :005 > date.to_time.change(hour: 23, min: 59, sec: 59).in_time_zone
 => Thu, 30 Oct 2014 04:59:59 UTC +00:00 

我使用.beginning_of_day到.end_of_day的原始失败模型范围无效:

scope :on_day, ->(date) { where( created_at: date.beginning_of_day..date.end_of_day ) }

而且,这就是修复它的原因,因为我无法升级到Rails 4.0

scope :on_day, ->(date) { where( created_at: date.to_time.change(hour: 0, min: 0, sec: 0).in_time_zone..date.to_time.change(hour: 23, min: 59, sec: 59).in_time_zone ) }