Rails: получить #beginning_of_day в часовом поясе - PullRequest
21 голосов
/ 24 марта 2011

У меня есть настройка часового пояса по умолчанию для приложения rails.И экземпляр объекта Date.

Как я могу получить make Date # begin_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 ]

39 голосов
/ 21 сентября 2011
DateTime.now.in_time_zone(Time.zone).beginning_of_day
20 голосов
/ 24 марта 2011
time_zone = Time.zone # any time zone really
time_zone.local(date.year, date.month, date.day)

Проблема в том, Date.beginning_of_day не соблюдает Time.zone в ActiveSupport 2.3

Сравнить https://github.com/rails/rails/blob/v2.3.11/activesupport/lib/active_support/core_ext/date/calculations.rb#L64 (AS 2.3)

до https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/calculations.rb#L74 а также https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/zones.rb#L7 (AS 3)

9 голосов
/ 24 марта 2011

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")
2 голосов
/ 07 апреля 2016

Отходя от ответа Педера, вот что я сделал для часового пояса PST:

DateTime.now.in_time_zone("Pacific Time (US & Canada)").beginning_of_day
1 голос
/ 20 февраля 2017

Я знаю, что этот пост старый, но как насчет:

Time.zone.parse("12am")
1 голос
/ 31 января 2013
may2 = Date.new(2012,5,2)
midnight = Time.zone.local(may2.year,may2.month,may2.day).beginning_of_day

Ср, 02 мая 2012 г. 00:00:00 UTC +00: 00

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

=> Ср, 02 мая 2012 г. 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)

Мне очень не нравится это, потому что, насколько я могу видеть, я только что изменил system понятие, в какой зоне я нахожусьИдея состоит в том, чтобы изменить поиск в моей базе данных в соответствии с зоной клиента ... Итак, я должен сохранить зону и восстановить ее:

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

Похоже, я должен быть в состоянии вызвать TimeWithZone.new (), но я не понял, как.

0 голосов
/ 18 февраля 2016

Как отметил Леонид Шевцов, Date.beginning_of_day не соблюдает Time.zone в ActiveSupport 2.3

Альтернатива, которую я использовал, если вы застряли с использованием 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 ) }
0 голосов
/ 29 июля 2013
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
...