Поэтому мне нужно создать своего рода ежедневный календарь с доступным временем, чтобы пользователь мог забронировать встречу с одним врачом из кабинета нескольких врачей.
Я надеюсь, что это объяснение не слишком странно уже ..
Кстати, я использую Laravel 5.5
Вот пример:
График работы кабинета по умолчанию: с 9:00 до 19:00
Доктор 1 говорит, что в понедельник он будет доступен только с 13:00 до 15:00
Доктор 2 говорит, что в понедельник он будет доступен только с 10:00 до 14:00
Когда я запрашиваю доступные временные интервалы:
$ids = Doctor::all()->pluck('id');
$workingSchedules = WorkingSchedule::whereIn('user_id', $ids)
->orderBy('start_date')
->whereDate('start_date', '=', $this->datetime->format('Y-m-d'))
->get();
Я получил:
0 => [
"start_date" => "2017-09-18 10:00:00"
"end_date" => "2017-09-18 14:00:00"
]
1 => [
"start_date" => "2017-09-18 13:00:00"
"end_date" => "2017-09-18 15:00:00"
]
И если из базы данных ничего не появляется, я использую часы кабинета по умолчанию.
Затем я использую метод Carbon diffInMinutes()
, чтобы построить массив из 30-минутных временных интервалов между этими диапазонами дат (которые может выбрать пользователь).
В любом случае, чтобы мой скрипт работал правильно, мне нужно преобразовать результат, который я показал вам, в следующее:
0 => [
"start_date" => "2017-09-18 10:00:00"
"end_date" => "2017-09-18 15:00:00"
]
Поскольку в этом примере у меня есть только два временных интервала, это может быть простым решением, но я также могу получить массив из 10 временных интервалов, которые перекрывают друг друга.
Может ли кто-нибудь помочь мне найти элегантное решение, которое охватит все возможные случаи?
Заранее большое спасибо.
3 ответа
Чтобы объединить перекрывающиеся периоды времени, вы можете использовать этот код:
$result = [];
$i = -1;
foreach ($workingSchedules as $row) {
if ($i < 0 || $row["end_date"] > $result[$i]["end_date"]) {
if ($i >= 0 && $row["start_date"] <= $result[$i]["end_date"]) {
$result[$i]["end_date"] = $row["end_date"];
} else {
$result[++$i] = $row;
}
}
}
$result
будет иметь только непересекающиеся периоды.
Я надеюсь, это поможет.
$workingSchedules=array(
0=>array(
"start_date" => "2017-09-18 10:00:00",
"end_date" => "2017-09-18 14:00:00"),
1=>array(
"start_date" => "2017-09-18 13:00:00",
"end_date" => "2017-09-18 15:00:00"
)
);
foreach ($workingSchedules as $schedule){
$start=new DateTime($schedule['start_date']);
$end=new DateTime($schedule['end_date']);
while ($start<=$end){
echo $start->format('Y-m-d H:i')."<br/>";
$start=$start->add(new DateInterval('PT'.'30'.'M'));
}
}
Чтобы было проще, я буду предполагать, что $ workingSchedules - это массив чисел, тогда мы можем легко сравнивать элементы
$workingSchedules = [
[
'start_date' => 1,
'end_date' => 5,
],
[
'start_date' => 13,
'end_date' => 16,
],
[
'start_date' => 16,
'end_date' => 17,
],
];
$result = [$workingSchedules[0]];
$index = 0;
foreach ($workingSchedules as $row) {
if ($result[$index]['end_date'] >= $row['start_date']) {
$result[$index]['end_date'] = max($result[$index]['end_date'], $row['end_date']);
} else {
$index++;
$result[] = $row;
}
}
var_dump($result);
Над кодом будет напечатано:
[
[
'start_date' => 1,
'end_date' => 5,
],
[
'start_date' => 13,
'end_date' => 17,
],
]
- Вы можете настроить код для сравнения 2 даты вместо числа
- Если $ workingSchedules пуст, мы можем просто вернуть расписание по умолчанию
Новые вопросы
php
PHP - это широко используемый высокоуровневый, динамический, объектно-ориентированный и интерпретируемый язык сценариев, в первую очередь предназначенный для серверной веб-разработки. Используется для вопросов о языке PHP.