Ich versuche alle Zeitstempel in einer Rails-Anwendung mit ihrer Zeitzone zu speichern. Mir geht es gut mit ActiveRecord, das sie in utc umwandelt, aber ich habe mehrere Anwendungen, die dieselbe Datenbank treffen, von denen einige mit einer Zeitzonenanforderung implementiert werden. Also, was ich tun möchte, ist activerecord zu bekommen, um meine Zeitstempel wie üblich zu konvertieren, und sie dann in die Datenbank mit der Zeichenkette 'America / Los_Angeles' oder einer anderen geeigneten Zeitzone zu schreiben, die an den Zeitstempel angehängt wird. Ich laufe derzeit Rails 3.2.13 am jruby 1.7.8, welches den ruby 1.9.3 api implementiert. Meine Datenbank ist postgres 9.2.4, verbunden mit dem activerecord-jdbcpostgresql-adapter
Juwel. Der Spaltentyp ist ein Zeitstempel mit Zeitzone.
Ich habe die natürlichen Active-Record-Mappings bereits mit dem activerecord-native_db_types_override
gem geändert, indem ich die folgenden Zeilen zu meiner environment.rb hinzufüge:
Meine application.rb enthält derzeit
%Vor% Ich vermute, ich kann ActiveSupport::TimeWithZone.to_s
umschreiben und das Format ':: db' ändern, um die richtige Zeichenfolge auszugeben, aber das war noch nicht möglich. Jede Hilfe wird sehr geschätzt.
Postgres unterstützt nicht die Speicherung von Zeitzonen in einem seiner Datums- / Zeittypen .
Es gibt also einfach keine Möglichkeit, sowohl einen einzelnen Zeitpunkt als auch seine Zeitzone in einer Spalte zu speichern. Bevor ich eine alternative Lösung vorschlage, möchte ich das mit den Postgres-Dokumenten
Alle zeitzonenbewussten Daten und Uhrzeiten werden intern in UTC gespeichert. Sie werden in der vom TimeZone-Konfigurationsparameter angegebenen Zone in die lokale Zeit konvertiert, bevor sie dem Client angezeigt werden.
Es gibt also keinen guten Weg, die Zeitzone einfach an den Zeitstempel anzuhängen. Aber das ist nicht so schlimm, das verspreche ich! Es bedeutet nur, dass Sie eine andere Spalte benötigen.
Meine (eher einfache) vorgeschlagene Lösung:
Angenommen, Sie benötigen dies in der Spalte explodes_at
:
Wenn Sie die Zeitzone automatisch speichern möchten, überschreiben Sie Ihren Setter:
%Vor% Um sicherzustellen, dass t.zone die richtige Zeitzone zurückgibt, muss Time.zone auf die richtige Zone eingestellt werden. Sie können Time.zone
für jede Anwendung, jeden Benutzer oder jedes Objekt leicht variieren, indem Sie einen Around-Filter (Railscast) verwenden. . Es gibt viele Möglichkeiten, dies zu tun. Ich mag den Ansatz von Ryan Bates, also implementieren Sie ihn auf eine Weise, die für Ihre Anwendung sinnvoll ist.
Und wenn Sie sich etwas einfallen lassen wollen und diesen Getter für mehrere Spalten benötigen, können Sie alle Ihre Spalten durchlaufen und für jede Datetime eine Methode definieren:
%Vor%Dies beinhaltet keine Setter-Methode, weil Sie nicht wirklich wollen, dass jede einzelne datetime-Spalte in self.time_zone schreiben kann. Sie müssen entscheiden, wo dies verwendet wird. Und wenn Sie wirklich möchten, können Sie dies für alle Ihre Modelle implementieren, indem Sie sie innerhalb eines Moduls definieren und in jedes Modell importieren.
%Vor%Hier ist eine ähnliche hilfreiche Antwort: Ignorieren von Zeitzonen in Rails und PostgreSQL
Hoffe, das hilft!
Darf ich vorschlagen, sie in iso8601 zu speichern
Damit können Sie:
Internationale Standards einhalten
Verwenden Sie in beiden Fällen das gleiche Speicherformat mit Offset und ohne.
Eine der db-Spalten kann also nur in UTC-Form mit einem Offset versehen sein (üblich).
Von der Ruby-Seite ist es so einfach wie
%Vor%ActiveRecord sollte nahtlos mit der Konvertierung funktionieren.
Außerdem verwenden die meisten APIs dieses Format (google), daher am besten für die Kompatibilität mit verschiedenen Apps.
to_char () für postgresql sollte Ihnen das richtige Format für den Fall geben, dass ein Fehler in der Standardkonfiguration auftritt.
Ein Ansatz, wie Sie vorschlagen, wäre es, ActiveSupport::TimeWithZone.to_s
Sie könnten so etwas versuchen:
%Vor% Ich habe das nicht getestet, aber Postgres-Dokumente auf Zeitmarken , das sieht gut aus und würde eine Zeit geben wie: "2013-12-26 10:41:50 +0000"
Das Problem dabei ist, soweit ich das beurteilen kann, dass Sie immer noch Schwierigkeiten haben, die richtige Zeitzone zurückzugeben:
Für Zeitstempel mit Zeitzone ist der intern gespeicherte Wert immer in UTC (Universal Coordinated Time, traditionell als Greenwich Mean Time, GMT bekannt). Ein Eingabewert, für den eine explizite Zeitzone angegeben ist, wird mit dem entsprechenden Offset für diese Zeitzone in UTC konvertiert.
Genau das tut das ursprüngliche ActiveSupport::TimeWithZone.to_s
bereits.
Der beste Weg, um die richtige Zeitzone zu erhalten, ist vielleicht, einen expliziten Zeitzonenwert als neue Spalte in der Datenbank festzulegen.
Dies würde bedeuten, dass Sie die native Date-Funktionalität von Postgres und Rails beibehalten könnten, während Sie auch die Zeit in der richtigen Zeitzone anzeigen könnten, falls erforderlich.
Sie könnten diese neue Spalte verwenden, um dann die richtige Zone mit Rubys Time::getlocal
oder Rails ' ActiveSupport::TimeWithZone.in_time_zone
' anzuzeigen.
Tags und Links ruby ruby-on-rails-3 ruby-on-rails activerecord postgresql