J'essaie actuellement de trouver la meilleure façon de stocker les heures d'ouverture d'une entreprise dans une base de données.
Par exemple:
L'entreprise A a les heures d'ouverture suivantes
Actuellement, j'ai un modèle de données semblable au suivant
CREATE TABLE "business_hours" (
"id" integer NOT NULL PRIMARY KEY,
"day" varchar(16) NOT NULL,
"open_time" time,
"close_time" time
)
où le "jour" est limité à un choix des 7 jours de la semaine en code (via l'ORM). Pour tester si une entreprise est fermée un certain jour, il vérifie si open_time et close_time sont NULL. Il est lié à l'entreprise via une table intermédiaire (plusieurs à plusieurs relation).
Quelqu'un at-il des suggestions pour ce schéma de base de données? Quelque chose ne me semble pas juste.
Dans l'ensemble, je ne vois rien de mal à cela. Sauf...
Je stockerais le jour de la semaine sous forme d'entier en utilisant le système de numérotation utilisé par votre langage de programmation natif (dans ses bibliothèques). Cela réduira la taille de la base de données et supprimera les comparaisons de chaînes de votre code.
Je mettrais probablement la clé étrangère à la table des affaires ici même dans ce tableau. De cette façon, vous n'aurez pas besoin d'une table de liens.
Donc je suppose que je ferais:
CREATE TABLE "business_hours" (
"id" integer NOT NULL PRIMARY KEY,
"business_id" integer NOT NULL FOREIGN KEY REFERENCES "businesses",
"day" integer NOT NULL,
"open_time" time,
"close_time" time
)
Dans ma logique métier, j'imposerais une contrainte selon laquelle chaque "entreprise" a au moins 7 "heures d'ouverture". ( Au moins parce que Jon Skeet a raison, vous voudrez peut-être les heures de vacances.) Bien que vous souhaitiez peut-être assouplir cette contrainte en laissant simplement les "heures d'ouverture" pendant des jours où l'entreprise est fermée.
Une situation qui n'est pas couverte par ce schéma est plusieurs périodes d'ouverture dans une journée. Par exemple, le pub local est ouvert de 12h00 à 14h30 et de 17h00 à 23h00.
Peut-être qu'un box-office de théâtre est ouvert pour une matinée et une représentation en soirée.
À ce stade, vous devez décider si vous pouvez avoir plusieurs entrées pour le même jour ou si vous devez représenter différentes heures sur la même ligne.
Qu'en est-il des heures d'ouverture qui traversent minuit. Supposons qu'un bar soit ouvert de 19h00 à 2h00. Vous ne pouviez pas simplement comparer les heures d'ouverture et de fermeture avec le temps que vous souhaitez tester.
J'ai appris que si vous souhaitez que le balisage de données Google reconnaisse vos données, vous devez suivre ces directives:
https://schema.org/openingHours
http://schema.org/OpeningHoursSpecification Contient des "dates valides", ce qui est très utile pour certaines entreprises.
https://schema.org/docs/search_results.html#q=hours
Vous devriez être bien sans clé primaire, sauf si vous autorisez les entreprises à partager les mêmes heures avec la table de jointure. Je ne sais pas combien cela serait: p
Avec l'un de mes projets, j'ai utilisé les colonnes:
[uInt] business_id, [uTinyInt] jour, [char (11)] timeRange
Si vous souhaitez prendre en charge OpeningHoursSpecification, vous devrez ajouter validFrom et validThrough.
La plage de temps est formatée comme: hh: mm-hh: mm
Voici une fonction qui l'analyse, vous pouvez également modifier cette fonction pour analyser une seule ouverture/fermeture, si vous les conservez en tant que colonnes distinctes dans la base de données.
D'après mon expérience, je recommanderais que vous autorisiez plusieurs fois dans la journée, permettez un moyen de savoir s'ils sont explicitement fermés ce jour-là, ou ouverts 24 heures ou 24/7. J'ai eu le mien dire que s'il manquait un jour dans la base de données, l'entreprise était fermée ce jour-là.
/**
* parseTimeRange
* parses a time range in the form of
* '08:55-22:00'
* @param $timeRange 'hh:mm-hh:mm' '08:55-22:00'
* @return mixed ['hourStart'=>, 'minuteStart'=>, 'hourEnd'=>, 'minuteEnd'=>]
*/
function parseTimeRange($timeRange)
{
// no validating just parsing
preg_match('/(?P<hourStart>\d{1,2}):(?P<minuteStart>\d{2})-(?P<hourEnd>\d{1,2}):(?P<minuteEnd>\d{2})/', $timeRange, $matches);
return $matches;
}
Pourrait penser à l'affacturage pendant les vacances en incluant des champs supplémentaires pour le mois de l'année/le jour du mois/la semaine du mois. La semaine du mois a quelques subtilités mineures "dernières" qui pourraient par exemple être la semaine 4 ou 5 selon l'année.