2017-02-14 1 views
0

Für ein Geschäft, würde ich gerne Ladenöffnungszeiten und Ortszeiten für diesen bestimmten Laden. Beispiel:Abfrage lokale Zeit

Shop1 öffnet um 8.00 (t1) und schließt um 16.00 (t2) Ortszeit. Shop1 befindet sich in Europa/London (tz).

Shop2 öffnet um 8.00 Uhr und schließt um 16.00 Uhr Ortszeit. Shop2 befindet sich in Europa/Kopenhagen.

Die Frage: Wie wähle ich zu einem bestimmten Zeitpunkt Geschäfte, die offen sind? Ich muss DST berücksichtigen: In diesem Beispiel im Sommer, Shop1 Öffnungszeiten sind 08: 00 + 01: 00, Shop2 Öffnungszeiten sind 08: 00 + 02: 00, im Winter ist dies 08: 00 + 00: 00 für Shop1 und 08: 00 + 01: 00 für Shop2.

Wird aus einer Tabelle mit vielen Zeilen ausgewählt, daher muss ich dies indizieren.

Verwenden von Django + PostgreSQL.

Antwort

0

Postgres unterstützt die Umwandlung einer Uhrzeit in eine lokale Zeit mit der Syntax at time zone. Zum Beispiel die aktuelle Zeit in Neuseeland zu finden:

select (current_timestamp at time zone 'NZDT')::time; 

Sie könnten diese Geschäfte wählen verwenden, um 10:00 Uhr geöffnet sind:

where ('10:00'::time at time zone time_zone)::time 
     between opens and closes 

Wo time_zone die Zeitzone für das Geschäft ist, opens die Zeit, die es öffnet, und closes die Zeit, die es schließt. Full example at regtester.com.

+0

Das ist sehr cool. Ich habe etwas ausprobiert, aber ich konnte mir nicht vorstellen, wie ich das machen soll. Irgendwelche Einblicke in die Kosten der lokalen Zeitberechnung?Welche Indizes müsste ich hinzufügen, damit dies für ~ 1 Million Zeilen schnell ausgeführt wird? – toucan

1

Coole Frage. Fortsetzung Andomar's answer above, vorausgesetzt, Sie mit „unerwarteten“ Sommerzeiträumen einige Zeitzonen sind Handling, wäre eine Option wäre:

  • Speichern Sie die Zeitzone in einem CharField und opens und closes in einem TimeField:

    class Shop(models.Model): 
        tz = models.CharField(max_length=200) 
        opens = models.TimeField() 
        closes = models.TimeField() 
    
    Shop.objects.create(opens="8:00", closes="19:00", tz="Europe/Moscow") 
    Shop.objects.create(opens="8:00", closes="19:00", tz="Europe/Berlin") 
    Shop.objects.create(opens="8:00", closes="19:00", tz="UTC") 
    Shop.objects.create(opens="8:00", closes="19:00", tz="Asia/Jerusalem") 
    Shop.objects.create(opens="8:00", closes="19:00", tz="Europe/London") 
    Shop.objects.create(opens="8:00", closes="19:00", tz="Europe/Copenhagen") 
    
  • berechnen "jetzt", wie UTC:

    now_utc = "10:30" 
    
  • Beschriften und filtern Sie Ihre queryset mit RawSQL:

    qs = Shop.objects.annotate(is_open=RawSQL("(%s::time at time zone tz)::time between opens and closes", (now_utc,))).filter(is_open=True) 
    

Eine andere Lösung wäre, die db für jede Zeitzone abfragen:

# pseudocode 
for tz in all_timezones: 
    now_local = convert_to_timezone(now, tz) # beware - this might fail when DST is currently changing! 
    shops = Shop.objects.filter(tz=tz, opens__lte=now_local, closes__gte=now_local) 

Wenn Sie index_together Felder (tz, opens, closes), Die Abfrage sollte den Index verwenden. Dies bedeutet jedoch nicht, dass Ihre Anfrage schneller ist.

Denken Sie daran, dass Sie Ihre Öffnungszeiten um Mitternacht in zwei Datensätzen "22:00" - "00:00" und "00:00" - "03:00" statt "22:00" behalten müssen "-" 03:00 ".