Frage

Wir bauen eine App, die „Betriebsstunden“ für verschiedene Unternehmen speichert. Was ist der einfachste Weg, um diese Daten darzustellen, so können Sie leicht überprüfen, ob ein Element geöffnet ist?

Einige Optionen:

  • Segment der Blöcke (alle 15 Minuten), die Sie „offen / geschlossen“ markieren. Überprüfen beinhaltet zu sehen, ob die „offene“ Bit für die gewünschte Zeit (ein bisschen wie ein Zugfahrplan) festgelegt ist.
  • eine Liste der Zeitbereiche Speicher (11.00 bis 14.00 Uhr, 5-7pm, etc.) und überprüft, ob die aktuelle Zeit fällt in einem festgelegten Bereich (das ist, was unser Gehirn tut, wenn die Saiten über das Parsen).

Hat jemand Erfahrung in der Speicherung und Fahrplaninformationen abfragt und einen Rat zu geben?

(Es gibt alle möglichen verrückten Ecke Fällen wie „die ersten Dienstag im Monat geschlossen“, aber wir werden, dass für einen anderen Tag verlassen).

War es hilfreich?

Lösung

speichert jeden zusammenhängenden Block von Zeit als Startzeit und einer Dauer; Dies macht es einfacher, zu überprüfen, wenn die Stunden Quer Datum Grenzen

Wenn Sie sind sicher, dass Betriebsstunden nie Quer Datum Grenzen (das heißt, es wird nie ein offen-all-Nacht Verkauf oder 72-Stunden-Marathon et al), dann starten / Endzeiten genügt

Andere Tipps

Die flexibelste Lösung könnte den bitset Ansatz verwenden. Es gibt 168 Stunden in der Woche, so gibt es 672 15-Minuten-Perioden. Das ist nur 84 Bytes im Wert von Raum, das erträglich sein sollte.

Ich habe eine Tabelle wie folgt verwenden würde:

BusinessID | weekDay | OpenTime | CloseTime 
---------------------------------------------
     1          1        9           13
     1          2        5           18
     1          3        5           18
     1          4        5           18
     1          5        5           18
     1          6        5           18
     1          7        5           18

Hier haben wir ein Unternehmen, das regelmäßig Stunden von 5 bis 6, aber kürzere Stunden am Sonntag.

Eine Abfrage für wenn offen sei (psuedo-SQL)

SELECT @isOpen = CAST
   (SELECT 1 FROM tblHours 
       WHERE BusinessId = @id AND weekDay = @Day 
       AND CONVERT(Currentime to 24 hour) IS BETWEEN(OpenTime,CloseTime)) AS BIT;

Wenn Sie Rand Fällen speichern müssen, dann haben nur 365 Einträge, einen pro Tag ... es ist wirklich nicht so viel in den großen Plan der Dinge, legen Sie einen Index für die Spalte Tag und BusinessID Spalte.

Vergessen Sie nicht, die Unternehmen Zeitzone in einer separaten Tabelle zu speichern (normalisieren!), Und führen Sie zwischen Ihrer Zeit eine Transformation und es vor, diese Vergleiche.

Ich glaube, ich persönlich für einen Start + Endzeit gehen würde, wie es wäre alles flexibler machen. Eine gute Frage wäre: Was ist die Chance, dass die Blockgröße an einem bestimmten Punkt ändern wäre? Dann die Lösung, die am besten Ihre Situation paßt (wenn sie geeignet ist, zu ändern, die ich für die Zeitspanne gehen würde auf jeden Fall).

Man könnte sie als Zeitraum speichern und verwenden Segmente in Ihrer Anwendung. Auf diese Weise haben Sie die einfachen Eingabeblocks verwendet wird, während die Flexibilität zu halten in Ihrem Datenspeicher zu ändern.

, um hinzuzufügen, was Johnathan Holland sagte , würde ich für mehrere Einträge für den gleichen Tag ermöglichen.

Ich würde auch für dezimal Zeit erlauben, oder eine andere Spalte für Minuten.

