Dois-je stocker des dates ou des règles de récurrence dans ma base de données lors de la construction d'une application de calendrier?
je construis un site Web de calendrier ( ASP.NET MVC
) application (pensez version simple de outlook) et je veux commencer à soutenir les événements de calendrier qui sont récurrents (mensuelle, annuelle, etc)
en ce moment je stocke les dates réelles Dans Mon mais je voulais savoir si, avec la récurrence, est-il raisonnable de continuer à stocker des dates (avec une coupure évidente), ou devrais-je stocker les options de récurrence et générer les dates à la volée.
It got me pensant comment outlook, google mail, etc fait ceci ou tout autre service qui prend en charge les éléments récurrents de calendrier.
y a-t-il des suggestions à ce sujet?
7 réponses
séparez vos données en deux parties: les données " canoniques "(la règle de récurrence) et" serving " (dates générées; lecture seule en dehors de la régénération). Si les données canoniques changent, régénérer les données de "service" à ce point. Pour les récurrences infinies, conservez un certain nombre d'instances et générez plus si vous n'en avez plus (par exemple si l'utilisateur regarde leur calendrier pour 2020).
si vous aviez une vitesse de processeur infinie, vous n'auriez besoin que des données canoniques - mais en réalité, faire tout le traitement date / heure pour toutes les règles de récurrence sur chaque Page view est susceptible d'être trop long... donc vous échangez un peu de stockage (et de complexité) pour sauver ce calcul répété. Le stockage est généralement assez bon marché, par rapport au calcul requis pour un grand nombre d'événements. Si vous seulement besoin de stocker les dates des événements, qui est vraiment très bon marché - vous pourriez facilement utiliser un entier de 4 octets pour représenter une date, et ensuite, générez une date/heure complète à partir de cela, en supposant que vos récurrences sont toutes basées sur la date. Pour les récurrences basées sur le temps (par exemple "toutes les trois heures"), vous pouvez utiliser des instantsutc complets-8 octets représenteront cette résolution jusqu'à une résolution assez fine aussi longtemps que vous en aurez besoin.
vous devez être prudent sur le maintien de la validité cependant - si une réunion récurrente change aujourd'hui , cela ne change pas quand il a s'est produit dans le passé... donc, vous voulez probablement aussi avoir des données canoniques en lecture seule sur quand les récidives se sont réellement produites. Évidemment, vous ne voudrez pas que pour garder le passé pour toujours, donc vous voulez probablement "collecte des ordures" événements de plus de quelques années, en fonction de vos limites de stockage.
vous pouvez également avoir besoin de la possibilité d'ajouter des notes et des exceptions (par exemple" réunion n'a pas lieu aujourd'hui en raison d'un jour férié "ou" déménagé à 16h") sur une base de fréquence. Cela devient vraiment amusant quand vous changez la récurrence - si vous changez "chaque lundi" à "chaque mardi" vous gardez les exceptions ou non? Comment faire correspondre les exceptions quand on passe de" tous les jours "à"toutes les semaines"? Ce ne sont pas des questions qui concernent directement le stockage - mais les décisions de stockage auront une incidence sur la facilité avec laquelle il est possible de mettre en œuvre n'importe quelle politique sur laquelle vous décidez.
j'ai dû construire un système qui fonctionnait avec la planification et nous avons fait les deux. Voici ce que nous avions
- un ensemble de tableaux qui ont gardé la trace de l'horaire.
- une table qui ont suivi les précédentes instances de la planification(quand ils ont réellement eu lieu)
- une table qui a gardé la trace de la dernière et la prochaine instance (quand le prochain article doit se produire basée sur la dernière fois) vous n'avez pas besoin de cette table, mais nous l'avons utilisée, parce qu'autrement vous calculeriez constamment si un article devrait se produire maintenant
avec l'horaire, les choses peuvent devenir vraiment délicates parce que vous devez vous rappeler qu'à tout moment, l'horaire peut changer. En outre, un élément peut être due lorsque votre application n'est pas en cours d'exécution, et quand il démarre à nouveau, vous devez savoir comment identifier les éléments dus.
aussi, nous avons fait en sorte que les tableaux qui ont gardé le suivi de l'horaire réel était seul. La raison en est que ces tables étaient les plus complexes du système et que nous voulions pouvoir les réutiliser afin qu'elles puissent être utilisées pour différentes choses qui devaient être programmées. Comme l'envoi d'emails d'admin, l'envoi de notifications, et la maintenance du serveur comme le nettoyage des fichiers journaux.
vous aurez besoin de traiter séparément les événements et les événements.
EVENT WISE: Pour les événements, vous aurez besoin de stocker des règles de récurence (qui peuvent être un rrule comme spécifié par rfc5545 mais aussi un ensemble explicite de dates comme rdate dans rfc5545) mais aussi des exceptions (voir exdate de rfc5545 et peut-être exrule comme dans rfc2445). Vous aurez également besoin de garder une trace des changements dans les règles: Les changements dans rdate, exdate ne sont pas un problème quand ils se produisent dans le futur et à ignorer pour des dates passées. Les changements dans le rrule sont plus difficiles car ils ont un impact sur les occurrences précédentes. Ma préférence personnelle est d'ajouter une propriété particulière pour l'ancien et le nouveau rrule de préciser leur début et date de fin de validité.
si l'événement a une période de temps limitée (disons Compter ou JUSQU'à ce que la propriété est présente) , vous devez stocker son début et la fin dans votre table pour permettre une interrogation plus facile des événements (en particulier lors de la recherche d'événements en dehors de votre fenêtre de temps précalculée (voir ci-dessous), il peut aider à réduire le nombre d'événements pour lesquels le calcul est à refaire).
EVENTS WISE: pour les occurences, vous devez stocker les instances dans une fenêtre prédéfinie autour de present (par exemple +/- 6 mois ou 12 mois et calculé sur une base régulière) et conserver des enregistrements de ceci pour permettre de recalculer si vos utilisateurs veulent voir plus loin dans le futur (pour les questions de performances). vous devriez également envisager le calcul de l'indice (RECURRENCE-ID) pour aider à trouver plus facilement la prochaine occurrence.
moins à l'arrière mais plus à l'avant vous devriez également garder une trace des changements tzid pour demander à l'utilisateur si un événement qui a été prévu sur un tzid donné si elle est censée rester sur le fuseau horaire actuel de celui-ci doit être mis à jour (pensez à quelqu'un dans L'Île du Samoa qui a prévu une réunion le vendredi, Décembre. 30 2011 avant que le pays ait décidé que ce jour n'existerait pas), de la même manière, vous pouvez demander si un événement qui se produit au cours de l'heure d'été est destiné "ne jamais se produire" ou "arriver deux fois" (plus sur ce sujet ici )
Note: vous pouvez vouloir considérer le soutien au-delà de ce qui est défini dans rfc5545 en termes de règles de récurence et aussi ajouter le soutien pour les règles religieuses récurrentes ( voir USNO introduction to calendars ou dans l'imprimé "Calendrical Calculations" (troisième édition) de E. Reingol et N. Dershowitz).
puisque vous posez des questions sur la mise en œuvre existante, vous pouvez consulter facilement le schéma de base de données de sunbird (sqlite) ou du Apple open source Calendar and Contacts Server , une liste plus complète des projets open source existants pour les serveurs caldav (qui est probablement un sous-ensemble de ce que vous recherchez) est disponible ici )
j'utiliserais certainement votre deuxième option. Utilisez différentes options de récurrence, stockez-les séparément et calculez à la volée. Stocker toutes ces dates serait une cargaison de données qui n'est pas nécessaire.
Voici une bonne réponse pour compléter votre question.
structure de données pour stocker les événements récurrents?
aussi, comme note latérale. J'ai commencé à tout stocker en temps UTC de sorte que vous avez un commun de référence si vous avez besoin d'utiliser plusieurs fuseaux horaires.
Vous avez besoin de stocker certains d'entre eux pour vous. L'utilisateur peut modifier l'un des événements, en laissant d'autres de côté (vous avez probablement rencontré la question: "voulez-vous modifier tous les événements récurrents ou seulement celui-ci?"dans certains calendriers, c'est à dire. Windows Mobile).
Vous pouvez également stocker des événements du passé et de ne pas les supprimer lorsque l'utilisateur supprime l'événement récurrent.
si vous stockez tous les autres ou les générez est un détail de mise en œuvre. Je préfère générez-les, si possible.
dans tous les cas, vous voulez avoir une identification de l'événement récurrent stocké avec chaque événement, plus un drapeau vous indiquant si l'événement a été modifié plus tard. Ou dans une approche plus compliquée, un drapeau pour chaque propriété d'événement indiquant, si c'est la valeur par défaut (de l'événement récurrent) ou si elle a été modifiée pour cette instance particulière. Vous en aurez besoin lorsque l'utilisateur décide de modifier l'événement récurrent.
j'ai eu un problème similaire dans une application web que j'ai faite il y a quelques années (il pourrait bien y avoir une meilleure façon maintenant :) ). Je voulais inclure un planificateur qui avait toutes les fonctionnalités des événements récurrents, gérer le temps, les jours, les semaines, les mois, les années, et les exceptions, de sorte que je pourrais avoir des règles comme:
1) Tous les jours à 10h sauf le mercredi
2) Toutes les 2 heures avec un maximum de 4 itérations par jour
3) Tous Les Lundi du mois
etc..
mémoriser les dates/heures récurrentes était possible, mais inflexible. Chaque itération de votre événement change lorsque le "maximum" serait. Et à quel point pensez-vous?
à la fin j'ai écrit une classe de planification personnalisée qui pouvait lire et écrire à une corde. C'était la chaîne de caractères qui était stockée dans la base de données et ensuite une fonction simple peut être appelée pour savoir quand la prochaine occurrence est.
notez que la plupart des réponses penchent vers la sauvegarde des données générées. Mais assurez-vous d'examiner votre cas d'utilisation.
à l'époque, mes serveurs étaient limités par io avec beaucoup de cpu ne faisant rien. De nos jours vous avez ssd (si vous pouvez vous les permettre, sinon votre gauche avec un vieux spinning hd) mais notez que le nombre de noyaux a augmenté aussi.
la bonne chose au sujet de ce genre de calculs est que vous pouvez les diviser facilement et les donner à vos nombreux des cœurs ou même à quelques serveurs bon marché dans un réseau local. Souvent moins cher que d'installer un nosql cluster ou les cluster de base de données.
et l'alternative pourrait aussi être un cache, il suffit de mettre en cache votre vue Calendrier, pas besoin de faire tous les calculs à chaque fois que rien n'a changé.
, Mais comme dit, cela dépend de votre cas d'utilisation. Ne vous contentez pas de suivre les réponses ci-dessus, mais faites vos propres calculs si vous avez le temps de prendre une décision.