Должен ли я хранить даты или правила рецидива в моей базе данных при создании приложения календаря?

StackOverflow https://stackoverflow.com/questions/4239871

Вопрос

Я создаю веб-сайт календаря (ASP.NET MVC) Применение (подумайте о простых версии Outlook), и я хочу начать поддерживать события календаря, которые являются повторяющимися (ежемесячно, ежегодно и т. Д.)

Прямо сейчас я храним фактические даты в моем, но я хотел понять, если, с рецидивом, имеет смысл продолжать хранить даты (с некоторыми очевидными отсеками), или я должен хранить варианты рецидива и генерировать даты на лету Отказ

Это заставило меня думать, как Outlook, Google Mail, ETC делает это или любая другая служба, поддерживающая повторяющиеся элементы календаря.

Есть ли какие-либо предложения по этому поводу?

Это было полезно?

Решение

Отделите ваши данные на две части: «Canonical» данные (правило повторения) и «обслуживание» (сгенерированные даты; только чтение - только от регенерации). Если канонические данные изменяются, восстановите данные «обслуживания» в этот момент. Для бесконечных рецидивов сохраните некоторое количество экземпляров и генерируйте больше, если вы закончите (например, если пользователь смотрит на их календарь на 2020).

Если у вас была бесконечная скорость процессора, вам понадобятся только канонические данные - но в действительности, выполняя все обработка даты / времени для всех правил рецидива на каждый Взгляд страницы, скорее всего, будет слишком трудоемким ... Итак, вы обмениваете некоторое хранилище (и сложность), чтобы сохранить эти повторные вычисления. Хранение обычно довольно дешевое, по сравнению с вычислением, необходимыми для большого количества событий. если ты Только Необходимо хранить даты событий, это действительно очень дешево - вы можете легко использовать 4 байтовое целое число для представления даты, а затем создать полную дату / время от этого, предполагая, что ваши рецидивы на основе даты. Для рецидивов на основе времени (например, «каждые три часа») вы можете полные моменты UTC - 8 байтов будут представлять это до довольно прекрасного разрешения до тех пор, пока вы, вероятно, понадобится.

Вы должны быть осторожны в поддержании достоверности - если изменяет повторяющиеся встречи сегодня, это не меняется, когда это имеет случилось в прошлом ... так что вы, вероятно, хотите также иметь канонические данные только для чтения, когда произошли рецидивы на самом деле. Очевидно, вы не хотите, чтобы это сохранить прошлое навсегда, так что вы, вероятно, хотите «мусор собирать» события более нескольких лет, в зависимости от ваших ограничений хранения.

Возможно, вам также понадобится возможность добавления примечаний и исключений (например, «Встреча» не происходит сегодня из-за общего праздника «или« переехала в 4 вечера ») на основании на вхождении. Это становится В самом деле Веселье, когда вы меняете рецидивов - если вы измените «каждый понедельник» на «каждый вторник», вы сохраняете исключения или нет? Как вы даже соответствуете исключениям, когда вы меняетесь из «каждый день» на «каждую неделю»? Это не вопросы, которые находятся непосредственно о хранении - но решения хранения будут влиять на то, насколько легко реализовать любую политику, которую вы решите.

Другие советы

Вам нужно будет обрабатывать отдельно события и вхождения.

Мероприятие WISE: для событий вам нужно будет хранить правила восстановления (что может быть подобным RRule, указанным RFC5545, но и явный набор дат, таких как rdate в RFC5545), но и исключения (см. Exdate rfc5545 и, возможно, экстерьера, как в RFC2445) Отказ Вам также потребуется отслеживать изменения в этих правилах: изменения в Rdate, Exdate без проблем, когда они происходят в будущем, и его игнорировать для прошлых дат. Изменения в RRULE более сложно, как влияют на предыдущие происшествия. Мои личные предпочтения состоит в том, чтобы добавить конкретное свойство для старого и нового RRULE для уточнения их соответствующего начала и окончания даты достоверности.

Если событие имеет ограниченное время промежутка времени (скажем, подсчет или до присутствия свойства), вы должны хранить свой начальный и конец в таблице, чтобы позволить более легким запросу событий (особенно при поиске вхождений за пределами вашего предварительного времени (см. Ниже), это Может помочь уменьшить количество событий, для которых вычисления должны быть переделаны).

Вступления Мудрые: для возникновения вы должны хранить экземпляры в пределах предопределенного окна вокруг настоящего (скажем, +/- 6 месяцев или 12 месяцев и вычисляются на регулярной основе) и сохраняйте записи этого, чтобы позволить повторному расчету, если ваши пользователи хотят видеть дальше в будущее (для выступлений вопросов). Вы также должны рассмотреть вопрос о вычислении индекса (рецидив-идентификатор), чтобы облегчить нахождение следующего возникновения.

Меньше на заднем конце, но больше на интерфейсе, вы также должны отслеживать TZID-изменения, чтобы попросить пользователя, если событие, которое было запланировано на данном TZID, если он должен остаться на текущем часовом поясе его должен быть Обновлено (подумайте о ком-то на острове Самоа, который запланировал встречу в пятницу, 30 декабря 2011 до того, как страна решила, что этот день не существует), аналогично вы можете спросить, если событие, которое происходит во время летнего времени, предназначена для «никогда не случиться "или" случиться дважды "(больше на этой теме здесь)