Warum? viele Restaurants und einige Unternehmen, und viele Unternehmen auf der ganzen Welt haben Mittagessen und oder am Nachmittag bricht. Auch viele Restaurants (2, die ich kenne in der Nähe von meinem Hause in der Nähe an den ungeraden nicht-15-Schritte Zeit. Man schließt um 21.40 Uhr am Sonntag, und man schließt um 01.40 Uhr.

Es gibt auch die Frage der Urlaubsstunden, wie Geschäfte früh erntedanktag schließen, zum Beispiel, so müssen Sie auf Kalenderbasis überschreiben lassen.

Vielleicht, was getan werden kann, ist ein Datum / Zeit offen, Datum-Zeit in der Nähe, wie folgt aus:

businessID  | datetime              | type
==========================================
        1     10/1/2008 10:30:00 AM    1
        1     10/1/2008 02:45:00 PM    0
        1     10/1/2008 05:15:00 PM    1
        1     10/2/2008 02:00:00 AM    0
        1     10/2/2008 10:30:00 AM    1

usw. (Typ: 1 offen ist und 0 geschlossen)

Und haben alle Tage in den nächsten 1 oder 2 Jahre 1-2 Jahre im Voraus vorberechnet. Beachten Sie, dass Sie würden nur drei Spalten: int., Datum / Uhrzeit / Bit so sollte der Datenverbrauch minimal sein

Dies erlaubt es Ihnen auch spezifische Daten für ungerade Stunden für besondere Tage zu ändern, wie sie bekannt werden.

Es kümmert sich auch um Überquerung über Mitternacht sowie 12/24 Stunden Konvertierungen.

Es ist auch Zeitzone Agnostiker. Wenn Sie die Startzeit und Dauer zu speichern, wenn Sie die Endzeit berechnen, wird Ihre Maschine, die Ihnen die TZ eingestellt Zeit geben? Ist es das was du willst? Mehr Code.

soweit Abfrage für Open-geschlossen-Status: abfragen, um die Datum-Zeit in Frage,

select top 1 type from thehours where datetimefield<=somedatetime and businessID = somebusinessid order by datetime desc

dann Blick auf „Typ“. wenn man, es ist offen, wenn 0, es geschlossen ist.

PS: Ich war 10 Jahre lang im Einzelhandel. Also ich bin vertraut mit den kleinen Unternehmen crazy-Stunden Problemen.

OK, ich werde auf diese werfen für das, was es wert ist.

Ich brauche schon einige Dinge zu behandeln.

  • Fast / Performante Abfrage
  • Jede Zeitinkremente, 09.01, 12.14, etc.
  • International (?) - nicht sicher, ob dies ein Problem mit Zeitzonen auch, zumindest in meinem Fall aber jemand mehr hier fühlen Sie sich frei läuten in versiert
  • Öffnen - Schließen Spanning auf den nächsten Tag (geöffnet mittags, in der Nähe um 2:00 Uhr)
  • Mehrere Zeitspanne / Tag
  • Möglichkeit bestimmte Tage außer Kraft zu setzen (Urlaub, was auch immer)
  • Möglichkeit für Überschreibungen wiederkehrende
  • werden
  • Möglichkeit für einen beliebigen Punkt in der Zeit abfragen und erhalten Unternehmen offen (jetzt, zukünftige Zeit, vergangene Zeit)
  • Die Fähigkeit, leicht Ergebnisse der Unternehmen ausschließen bald schließen (Filter Unternehmen in 30 Minuten zu schließen, wollen Sie nicht Ihre Benutzer dieser Typ machen, die 5 Minuten zeigt sich vor in der Lebensmittel- / Getränkeindustrie schließen)

Ich mag viele der Ansätze vorgestellt, und ich bin von ein paar von ihnen zu leihen. In meiner Website, Projekt, was ich in Betracht ziehen muss ich hier Millionen von Unternehmen und einige der Ansätze haben scheinen nicht mir persönlich gut zu skalieren.

Hier ist, was ich für einen Algorithmus und Struktur vorzuschlagen.

Wir müssen einige konkreten Annahmen getroffen werden, auf der ganzen Welt, an jedem Ort, zu jeder Zeit: Es gibt 7 Tage in der Woche. Es gibt 1440 Minuten an einem Tag. Es gibt eine endliche Anzahl von Permutationen von Minuten offen / geschlossen, die möglich sind.

Nicht konkret, aber anständige Annahmen: Viele Permutationen von offen / geschlossen Minuten wird über Unternehmen geteilt werden Reduzierung der gesamten Permutationen tatsächlich gespeichert. eine Zeit in meinem Leben dort war, konnte ich leicht die tatsächlichen möglichen Kombinationen dieser Ansatz berechnen, aber wenn jemand helfen könnte / denkt, dass es nützlich wäre, das wäre toll.

Ich schlage vor, 3 Tabellen: Bevor Sie aufhören zu lesen, sollten Sie ordentlich in der realen Welt 2 dieser Tabellen wird klein genug Cache sein. Dieser Ansatz wird nicht jedermanns Sache sein, entweder aufgrund der schieren Komplexität des Codes erforderlich, um eine Benutzeroberfläche auf das Datenmodell zu interpretieren und wieder zurück, wenn nötig. Ihre Laufleistung und Bedürfnisse können variieren. Dies ist ein Versuch, zu einer vernünftigen ‚Unternehmen‘ Ebene Lösung, was auch immer das bedeutet.

HoursOfOperations Tabelle

ID | OPEN (Minute des Tages) | CLOSE (Minute des Tages)


1 | 360 | 1020 (Beispiel: 9.00 Uhr bis 17.00 Uhr)

2 | 365 | 1021 (Beispiel: kanten Fall von 9.05 bis 05.01 Uhr (weirdos))

etc.

HoursOfOperations kümmert sich nicht darum, was Tage, nur öffnen und schließen und Einzigartigkeit. Es kann pro Öffnen / Schließen Kombination nur ein einziger Eintrag sein. Nun, je nach Ihrer Umgebung entweder das gesamte Tabelle zwischengespeichert werden kann, oder es könnte für die aktuelle Stunde des Tages im Cache gespeichert werden, usw. Auf jeden Fall sollten Sie nicht in diese Tabelle für jede Operation abfragen müssen. Je nach Speicherlösung vorstellen, ich jede Spalte in dieser Tabelle als für die Leistung indiziert. Im Laufe der Zeit hat diese Tabelle wahrscheinlich eine exponentiell inverse Wahrscheinlichkeit der Einlage (n). Wirklich obwohl, sollte vor allem mit dieser Tabelle zu tun sein, ein In-Process-Betrieb (RAM).

Business2HoursMap

Hinweis: In meinem Beispiel ist ich "Day" als Bit-Flag-Feld / Spalte zu speichern. Dies ist im Wesentlichen auf meine Bedürfnisse und die Weiterentwicklung von LINQ / Flags Aufzählungen in C #. Es gibt nichts, was man von erweitern, dies zu 7-Bit-Felder zu stoppen. Beiden Ansätze sollten relativ ähnlich in beide Speicherlogik und Abfrage Ansatz sein.

Ein weiterer Hinweis: Ich bin Eingabe nicht in eine Semantik Argument auf „jeder Tisch eine PK-ID-Spalte muss“, wählen Sie ein anderes Forum für das finden

.

BusinessID | HoursID | Tag (oder, wenn Sie es vorziehen, aufgeteilt in: BIT Montag, BIT Dienstag, ...)


1 | 1 | 1111111 (dieses Geschäft ist offen 9-5 an jedem Tag der Woche)

2 | 2 | 1111110 (dieses Geschäft ist geöffnet von 9.05 bis 05.01 Uhr M-Sa (Montag = Tag 1)

Der Grund, diese einfach zu Abfrage ist, dass wir immer ganz problemlos die MOTD (Minute des Tages) bestimmen können, dass wir nach. Wenn ich wissen will, was bei 05.00 geöffnet ist morgen ich alle HoursOfOperations IDS greifen WHERE Schließen> = 1020. Wenn ich mich für eine Zeitbereich suchen, wird Öffnen unbedeutend. Wenn Sie wollen Unternehmen nicht zeigen, in der nächsten halben Stunde zu schließen, nur entsprechend eingehende Zeit einstellen (für 5.30 suchen (1050), nicht 05.00 (1020). Die zweite Abfrage natürlich ‚geben Sie mir alle Geschäfte mit HoursID IN wäre (1, 2, 3, 4, 5), etc. Dies sollte wohl eine rote Fahne heben, da es Beschränkungen in Bezug auf diesen Ansatz. wenn jemand beantworten kann jedoch in Frage stellen die tatsächlichen Permutationen oben wir in der Lage sein können, nach unten der roten Fahne zu ziehen. Betrachten wir die möglichen Permutationen nur noch auf einer beliebigen Seite der Gleichung zu einer Zeit, entweder öffnen oder schließen.

In Anbetracht wir unsere erste Tabelle gecached haben, das ist eine schnelle Bedienung. Zweite Operation wird diese potenziell große Reihe Tabelle abfragt, aber wir suchen sehr klein (SMALLINT) hoffentlich indizierten Spalten.

Nun können Sie die Komplexität auf der Code-Seite der Dinge sehen werden. Ich bin Targeting meist Bars in meinem speziellen Projekt, so dass es sehr sicher sein wird davon ausgehen, dass ich eine beträchtliche Anzahl von Unternehmen mit Stunden wie habe „11.00 bis 02.00 Uhr (am nächsten Tag)“. Das wäre in der Tat 2 Einträge sowohl in der HoursOfOperations Tabelle sowie die Business2HoursMap Tabelle. Z.B. eine Bar, die von 11.00 Uhr geöffnet ist - 1440 (11:00 Uhr - - Mitternacht) und 0 - 02.00 wird 2 Verweis auf die HoursOfOperations Tabelle 660 hat 120 (Mitternacht - 02.00). Diese Referenzen würden in die tatsächlichen Tage in der Business2HoursMap Tabelle als 2 Einträge in unserem simplen Fall 1 Eintrag widerspiegeln = alle Tage Stunden # 1 Referenz, eine andere alle Tage Referenz # 2. Hoffe, das macht Sinn, es war ein langer Tag.

Übergeordnete an besonderen Tagen / Feiertagen / was auch immer. Überschreibungen sind von Natur aus, Datum basiert, nicht Tag der Woche basiert. Ich denke, das ist, wo einige der Ansätze versuchen, die sprichwörtlich runden Pflock in ein quadratisches Loch zu schieben. Wir brauchen eine andere Tabelle.

HoursID | BusinessID | Day | Monat | Jahr

1 | 2 | 1 | 1 | NULL

Dies kann sicherlich komplexer, wenn man so etwas wie erforderlich „an jedem zweiten Dienstag, das Unternehmen für 4 Stunden geht zu fischen“. Doch was dies ermöglicht es uns ganz einfach zu tun ist, erlauben 1 - Überschreibungen, 2 - vernünftig wiederkehrende Überschreibungen. Z.B. wenn Jahr NULL ist, dann ist jedem Jahr am Neujahrstag dieser Weirdo-Bar geöffnet von 9.00 bis 5.00 Uhr hält im Einklang mit unseren obigen Daten Beispielen. D. h - Wenn Jahr eingestellt wurde, ist es nur für das Jahr 2013. Wenn Monat null ist, ist es an jedem ersten Tag des Monats ist. Auch dies wird jedes Scheduling-Szenario von NULL-Spalten nicht alleine bewältigen, aber theoretisch könnte man, indem sie sich auf eine lange Folge von absoluten Daten fast alles bewältigt, wenn nötig.

Auch hier würde ich diese Tabelle auf rollierender Basis Tag zwischenzuspeichern. Ich kann einfach nicht realistisch sehen Sie die Zeilen für diese Tabelle in einem Ein-Tages-Snapshot sehr groß zu sein, zumindest für meine Bedürfnisse. Ich würde diese Tabelle prüfen Sie zuerst, wie es gut ist, eine Überschreibung und würde eine Abfrage für die viel größere Business2HoursMap Tabelle auf der Speicherseite speichern.

Interessantes Problem. Ich bin wirklich überrascht, dies ist das erste Mal, dass ich wirklich gebraucht habe, dies zu durchdenken. Wie immer sehr daran interessiert, auf unterschiedliche Einsichten, Ansätze oder Mängel in meinem Ansatz.

Die Segmentblöcke sind besser, so stellen Sie sicher, dass Sie dem Benutzer eine einfache Möglichkeit geben, sie zu setzen. Klicken und Ziehen ist gut.

Jedes andere System (wie Bereiche) sein wird, wirklich ärgerlich, wenn man die Mitternachtsgrenze überschreiten.

Was, wie Sie sie speichern, in C ++ bitfields wahrscheinlich am besten sein würde. In den meisten anderen Sprachen, und Array könnte besser (viel Platz verschwendet, aber schneller laufen würde und leichter zu verstehen) sein.

Ich würde denken, ein wenig über diese Rand-Fälle gerade jetzt, weil sie, ob Sie eine Basiskonfiguration und Overlay oder komplette statische Speicherung von Öffnungszeiten oder was auch immer haben werden informieren.

Es gibt so viele Ausnahmen - und in regelmäßigen Abständen (wie Schneetag, unregelmäßige Feiertage wie Ostern, Karfreitag), dass, wenn dies erwartet eine zuverlässige Darstellung der Realität zu sein (im Gegensatz zu einer guten Vermutung gegen), Sie ‚ll müssen sie adressiert ziemlich bald in der Architektur ein.

Wie wäre es etwa so:

Öffnungszeiten Tabelle

Business_id (int)
Start_Time (time)
End_Time (time)
Condition varchar/string
Open bit

'Bedingung' ist ein Lambda-Ausdruck (Text für ein 'where' -Klausel). Erstellen Sie die Abfrage dynamisch. Also für ein bestimmtes Geschäft wählen Sie alle die Öffnungs- / Schließzeiten

Let Query1 = select count(open) from store_hours where @t between start_time and end_time and open  = true and business_id = @id and (.. dynamically built expression)

Let Query2 = select count(closed) from store_hours where @t between start_time and end_time and open = false and business_id = @id and (.. dynamically built expression)

Also das Ende beenden Sie so etwas wie:

select cast(Query1 as bit) & ~cast(Query2 as bit)

Wenn das Ergebnis der letzten Abfrage 1 ist dann der Laden ist zur Zeit t geöffnet, sonst ist es geschlossen ist.

Jetzt müssen Sie nur eine benutzerfreundliche Oberfläche, die Ihre where-Klauseln (Lambda-Ausdrücke) für Sie generieren können.

Der einzige andere Ecke Fall, dass ich denken kann, ist, was passiert, wenn ein Geschäft geöffnet ist von 07.00 Uhr an einem Tag bis 2 Uhr sagen, aber um 11 Uhr am folgenden Tag geschlossen. Ihr System soll in der Lage sein, das zu handhaben als auch durch intelligent die Zeiten zwischen den zwei Tagen Aufspaltung.

Es ist sicherlich keine Notwendigkeit Speicher hier zu sparen, aber vielleicht ein Bedarf für sauberen und nachvollziehbaren Code. "Bit twiddling" ist nicht, meiner Meinung nach, den Weg zu gehen.

Wir brauchen hier einen Satz Behälter, die eine beliebige Anzahl von Unikaten hält und lässt sich schnell und einfach feststellen, ob ein Element ein Mitglied ist oder nicht. Das Setup reuires Pflege, aber in dem Routineeinsatz eine einzige Zeile einfach verstanden Code bestimmt, ob Sie sind offen oder geschlossen

Konzept: Vergeben Indexnummer zu je 15 min Block, beginnend bei etwa Mitternacht Sonntag.

initialisieren: Legen Sie in einem Satz die Indexnummer von jeweils 15 min Block, wenn Sie geöffnet sind. (Angenommen, Sie öffnen weniger Stunden sind als Sie sind geschlossen.)

Verwendung: Subtrahieren von interessanten Zeit in Minuten, Mitternacht den vorherigen Sonntag und dividieren durch 15. Wenn diese Zahl in der Reihe ist, sind Sie offen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top