2009-09-06 7 views
90

Мои created_at метки времени хранятся в формате UTC:Преобразование времени из одного часового пояса в другой в Rails

>> Annotation.last.created_at 
=> Sat, 29 Aug 2009 23:30:09 UTC +00:00 

Как превратить один из них в «Восточное время (США & Канада)» (с учетом дневного света экономия)? Что-то вроде:

Annotation.last.created_at.in_eastern_time 

ответ

159

Используйте метод in_time_zone класса DateTime

Loading development environment (Rails 2.3.2) 
>> now = DateTime.now.utc 
=> Sun, 06 Sep 2009 22:27:45 +0000 
>> now.in_time_zone('Eastern Time (US & Canada)') 
=> Sun, 06 Sep 2009 18:27:45 EDT -04:00 
>> quit 

Таким образом, для вашего конкретного примера

Annotation.last.created_at.in_time_zone('Eastern Time (US & Canada)') 
+6

или вы можете просто использовать час идент 'now.in_time_zone (3)' ' – fl00r

+7

created_at.in_time_zone («EST») 'короче – Orlando

+40

« EST »=« Восточное стандартное время », поэтому это будет неправильно во время летнего времени. «Восточное время (США и Канада)» показывает, является ли это DST или нет для вас. – jhiro009

2

Установите часовой пояс Восточное время.

Вы можете установить часовой пояс по умолчанию в конфиге/environment.rb

config.time_zone = "Eastern Time (US & Canada)" 

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

class ApplicationController < ActionController::Base 

    before_filter :set_timezone 

    def set_timezone 
    Time.zone = current_user.time_zone 
    end 
end 

Просто убедитесь, что вы сохраняете все свое время в базе данных как UTC, и все будет сладко.

+2

Я бы избегал 'Time.zone = ..'поскольку он не является потокобезопасным. – gertas

+0

Имеет ли это значение, если вы используете сервер приложений, например, дворняжку, тонкую или пассажирскую? Я считаю, что они запускают более одного экземпляра, с одним потоком? Возможно, я ошибаюсь, хотел бы узнать! – nitecoder

+4

'Time.zone =' является потокобезопасным https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/time/zones.rb#L36-38. – lest

8

Если добавить к вашему /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)' 

Затем вы можете клеточные

Annotation.last.created_at.in_time_zone 

, чтобы получить время в указанном часовом поясе.

14

Хотя это старый вопрос, стоит упомянуть что-то. В previous reply предлагается использовать параметр before_filter, чтобы временно установить часовой пояс.

Вы должны Никогда, никогда не делайте этого, потому что Time.zone хранит информацию в потоке, и это, вероятно, будет утечка в следующий запрос, обрабатываемый этим потоком.

Вместо этого вы должны использовать round_filter, чтобы убедиться, что Time.zone сбрасывается после завершения запроса. Что-то вроде:

around_filter :set_time_zone 

private 

def set_time_zone 
    old_time_zone = Time.zone 
    Time.zone = current_user.time_zone if logged_in? 
    yield 
ensure 
    Time.zone = old_time_zone 
end 

Подробнее об этом here

+0

В настоящее время существует хороший метод [Time.use_zone] (https://apidock.com/rails/Time/use_zone/class). – freemanoid

2

Если настроить /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)' 

Time.now.in_time_zone 

DateTime.now.in_time_zone