2015-08-28 5 views
4

Я работаю над приложением Rails, где мне нужно найти даты начала и окончания летнего времени с учетом определенного смещения или часового пояса.Дата начала и окончания летнего времени в Ruby/Rails

Я в основном сохраняю в своей базе данных смещение временной зоны, полученное от браузера пользователя ("+3", "-5"), и я хочу изменить его, когда он изменится из-за летнего времени.

Я знаю Time переменные экземпляра имеют методы dst? и isdst, которые возвращают true или false, если сохраненная в них дата находится в летнее время или нет.

> Time.new.isdst 
=> true 

Но использовать это, чтобы найти даты начала и окончания Переход на летнее время заняло бы слишком много ресурсов, и я должен сделать это для каждой временной зоны смещения у меня есть.

Я хотел бы знать лучший способ сделать это.

+0

Так что оглядываясь на то, что вы делаете, приходит на ум. Вы храните только их смещение. Но это смещение от ВАШЕГО времени или от UTC? Если смещение является UTC, то DST не вступает в игру, если они не находятся в зоне, которая соблюдает DST.Или это смещение, отличное от твоего, и еще раз, знаете ли вы, наблюдают ли они DST или нет? Если ваше местное время изменяется из-за DST и их тоже, то смещение остается неизменным. – Beartech

+0

Я вижу некоторые возможные проблемы с тем, как вы это делаете. Просто потому, что смещение человека ставит их в западную часовую зону США, не говорит вам, наблюдают ли они DST. Большая часть Аризоны не наблюдает за ДСТ. Заметьте, я говорю больше всего, не все. Вот почему вы, вероятно, захотите сохранить фактический часовой пояс в виде строки. – Beartech

+0

Позвольте мне подробнее рассказать об этом. Я работаю над солнечным калькулятором, который вычисляет углы углов солнца на каждый день в определенном месте на земном шаре. Приложение принимает координаты геолокации, дату и смещение временной зоны только один раз. На сервере я запускаю работу cron, которая каждый день обрабатывает возвышенность в полночь для каждого часового пояса (у меня могут быть пользователи из Нью-Йорка, Лондона, Москвы и т. Д.). – user3790827

ответ

2

Возможно, вы, вероятно, ищете TZInfo::TimezonePeriod. В частности, методы local_start/utc_start и local_end/utc_end.

Учитывая смещение часового пояса, вы можете получить TZInfo::TimezonePeriod объект с

ActiveSupport::TimeZone[-8].tzinfo.current_period 

Или, если у вас есть имя часового пояса, вы также можете получить TZInfo::TimezonePeriod объект с

ActiveSupport::TimeZone['America/Los_Angeles'].tzinfo.current_period 
+0

ах, ты избил меня к нему и с более простым примером. – Beartech

6

Хорошо, опираясь на что вы сказали и ответ @ dhouty:

Вы хотите, чтобы иметь возможность подавать в офсет и получать набор дат, зная, существует ли DST fset или нет. Я рекомендовал бы в конечном итоге с диапазоном из двух объектов DateTime, как легко использовать для многих целей в Rails ...

require 'tzinfo' 

def make_dst_range(offset) 

    if dst_end = ActiveSupport::TimeZone[offset].tzinfo.current_period.local_end 
    dst_start = ActiveSupport::TimeZone[offset].tzinfo.current_period.local_start 
    dst_range = dst_start..dst_end 
    else 
    dst_range = nil 
    end 

end 

Теперь у вас есть метод, который может сделать больше, чем просто взять смещение благодаря сахар, который поставляется с ActiveSupport. Вы можете сделать что-то вроде:

make_dst_range(-8) 
#=> Sun, 08 Mar 2015 03:00:00 +0000..Sun, 01 Nov 2015 02:00:00 +0000 

make_dst_range('America/Detroit') 
#=> Sun, 08 Mar 2015 03:00:00 +0000..Sun, 01 Nov 2015 02:00:00 +0000 

make_dst_range('America/Phoenix') 
#=> nil  #returns nil because Phoenix does not observe DST 

my_range = make_dst_range(-8) 
#=> Sun, 08 Mar 2015 03:00:00 +0000..Sun, 01 Nov 2015 02:00:00 +0000 

Сегодня случается 29 августа так:

my_range.cover?(Date.today) 
    #=> true 
my_range.cover?(Date.today + 70) 
    #=> false 
my_range.first 
    #=> Sun, 08 Mar 2015 03:00:00 +0000 
    #note that this is a DateTime object. If you want to print it use: 
my_range.first.to_s 
    #=> "2015-03-08T03:00:00+00:00" 
my_range.last.to_s 
    #=> "2015-11-01T02:00:00+00:00" 

ActiveSupport дает вам все виды лакомства для отображения:

my_range.first.to_formatted_s(:short) 
    #=> "08 Mar 03:00" 
my_range.first.to_formatted_s(:long) 
    #=> "March 08, 2015 03:00" 
my_range.first.strftime('%B %d %Y') 
    #=> "March 08 2015" 

Как вы можете видеть это полностью выполним только с помощью смещения, но, как я уже сказал, смещение не говорит вам всего, поэтому вы можете захотеть захватить их фактический часовой пояс и сохранить это как строку, так как метод будет с радостью принимать tha t string и по-прежнему дает вам диапазон дат. Даже если вы просто получаете временное смещение между своей зоной и их, вы можете легко вычислить правильность этого значения для смещения UTC:

my_offset = -8 
their_offset = -3 
utc_offset = my_offset + their_offset 
+0

Кажется хорошим предложением, я его поддержу, но я все равно оставлю вопрос открытым. – user3790827

+1

Этот ответ обычно получает мне несколько очков два раза в год. лол – Beartech

Смежные вопросы