2016-07-25 7 views
0

Ich habe einen Hintergrund-Job, der alle 15 Minuten läuft und generiert Erinnerungs-E-Mails. Ich möchte eine Abfrage erstellen, die alle Benutzer zurückgibt, die eine bestimmte Zeit gespeichert haben und respektieren, wie ihre Zeitzoneneinstellung diese Zeit beeinflusst.Rails: Abfrage Datenbank für Benutzer mit bestimmten Zeitwert unter Berücksichtigung der einzelnen Benutzer Zeitzone Einstellung

So habe ich ein User Modell, das speichert:

  • :time: eine Benutzer Erinnerungszeit, zB 17:00:00
  • :string: ihre Zeitzone, zB EST

Also, wenn der Auftrag ausgeführt 17:00:00 EST, gibt es Benutzer mit folgenden Einstellungen zurück:

  • reminder_time: 17:00:00, time_zone: EST
  • reminder_time: 13:00:00, time_zone: PST

Was ist der beste Weg, um die Abfrage zu erstellen? Kann es in einem einzigen Schritt erledigt werden, wenn man sich darauf verlässt, dass Postgres mit der Arbeit fertig wird? Muss ich es staffeln, nach jeder Zeitzone gruppieren und für jeden in Ruby rechnen?

Ich habe derzeit dieses Setup als Bereich, die Zeitzonen nicht berücksichtigt, und ich versuche, diese Überlegung jetzt hinzuzufügen.

scope :receives_reminder_at, -> (time) do 
    ready.where(reminder_time: time) 
end 
+1

speichern nur die REMINDER_TIME in UTC, auf diese Weise müssen Sie über die TZ keine Sorge bei der Abfrage, da werden sie alle UTC normalisiert werden. (Vorausgesetzt, Sie laufen Ihre Server UTC. Es wird nur wie erwartet funktionieren). Dann verwenden Sie einfach ihren TZ-Offset, um die Zeit für das Anzeigen einzustellen? – Doon

+0

Ich wollte gerade das als Antwort schreiben, nachdem ich mit einem Kumpel von mir gesprochen hatte. Setzen Sie das als eine Antwort unten, und ich werde sicher sein, es zu markieren – mattmcmanus

Antwort

1

Wenn es sich um Benutzer in mehreren Zeitzonen handelt, ist es normalerweise am einfachsten, auf UTC zu standardisieren.

Speichern Sie also die reminder_time in UTC, damit Sie sich bei der Abfrage keine Sorgen um die TZ machen müssen, da sie alle auf UTC normalisiert werden. (Vorausgesetzt, Sie laufen Ihre Server UTC. Es wird nur wie erwartet funktionieren). Dann verwenden Sie einfach ihren TZ-Offset, um die Zeit für ihre Anzeige anzupassen.

+0

Tatsächlich ist es falsche Antwort (nicht für jeden akzeptabel). Es gibt viele Zeitzonen, die Sommerzeit haben und sie haben unterschiedliche Sommer- und Winterzeiten. Beispielsweise. Benutzer haben Winter utc offset +4 Stunden. Und möchte um 06:00 Uhr erinnert werden. Sie sparen Erinnerungszeit 02:00 in UTC. Aber im Sommer hat diese Zeitzone +3 Stunden verrechnet. Also im Sommer wird der Benutzer in 05:00 anstatt 06:00 eine Erinnerung bekommen. –

+0

Wenn Sie die Zeitzone des Benutzers speichern, enthält diese ihre Offsets für Both Daylight und Standard, und basierend auf dem Tag, den Sie betrachten, verwenden Sie den korrekten Offset (vorausgesetzt, Sie halten die tz/zoneinfo-Dateien auf Ihrem Server/Ihrer App auf dem neuesten Stand) . Sie speichern einfach nicht so etwas wie -0500, Sie speichern etwas wie "Amerika/New_York" (oder vielleicht "US/Eastern", das darauf verweist). Siehe https://en.wikipedia.org/wiki/List_of_tz_database_time_zones – Doon

0

Sie könnten ein Benutzermodell auswählen. Etwas wie:

User.select{|user| user.time == time_the_job_runs.in_time_zone(user.string)} 

Sie sollten die "time_the_job_runs" ersetzen. Es ist mir nicht klar geworden, wie ich es bekommen soll. Aber die in_time_zone Methode sollte diejenige sein, nach der Sie suchen, um Zeit basierend auf einem Zeitzonen-String zu konvertieren. Hoffe es hilft, danke!

0

Nur erfüllt das gleiche Problem. Und Artikel gefunden, wie man es macht, wie man denkt, es selbst zu lösen. Aber mit fertigem Code. https://robots.thoughtbot.com/a-case-study-in-multiple-time-zones

Leitgedanke ist:

  1. Zuerst Sie Zeitzonen finden, die jetzt bestimmte Zeit.

    module ActiveSupport 
        class TimeZone 
        def self.current_zones(hour) 
         all.select { |zone| 
         t = Time.current.in_time_zone(zone) 
         t.hour == hour 
         }.map(&:tzinfo).map(&:name) 
        end 
        end 
    end 
    
  2. Sie finden Benutzer mit dieser Zeitzone.

    User.where(zone: ActiveSupport::TimeZone.current_zones(hour)).where(options) 
    
Verwandte Themen