Konvertieren Sie die Zeit in Rails von einer Zeitzone in eine andere

105

Meine created_atZeitstempel werden in UTC gespeichert:

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

Wie konvertiere ich eine davon in "Eastern Time (USA & Kanada)" (unter Berücksichtigung der Sommerzeit)? Etwas wie:

Annotation.last.created_at.in_eastern_time
Tom Lehman
quelle

Antworten:

191

Verwenden Sie die Methode in_time_zone der DateTime-Klasse

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

Also für Ihr spezielles Beispiel

Annotation.last.created_at.in_time_zone('Eastern Time (US & Canada)')
Steve Weet
quelle
7
oder Sie können einfach die now.in_time_zone(3)
Stundenidentifikation
8
created_at.in_time_zone("EST")ist kürzer
Orlando
51
"EST" = "Eastern Standard Time", daher ist es während der Sommerzeit falsch. "Eastern Time (USA & Kanada)" findet heraus, ob es Sommerzeit für Sie ist oder nicht.
jhiro009
1
Beachten Sie, dass die Methode in_time_zone Teil von ActiveSupport ist und daher in Rails integriert ist, jedoch nicht Teil der Ruby stdlib. Wenn Sie eine Rails-App haben, kein Problem. Wenn Sie eine reine Ruby-App haben, müssen Sie sicher sein, dass Sie aktiven Support benötigen.
Gayle
Der Link zur Dokumentation für diese Methode ist hier: apidock.com/rails/DateTime/in_time_zone
Naved Khan
17

Obwohl dies eine alte Frage ist, ist es wert, etwas zu erwähnen. In einer früheren Antwort wurde empfohlen, einen before_filter zu verwenden, um die Zeitzone zeitlich festzulegen.

Sie sollten dies niemals tun, da Time.zone die Informationen im Thread speichert und sie wahrscheinlich an die nächste von diesem Thread behandelte Anforderung weiterleiten.

Verwenden Sie stattdessen einen around_filter, um sicherzustellen, dass die Time.zone nach Abschluss der Anforderung zurückgesetzt wird. Etwas wie:

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

Lesen Sie mehr dazu hier

opsidao
quelle
1
Heutzutage gibt es eine nette Time.use_zone- Methode.
Freemanoid
9

Wenn Sie dies zu Ihrem hinzufügen /config/application.rb

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

Dann können Sie Zelle

Annotation.last.created_at.in_time_zone

um die Zeit in der angegebenen Zeitzone zu erhalten.

Eifion
quelle
Wenn wir die Zeitzone in application.rb konfigurieren, müssen Sie nicht ".in_time_zone" aufrufen. Schienen tun es automatisch für uns jyst müssen Annotation.last.created_at
Vishal
3

Wenn Sie Ihre konfigurieren /config/application.rb

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

Time.now.in_time_zone

DateTime.now.in_time_zone
Dorian
quelle
2

Stellen Sie Ihre Zeitzone auf Eastern Time ein.

Sie können Ihre Standardzeitzone in config / environment.rb festlegen

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

Jetzt befinden sich alle Datensätze, die Sie herausziehen, in dieser Zeitzone. Wenn Sie unterschiedliche Zeitzonen benötigen, z. B. basierend auf einer Benutzerzeitzone, können Sie diese mit einem before_filter in Ihrem Controller ändern.

class ApplicationController < ActionController::Base

  before_filter :set_timezone

  def set_timezone
    Time.zone = current_user.time_zone
  end
end

Stellen Sie einfach sicher, dass Sie alle Ihre Zeiten in der Datenbank als UTC speichern und alles wird süß.

Nitecoder
quelle
Ist dies wichtig, wenn Sie einen Anwendungsserver wie Mischling, Thin oder Passagier ausführen? Sie führen mehr als eine Instanz aus, Single-Threaded, glaube ich? Ich kann mich irren, würde gerne wissen!
Nitecoder
4
Time.zone=ist threadsicher github.com/rails/rails/blob/master/activesupport/lib/… .
damit
Es kann nicht in '09 gewesen sein?
Nitecoder
2
@jpwynn: Demnach: github.com/rails/rails/commit/… es ist seit mehr als 5 Jahren threadsicher. Irgendeine Quelle oder ein Beispiel für Ihr Problem?
Pascal
1
Ein Thread kann mehrere Sitzungen bedienen. Wenn Sie es einmal festlegen, wenn der Benutzer angemeldet ist, legt beispielsweise der LETZTE Benutzer, der sich anmeldet, die Zeitzone für ALLE Benutzer fest, deren Sitzung denselben Thread verwendet. Sie MÜSSEN also einen before_filter verwenden, um ihn für jeden Benutzer bei jedem Laden der Seite festzulegen.
JPW