Примечание. Возможно, вы захотите рассмотреть вопрос о том, что определяется в RFC5545 с точки зрения правил рецензии, а также повысить поддержку религиозных рецидивирующих правил ( Смотрите Usno Введение в календари Или в печати «календальные расчеты» (третье издание) от E. Reingol и N. Dershowitz).

Поскольку вы спрашиваете о существующей реализации, вы можете легко проверить схему базы данных Sunbird (SQLite) или Apple Открытый исходный код календаря и сервер контактов, более полный список существующих проектов с открытым исходным кодом для серверов Caldav (который, вероятно, подмножество того, что вы ищете), доступен здесь)

Я должен был построить систему, которая работала с планированием, и мы сделали обоих. Вот что мы имели

  • Набор таблиц, которые держали отслеживание графика.
  • Таблица, которая сохранила отслеживание предыдущих экземпляров расписания (когда они на самом деле произошли)
  • Таблица, которая сохранила отслеживание последнего и следующего экземпляра (когда следующий элемент должен быть связан на основе в последнее время), вам не нужен эта таблица, но мы использовали его, потому что иначе вы будете постоянно рассчитывать, если предмет должен происходить сейчас

С планированием все может стать действительно хитрым, потому что вы должны помнить, что в любой момент времени расписание может измениться. Кроме того, элемент может быть предшествовать, когда ваше приложение не запущено, а когда он снова запускается, вам нужно знать, как определить прошедшие пункты.

Кроме того, мы уверены, что таблицы, которые держали отслеживание фактического графика, стояли в одиночестве. Причина этого состоит в том, что это был самый сложный набор таблиц в системе, и мы хотели иметь возможность повторно использовать их, чтобы их можно было использовать для разных вещей, которые необходимы планирования. Такие, как отправка электронной почты администратора, отправки уведомлений и обслуживание сервера, как очистки файлов журнала.

Я бы определенно использовал ваш второй вариант. Используйте различные варианты рецидива, храните его отдельно и рассчитайте на лету. Хранение всех этих дат будет лодочная нагрузка данных, которые не нужны.

Вот хороший ответ, чтобы дополнить ваш вопрос.
Структура данных для хранения повторяющихся событий?

Также как боковая заметка. Я начал хранить все время UTC, чтобы у вас была общая базовая линия, если вам когда-нибудь нужно использовать несколько часовых поясов.

У меня была похожая проблема в веб-приложении, которое я сделал несколько лет назад (теперь вполне может быть лучший путь :)). Я хотел включить планировщик, который имел все функциональные возможности повторяющихся событий, обрабатывать время, дни, недели, месяцы, годы и исключения, чтобы я мог иметь такие правила, как:

1) каждый день в 10 утрах исключен среда

2) каждые 2 часа с максимум 4 итерации в день

3) каждый первый понедельник месяца

так далее..

Хранение повторяющихся дат / раз было возможно, но негибкое. Каждая итерация вашего мероприятия меняется, когда «максимум» будет. И как далеко ты выглядишь?

В конце концов я написал пользовательский класс планирования, который мог прочитать и запись в строку. Это была строка, которая была сохранена в базе данных, а затем можно призвать простую функцию, чтобы узнать, когда следующее происшествие.

Вам нужно хранить некоторые из них наверняка. Пользователь может редактировать одно из событий, оставив других нетронутых (вы, вероятно, встречали вопрос: «Хотите ли вы редактировать все повторяющиеся события или только этот?» В некоторых календарях, то есть Windows Mobile).

Вы также можете хранить прошлые события и не удалять их, когда пользователь удаляет повторяющееся событие.

Если вы храните все остальные или генерируете их, это деталь реализации. Я бы предпочел генерировать их, если это возможно.

В любом случае вы захотите иметь какой-то идентификатор повторяющегося события, хранящегося с каждым событием, плюс какой-то флаг, рассказывающий вам, если событие было изменено позже. Или в более сложном подходе флаг для каждого свойства свойства событий, если это значение по умолчанию (из повторяющегося события) или если оно было изменено для этого конкретного экземпляра. Вам понадобится это, когда пользователь решит редактировать повторяющееся событие.

Обратите внимание, что большинство ответов наклоняется к сохранению сгенерированных данных. Но убедитесь, что вы считаете вашим применением.

Назад в те дни мои серверы были ограничены IO с большим количеством процессоров, ничего не делая. В наши дни у вас есть SSD (если вы можете себе позволить, в противном случае вы оставили со старым спиннингом HD), но обратите внимание, что подсчет Core также увеличился.

Приятная вещь об этих расчетах состоит в том, что вы можете легко разделить их и дать им свои многочисленные серверы или даже на несколько дешевых серверов в локальной сети. Часто дешевле, чем настройку кластера NoSQL или прохождение полноценного кластера базы данных.

И альтернатива также может быть кэшем, просто кэшируйте свой календарный вид, не нужно делать все расчеты каждый раз, когда ничего не изменилось.

Но как сказано, что это зависит от вашего случая использования. Не только следуйте приведенным выше ответам, но сделайте свои собственные расчеты, если у вас есть время, а также принять решение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top