Hilfe grokking Zeit - und Zeitzonen in Rails 3

8

Ich weiß, dass es ein paar Dutzend ähnliche Fragen gibt, ganz zu schweigen von unzähligen Artikeln über die Interwebs im Allgemeinen, aber es fällt mir immer noch schwer zu verstehen, wie Rails intern mit Time Zones arbeitet.

Ich habe derzeit config.time_zone = 'Eastern Time (US & Canada)' in meiner Anwendungsdatei konfiguriert, da ich und die anderen Projektadministratoren dort sind. Das Unternehmen, das die Website besitzt, hat seinen Sitz in Kalifornien und wird daher in der Pazifik-Zeit sein. Die Anwendung hat eine globale Zielgruppe und solange wir dies noch nicht getan haben, werden wir eventuell vom Benutzer bevorzugte Zeitzonen implementieren.

Also meine aktuellen Fragen:

  1. Ich weiß, dass Rails magisch Datetime-Spaltenwerte in und von UTC transformiert, wenn sie jeweils gespeichert und abgerufen werden, aber was ist die richtige Methode, um die lokale Version eines bestimmten Datetime-Attributs anzuzeigen?

  2. Wann würde man Time.now gegen Time.zone.now gegen Time.now.in_time_zone gegen DateTime.now gegen DateTime.now.in_time_zone verwenden?

  3. Was ist der richtige Weg, um ein bestimmtes datetime-Attribut mit den oben genannten Methoden oder einer anderen spezifischen Zeit im Verhältnis zur aktuell konfigurierten Zeitzone zu vergleichen? Mit UTC?

  4. Wir werden einige zeitkritische Dinge wie Artikel haben, die zu einer bestimmten Zeit entsprechend der Zeitzone der Anwendung veröffentlicht werden müssen, also wie kann ich die Anwendung diesen Vergleich in unserer spezifizierten Zeitzone machen, im Gegensatz zu der aktuell konfiguriert (unter der Annahme, dass ein Benutzer Zeitzonen implementiert?)

  5. ( Neue Frage ) Was passiert, wenn ich zu einem späteren Zeitpunkt config.time_zone in UTC ändere? Muss ich alle meine Zeiten in der Datenbank zurücksetzen oder beeinflusst es sonst alte Zeiten?

Chris Bloom 27.06.2011, 16:18
quelle

1 Antwort

8

Zuallererst ist es wichtig zu verstehen, dass es bei rails 'timezone stuff hauptsächlich um Präsentation geht. Hinter den Kulissen passiert alles in UTC.

Q1. Auf der Konsole zeigt Rails Zeiten in Ihrer Standardzeitzone an, so dass Something.last.created_at diesen Zeitstempel in der von Time.zone

angegebenen Zone anzeigt

Q2. Alle diese geben ein Objekt zurück, das 'jetzt' darstellt. Die Wahl von DateTime gegen Time steht nicht im Zusammenhang mit Zeitzonen. Wenn Sie z. B. Zeiten außerhalb der Unix-Epoche darstellen können, verwenden Sie DateTime. Der Unterschied zwischen Time.now und Time.zone.now besteht darin, ob Sie eine Instanz von Time zurückbekommen (die sich in der lokalen Zeitzone des Servers als Controller befindet). Dies steuert beispielsweise, was to_s zurückgibt, aber nicht, welcher Zeitpunkt in der Zeit dargestellt wird:

%Vor%

fügt dieselbe Zeile in die Datenbank ein. Wenn Sie dem Benutzer nur eine Zeit anzeigen (wenn Ihre Website z. B. die aktuelle Uhrzeit in der Kopfzeile anzeigt), sollten Sie Time.zone.now verwenden, damit sie in der richtigen Zeitzone angezeigt wird. Wenn Sie es nur in der db speichern, ist es nicht wirklich wichtig - activerecord konvertiert es trotzdem in eine TimeWithZone.

Q3. Die Vergleichsmethoden in TimeWithZone werden implementiert, indem die utc-Version des Datums verglichen wird, sodass Sie Zeiten in verschiedenen Zonen vergleichen können. Sie müssen sie nicht in eine gemeinsame Zeitzone konvertieren. Sie können TimeWithZone-Instanzen auch mit einfachen Zeitobjekten vergleichen.

Q4. Sie müssen normalerweise nichts tun. Eine gängige Methode zur Implementierung wäre ein Attribut published_at in Ihrem Modell. Seiten, die die Listenartikel anzeigen, würden ein

hinzufügen %Vor%

Bedingung für die Abfrage. Wenn Sie Ihren Artikel erstellen, nimmt Rails die Datumszeit aus dem Formular und konvertiert sie in utc. Daher wird in der Datenbank die Version dieser published_at -Zeit gespeichert. Vergleiche sind zeitzonenunabhängig, so dass die Abfrage unabhängig von der Zeitzone funktioniert.

Dies kann mit reinen Tageszeitdaten (zB '4pm') kompliziert werden, da eine Zeitzonenumrechnung nur dann richtig durchgeführt werden kann, wenn Sie das Datum kennen (dh Sie kennen den genauen Zeitpunkt), abhängig von der Sommerzeit (oder politische Ereignisse wie Länder, die ihre Zeitzone ändern) die Abweichung von UTC-Änderungen. In einer solchen Situation möchten Sie normalerweise nur die Uhrzeit speichern und erst so spät wie möglich in eine Vollzeit umwandeln, wenn Sie das Datum ebenfalls kennen.

Q5. Rails speichert UTC immer in der Datenbank. Eine direkte Konsequenz daraus ist, dass das Ändern von config.time_zone nicht erfordert, dass Sie die in der Datenbank gespeicherten Daten ändern müssen. Sie können Time.zone sogar pro Benutzer festlegen, so dass Benutzer Zeiten in ihrer Zeitzone sehen - config.time_zone steuert nur den Standardwert von Time.zone

    
Frederick Cheung 11.08.2012, 12:35
quelle