2010-11-21 45 views
22

Je construis un site de calendrier (ASP.NET MVC) application (pensez version simple de perspectives) et je veux commencer à soutenir les événements de calendrier qui sont récurrents (mensuel, annuel, etc.)Dois-je stocker des dates ou des règles de récurrence dans ma base de données lors de la création d'une application de calendrier?

en ce moment je stocke les dates réelles dans ma mais je voulais savoir si, avec récurrence, il est logique 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.

Il m'a fait penser comment Outlook, Google Mail, etc. fait cela ou tout autre service qui prend en charge les éléments de calendrier récurrents.

Y a-t-il des suggestions à ce sujet?

Répondre

41

Séparez vos données en deux parties: les données « canoniques » (la règle de récurrence) et « au service » (dates générées, en lecture seule en dehors de la régénération). Si les données canoniques changent, régénérez les données de "diffusion" à ce moment-là. Pour les récurrences infinies, conservez un certain nombre d'instances et générez plus d'occurrences si vous en manquez (par exemple, si l'utilisateur consulte son calendrier pour 2020). Si vous aviez une vitesse de processeur infinie, vous auriez seulement besoin des données canoniques - mais en réalité, faire tout le traitement de la date/heure pour toutes les règles de récurrence sur chaque page risque de prendre trop de temps ... donc vous échangez du stockage (et de la complexité) pour sauvegarder ce calcul répété. Le stockage est généralement bon marché, comparé au calcul requis pour un grand nombre d'événements. Si vous ne besoin de stocker les dates des événements, qui est vraiment très pas cher - vous pouvez facilement utiliser un entier de 4 octets pour représenter une date, puis générer une date complète/heure de cela, en supposant que vos récurrences sont tous fondé sur la date . Pour des récurrences basées sur le temps (par exemple "toutes les trois heures"), vous pouvez avoir des instants UTC complets - 8 octets représenteront cela jusqu'à une résolution assez fine aussi longtemps que vous en aurez probablement besoin.

Vous devez faire attention à maintenir la validité si - si une réunion récurrente change aujourd'hui, cela ne change pas quand il a est arrivé dans le passé ... si vous voulez probablement aussi ont canonique des données en lecture seule sur le moment où les récurrences se sont réellement produites. Évidemment, vous ne voudrez pas que cela garde le passé pour toujours, alors vous voudrez probablement "ramassez" les événements de plus de quelques années, en fonction de vos limites de stockage.

Vous devrez peut-être la possibilité d'ajouter des notes et des exceptions (par exemple « réunion ne se produit pas aujourd'hui en raison d'un jour férié » ou « déplacé à 16 heures ») sur une base par événement. Cela devient vraiment amusant quand vous changez la récurrence - si vous changez "tous les lundis" à "tous les mardis" gardez-vous les exceptions ou non? Comment faites-vous correspondre les exceptions lorsque vous passez de "tous les jours" à "chaque semaine"? Ce ne sont pas des questions qui concernent directement le stockage, mais les décisions de stockage affecteront la facilité d'implémentation de la politique que vous décidez.

3

J'utiliserais certainement votre deuxième option. Utilisez différentes options de récurrence, enregistrez-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.
Data structure for storing recurring events?

En outre, comme une note de côté. J'ai commencé à stocker tout en temps UTC afin que vous ayez une base de référence commune si vous avez besoin d'utiliser plusieurs fuseaux horaires.

+0

si vous avez enregistré une date distincte pour chaque récurrence de chaque utilisateur qui a une récidive, il peut devenir beaucoup de données à la hâte. –

+0

+ 1 favorisant la récurrence de stockage. Pensez à l'utilisation cas où un utilisateur déplace une instance d'un événement récurrent: elle a la possibilité d'appliquer le mouvement à tous les événements, tous les événements ultérieurs, tout cet événement, etc. – Fuhrmanator

0

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, jours, semaines, mois, années et exceptions, afin que je puisse avoir des règles comme:

1) Tous les jours à 10h sauf les mercredis

2) Toutes les 2 heures avec un maximum de 4 itérations par jour

3) Tous les premiers lundis du mois

etc ..

Mémorisation des dates récurrentes/heures était possible, mais inflexible . Chaque itération de votre événement change quand le "maximum" serait. Et à quelle distance as-tu l'air? En fin de compte, j'ai écrit une classe de planification personnalisée qui pouvait lire et écrire dans une chaîne. C'était la chaîne qui était stockée dans la base de données et ensuite une simple fonction peut être appelée pour savoir quand l'occurrence suivante est.

+0

mais j'ai besoin plus que la prochaine occurrence – leora

+0

