2010-11-21 2 views
22

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

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

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

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

ответ

41

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

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

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

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

3

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

Вот хороший ответ, чтобы удовлетворить ваш вопрос.
Data structure for storing recurring events?

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

+0

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

+0

+1 в пользу сохранения повторения. Подумайте о прецеденте, когда пользователь перемещает экземпляр повторяющегося события: у нее есть возможность применить переход ко всем событиям, все последующие события, только это событие и т. Д. – Fuhrmanator

0

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

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

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

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

и т.д ..

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

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

+0

, но мне нужно больше, чем просто следующее вхождение – leora

+0

@ ooo, но хорошо написанный класс расписания может сделать именно это. С учетом текущей даты он может вычислить следующее вхождение, одно после этого ad-infinitum. Вход в функцию 'when()' должен быть «сейчас» и может возвращать следующую дату появления. Учитывая, что вы можете рассчитать столько, сколько хотите, либо подав дату, указанную в 'when()', либо этой функцией, которая возвращает вам целую последовательность. –

7

Мне пришлось создать систему, которая работала с расписанием, и мы сделали то и другое. Вот что мы имели

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

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

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

1

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

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

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

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

7

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

EVENT WISE: Для событий, вам нужно будет хранить правила recurence (которые могут быть rrule как указано rfc5545, но и явный набор дат, как rdate в rfc5545), но и исключения (см exdate из rfc5545 и, возможно, exrule, как в rfc2445). Вам также необходимо отслеживать изменения в этих правилах: Изменения в rdate, exdate не представляют проблемы, когда они происходят в будущем и игнорируются для прошлых дат. Изменения в rrule более сложны, так как они влияют на предыдущие случаи. Мое личное предпочтение заключается в добавлении определенного свойства для старого и нового rrule для указания их даты начала и окончания срока действия.

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

ЗАМЕЧАНИЯ: для случаев, в которых вы должны хранить экземпляры в пределах предопределенного окна вокруг настоящего (скажем +/- 6 месяцев или 12 месяцев и рассчитывать на регулярной основе) и вести учет этого, чтобы разрешить перерасчет, если ваши пользователи хотят видеть дальше в будущем (для выступлений). вы также должны рассмотреть возможность вычисления индекса (RECURRENCE-ID), чтобы облегчить поиск следующего события.

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

Примечание: вы можете захотеть рассмотреть вопрос о поддержке сверх того, что определено в rfc5545 с точки зрения правил recurence, а также добавить поддержку религиозных повторяющимися правил (see USNO introduction to calendars или в печати «Календарные расчеты» (Третье издание) от E. Reingol и N. Dershowitz).

Поскольку вы спрашиваете о существующей реализации, вы можете легко проверить схему базы данных sunbird (sqlite) или Apple open source Calendar and Contacts Server, более полный список существующих проектов с открытым исходным кодом для серверов caldav (что, вероятно, является частью того, что вы) here)

Смежные вопросы