2016-01-28 2 views
1

Я запустил сайт планирования, который позволяет пользователям устанавливать часовой пояс для своей учетной записи. Затем они могут планировать «сообщения» в календаре для этого часового пояса. В фоновом режиме я трачу время и конвертирую его в UTC (где рабочий обрабатывает и собирает эти сообщения в UTC).Ruby Timezones - to UTC и обратно

Я запустил сайт на Ruby (с Puma/Sinatra), но без Rails, и я хотел бы держаться подальше от Rails. Впереди есть HTML/ERB/​​JS и бэкэнд MYSQL.

Я думал, что простое добавление/вычитание смещений UTC решит все проблемы. У меня есть простой список, который имеет TIMEZONE <--> UTCOFFSET, и это сработало очень хорошо - или так я думал.

И тогда я понял, что это не работает, когда данный часовой пояс (или место) находится в DST в настоящее время.

Вена летом: UTC смещение: + 2h

Вена зимой: UTC смещение: + 1ч

Есть простой способ дать Руби (не Rails) а " timezone ID "и получить правильное скорректированное смещение UTC назад?

Как:

user.timezone = "Europe/Vienna" 
utc_adjusted_time = post.local_time.to_i + get_utc_offset(user.timezone) 

Где get_utc_offsetзнает ли это в DST или нет. Есть идеи?

Я прошел через базу данных IANA (что является абсолютным излишеством), я обыскал множество Гистов в Github, я пытался злоупотреблять тем, что казалось Rails, но не очень далеко.

Как вы, парни, справляетесь с этим? В идеале, как сказано, каждое сообщение будет преобразовано и сохранено в время UTC, разделенное на DST. Благодаря!

+1

'get_utc_offset' должен знать, находится ли он в DST * для local_time *. Не сейчас. В принципе, вам нужен правильный часовой пояс, например. http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html - но это похоже на Rails. (Я не человек Ruby, поэтому могут быть некоторые наивные предположения вокруг того, что вы можете использовать). Обратите внимание, что локальное отображение UTC может быть невозможным или неоднозначным, если локальное время находится вокруг перехода DST. (например, при переходе вперед, 1:30 утра может вообще не существовать, когда падение назад 1:30 может происходить дважды). Вам нужно выработать свое желаемое поведение. –

+0

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

+1

_Offtopic_: примечания к выпуску Ruby 1.6 содержат комментарий комментировать от Matz: https://speakerdeck.com/skade/the-dark-side-of-matz-1?slide=11 – mudasobwa

ответ

0

Просто используйте Ruby TZInfo gem.

Ваш случай использования точно показанный in the readme:

require 'tzinfo' 

tz = TZInfo::Timezone.get('America/New_York') 
local = tz.utc_to_local(Time.utc(2005,8,29,15,35,0)) 

utc = tz.local_to_utc(local) 

period = tz.period_for_utc(Time.utc(2005,8,29,15,35,0)) 
id = period.zone_identifier 

Глядя на документы для TZInfo::TimePeriod вы можете увидеть другую информацию, которую вы просили о:

period.offset 
period.dst? 

... и т.д.

FYI - поддержка часовых поясов Rails основана на этом драгоценном камне в любом случае. Затем Rails идет и накладывает на верхнюю часть фальшивого сглаживания (что я советую не использовать). См. Раздел о Rails в the timezone tag wiki.