Проектирование непересекающихся событий даты и времени
У меня есть следующая проблема:
События имеют время начала и окончания и количество. Я использую MySQL DATETIME для обоих.
Теперь, если у меня есть ограничение, которое говорит "нет перекрывающихся событий", мне нужно сделать несколько проверок и т. Д., Но как это спроектировать? Пользователю нужна только 5-минутная точность или около того, но я хочу делать вычисления с секундами, так как это "проще"/"чище"
Если у меня есть событие (A) с началом "YYYY-MM-DD 12:00:00"-"YYYY-MM-DD 14:00:00"
и другой
(B) "ГГГГ-ММ-ДД 14:00:00"-"ГГГГ-ММ-ДД 16:15:00" -> они не перекрываются, даже если они оба содержат 14:00:00.
Чтобы определить, что они действительно не перекрываются, я должен использовать
А. конец <Б. начало и т. Д.
Или же
A.end <= B.begin и т. Д. И сделайте "хак" таким образом, чтобы все времена окончания были "DATE HH:MM:00 (минус одна секунда)" вместо "DATE HH:MM:00", т.е. A.end тогда будет "ГГГГ-ММ-ДД 13:59:59" вместо "ГГГГ-ММ-ДД 14:00:00"
Первый простейший, но пропустит ли он какие-либо совпадения, если у меня много разных событий и мне нужно убедиться, что я не "перебронировал", т. Е. Что отдельные суммы событий не превышают общую сумму (пример: если каждое событие это бронирование столика с количеством человек, я не могу превышать общее количество столов в любой момент времени)
1 ответ
При работе с диапазонами даты и времени очень часто используется диапазон, включающий в начале и исключительный в конце. Например:
(using ISO8601 formatting)
Start End
2013-04-29T01:00:00Z - 2013-04-29T02:00:00Z
2013-04-29T02:00:00Z - 2013-04-29T03:00:00Z
Значение находится в диапазоне, когда оно меньше или равно началу и больше (но не равно) конца. В приведенном выше примере 02:00
принадлежит второму диапазону, а не первому. Другими словами:
Start <= value < End
Или, что то же самое,
Start <= value AND End > value
В математике, используя обозначение интервала, это называется "полуоткрытым" интервалом.
[Start, End)
Это всегда лучший подход, чем идея использования такого значения, как 01:59:59
, Подумай, если бы я вычел End - Start
чтобы получить продолжительность. Я ожидаю, что ответ будет один час, а не 59 минут и 59 секунд.
В большинстве примеров используются термины Start/End
, но иногда вы увидите Begin/End
или же Start/Stop
, Лично я думаю, что наилучший набор терминов, которые можно использовать, когда у вас есть инклюзивный / эксклюзивный диапазон, это Start/Until
, Он имеет дополнительное преимущество: оба термина состоят из 5 символов, расположены в алфавитном порядке и явно передают, что дата окончания является исключительной.
Кроме того, когда вы говорите об отдельных событиях, вы должны записывать свое время в формате UTC, чтобы избежать путаницы вокруг часовых поясов. Это даже важно для локальных приложений, поскольку многие часовые пояса проходят переходы на летнее время. Вы не хотите, чтобы значения, которые вы записали в базе данных, были неоднозначными. В MySQL вы можете использовать TIMESTAMP
тип данных, чтобы убедиться, что значения хранятся как UTC, или вы можете использовать DATETIME
тип данных, если вы можете быть уверены, что работаете со значениями UTC в коде приложения.