@ ooo, mais une classe horaire bien écrite peut le faire. Compte tenu de la date actuelle, il peut calculer l'occurrence suivante, celle après cette annonce infini. L'entrée de votre fonction 'when()' devrait être "maintenant" et elle peut renvoyer la date d'occurrence suivante. Étant donné que vous pouvez en calculer autant que vous le souhaitez, soit en alimentant la date donnée en 'when()' ou en lui retournant toute une séquence. –

7

Je devais construire un système qui fonctionnait avec la planification et nous avons fait les deux. Voici ce que nous avions

  • un ensemble de tables qui gardait la trace de la planification.
  • une table qui gardait une trace de la dernière instance et de ne pas besoin de cette table, mais nous l'avons utilisé, parce que sinon vous constamment calculera si un élément doit se produire maintenant

Avec le calendrier, les choses peuvent devenir vraiment difficile parce que vous devez vous rappeler que à tout moment temps, l'horaire peut changer.En outre, un élément peut être dû lorsque votre application n'est pas en cours d'exécution, et quand il redémarre, vous devez savoir comment identifier les éléments en retard.

De plus, nous nous sommes assurés que les tables qui ont gardé la trace de l'horaire réel se retrouvent seuls. La raison en est que ce sont les tables les plus complexes du système et que nous voulions être en mesure de les réutiliser pour qu'elles puissent être utilisées pour différentes tâches nécessitant une planification. Comme l'envoi d'e-mails d'administration, l'envoi de notifications et la maintenance du serveur, comme le nettoyage des fichiers journaux.

1

Vous avez besoin de stocker certains d'entre eux à coup sûr. L'utilisateur peut éditer l'un des événements, en laissant les autres intacts (vous avez probablement rencontré la question: "Voulez-vous modifier tous les événements récurrents ou seulement celui-ci?" Dans certains calendriers, par exemple Windows Mobile).

Vous pouvez également stocker des événements passés et non les supprimer lorsque l'utilisateur supprime l'événement récurrent.

Si vous stockez tous les autres ou si vous les générez, un détail d'implémentation est indiqué. Je préférerais les générer, si possible.

Dans tous les cas, vous aurez envie d'avoir un identifiant de l'événement récurrent stocké à chaque événement, ainsi que certains drapeau vous dire si l'événement a été modifié par la suite. 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écidera de modifier l'événement récurrent.

7

Vous aurez besoin de gérer séparément les événements et les événements.

CAS WISE: Pour les événements, vous devez stocker les règles de recurence (qui peut ê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 aussi besoin de garder une trace des changements dans les règles: Les changements dans rdate, EXDATE sont pas un problème quand ils se produisent à l'avenir et à être ignorés pour les dates antérieures. Les modifications de la règle sont plus complexes car elles ont un impact sur les occurrences précédentes. Ma préférence personnelle est d'ajouter une propriété spécifique pour l'ancienne et la nouvelle règle pour spécifier leurs dates respectives de début et de fin de validité. Si l'événement a une durée limitée (par exemple COUNT ou UNTIL propriété), vous devez stocker son début et sa fin dans votre table pour faciliter l'interrogation des événements (en particulier lorsque vous recherchez des occurrences 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 doit être refait). Pour les occurrences, vous devez stocker les instances dans une fenêtre prédéfinie (par exemple +/- 6 mois ou 12 mois et calculées régulièrement) et conserver des enregistrements pour permettre le recalcul si vos utilisateurs le souhaitent. pour voir plus loin dans le futur (pour les problèmes de performances). vous devriez également envisager de calculer l'index (RECURRENCE-ID) pour faciliter la recherche de l'occurrence suivante.

moins sur le back-end, mais plus sur le front-end, vous devez également garder la trace des changements tzid pour demander à l'utilisateur si un événement qui était prévu sur un tzid donné si elle est destinée à rester sur le fuseau horaire il doit être mis à jour (pensez à quelqu'un dans l'île de Samoa qui a organiser une réunion du vendredi 30 décembre 2011 avant que le pays a décidé ce jour n'existerait pas), vous pouvez de la même demander si un événement qui se produit pendant l'heure d'été est destiné à « jamais arriver » ou « passer deux fois » (plus sur ce sujet here)

note: vous voudrez peut-être envisager un soutien au-delà de ce qui est défini dans rfc5545 en termes de règles de recurence et ajouter le soutien des règles récurrentes religieuses (see USNO introduction to calendars ou en imprimé "Calculs calendriers" (troisième édition) de E. Reingol et N. Dershowitz). Puisque vous posez des questions sur l'implémentation existante, vous pouvez vérifier 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 êtes recherche) est disponible here)