Rails: get #beginning_of_day in time zone

风流意气都作罢 提交于 2020-01-12 03:11:14

问题


I have a default time zone setup for the rails application. And an instance of the Date object.

How can I get make Date#beginning_of_day to return the beginning of the day in the specified time zone, but not my local timezone.

Is there any other method to get beginning of the day time in the specified timezone for the given date?

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"

回答1:


time_zone = Time.zone # any time zone really
time_zone.local(date.year, date.month, date.day)

Problem is, Date.beginning_of_day does not honor Time.zone in ActiveSupport 2.3

Compare https://github.com/rails/rails/blob/v2.3.11/activesupport/lib/active_support/core_ext/date/calculations.rb#L64 (AS 2.3)

to https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/calculations.rb#L74 and https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/zones.rb#L7 (AS 3)




回答2:


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



回答3:


Date#beginning_of_day will always return 00:00.

But as I understand you want to know time in other time zone while in current time zone is beginning of the day.

So. Let's find out beginning of the day in your current place. Imagine it is Paris, France:

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

Now lets found out what time is in Moscow:

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 

For different form now day:

# 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)

and converting Date to DateTime

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



回答4:


Going off Peder's answer, here's what I did for the PST time zone:

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



回答5:


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

Wed, 02 May 2012 00:00:00 UTC +00:00

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

=> Wed, 02 May 2012 00:00:00 MSK +04:00

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

=> Tue, 01 May 2012 00:00:00 AKDT -08:00

NOTICE, it's the WRONG DAY.

What is needed is a way to construct a TimeWithZone in the correct timezone.

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

I really dislike this, because as far as I can see, I've just changed the system notion of what zone I'm in. The idea is to change my database searches to match the zone of the client... So, I have to save zone and restore it:

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

It seems like I ought be able to call TimeWithZone.new(), but I didn't figure out how.




回答6:


I know this post is old, but what about:

Time.zone.parse("12am")



回答7:


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



回答8:


As Leonid Shevtsov mentioned, Date.beginning_of_day does not honor Time.zone in ActiveSupport 2.3

An alternative I used, if your stuck using Rails 4.0 or ActiveSupport 2.3, and you need to use a custom date:

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

Results:

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 

My original failed model scope using .beginning_of_day to .end_of_day failed to work:

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

And, this is what fixed it, since I could not upgrade to 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 ) }


来源:https://stackoverflow.com/questions/5419148/rails-get-beginning-of-day-in-time-zone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!