Я собираю небольшую систему бронирования, где отображаются временные интервалы (каждые 30 минут).
Я хочу иметь возможность отмечать, когда в этот временной интервал попадает бронирование.
Итак, у меня есть DateTime ОТ и DateTime ДО для временного интервала.
Затем у меня есть бронирования DateTime ОТ и DateTime ТО для временного интервала.
Я не могу понять, как отметить временной интервал, что существует бронирование, которое (по крайней мере частично) занимает этот временной интервал.
Я пытаюсь с помощью этого сравнения определить, существует ли запись, но она помечается неправильно.
Вероятно, есть лучший способ сделать это. Есть какие-нибудь указатели?
var checkbookings = bookings
.Where(i => i.StartTime.TimeOfDay >= timeslot.StartTime.TimeOfDay)
.Where(i => i.EndTime.TimeOfDay <= timeslot.EndTime.TimeOfDay)
.FirstOrDefault();
Объект бронирования уже был пронумерован из базы данных с помощью ToList().
Во-первых, вам не нужны два предложения Where, вы можете использовать одно с &&. More importantly though, calling TimeOnly` генерирует операцию преобразования, которая предотвращает использование любых индексов для StartTime и EndTime. Если вам важно время, используйте тип time в базе данных и TimeOnly в C#.
Могут ли timeslot.StartTime и timeslot.EndTime находиться в разные дни?
Я знаю, что мне не нужны 2 предложения, но это делает его немного более читабельным на данный момент, пока я все еще работаю над ним.
@MaximilianBurszley тип на стороне клиента не влияет на запрос. Однако тип базы данных имеет значение. Этот запрос LINQ генерирует cast(starttime as time)>=@t1, который предотвращает использование индексов.
@TimSchmelter нет, будет в тот же день
LINQ — это функция итераторов, а не баз данных @PanagiotisKanavos
@PanagiotisKanavos Хорошо, если я сохраняю время только в специальном столбце базы данных для бронирования и использую TimeOnly в C# для временного интервала, как мне проверить совпадение?
@MaximilianBurszley и EF Core, как и этот вопрос
@MaximilianBurszley, спасибо, как мне сравнить два временных интервала, чтобы получить одинаковый результат?
Вы должны построить временной интервал для временного интервала и проверить, содержится ли в нем начало/конец резервирования.
@PanagiotisKanavos Вы делаете вывод о том, чего нет. Этот вопрос помечен только тегом С# и спрашивает только о сравнении дат и времени.
@MaximilianBurszley, но TimeSpan - это просто время, верно? Итак, если бы временной интервал был с 15:30 до 16:00, как бы я выразил это как TimeSpan?
@MaximilianBurszley нет, за эти годы я просто написал довольно много временных запросов до такой степени, что инстинктивно помню упрощенное условие. Вы говорите о timespan, как если бы это был период (в терминах временной БД). В C# TimeSpan — это продолжительность, и здесь он вообще не может помочь.





Логическое условие после небольшого логического упрощения и предположения, что поля равны time и TimeOnly:
.Where(i => timeslot.StartTime <= i.EndTime &&
timeslot.EndTime >= i.StartTime)
То, что вы спрашиваете, эквивалентно вопросу, перекрываются ли два линейных сегмента. Если вы нарисуете два временных отрезка на линии, они будут выглядеть так:
T-Start T-End
|-------------|
I-Start I-End
|------------------|
Независимо от того, какой сегмент первый или последний, начало одного из них предшествует концу другого.
Обновлять
Это условие обрабатывает заданное перекрытие. Если T-End и I-Start логически одинаковы, они все равно перекрываются. Однако в системе бронирования мы бы не сочли это совпадением. Хотя одним из вариантов является обеспечение того, чтобы время окончания было «непосредственно перед» фактическим завершением, более чистым решением было бы использовать <
.Where(i => timeslot.StartTime < i.EndTime &&
timeslot.EndTime > i.StartTime)
T-Start T-End
|-------------|
I-Start I-End
|------------------|
Часто мы включаем StartTime, но исключаем EndTime, в этом случае >= и <= следует заменить на > и <.
Вопрос в перекрытии. Если I-Start и T-End одинаковы, сегменты логически все равно перекрываются. Но да, возможно, это не то, что намеревается ФП.
@DmitryByченко немного странно, что я вспомнил упрощенное условие раньше, чем вспомнил, почему оно работает.
@PanagiotisKanavos Это было превосходно. Спасибо. Мне пришлось провести небольшой рефакторинг, и поскольку в .NET 7 (еще не переведенной на 8) пришлось добавить преобразователь типов данных, но теперь он дает желаемый эффект. Спасибо!
@MatthewWarr в .NET 7 и более ранних версиях вы можете использовать TimeSpan вместо TimeOnly.
Я бы предложил использовать временной интервал вместо того, чтобы просто сравнивать необработанные моменты времени, как вы есть, тогда вы сможете проверить, содержит ли этот интервал ваше бронирование.