Задать вопрос
@DeniSidorenko

Как правильнее сделать такой функционал?

Добрый день, есть вот такое объявления
31 Декабря с 8:00 до 17:00
1 Января выходной день
Со 2 января по 8 Января 10:00 до 23:00
9 Января с 11:00 до 23:00

График работы ресторана
Вопрос как лучше сделать что бы в дни и часы что ресторан не работал переменная $classMain = 'not-worked'

В остальное время ресторан работает круглосуточно кроме с 6 до 8
И я делал тогда такое условия

date_default_timezone_set('Europe/Moscow'); 
  $simpleDate = date('Y-m-d');
  $nameDay = date('l', strtotime($simpleDate));
  $timeMoscow =  intval(date('H'));
 if($nameDay == 'Saturday' || $nameDay == 'Sunday') {
    if($timeMoscow == 6 && $timeMoscow == 7 || $timeMoscow  == 8 || $timeMoscow == 9){
      $classMain = 'not-worked';
    }
  }


НО делать по такой же аналогии очень долго и неправильно. Может как то поставить данные в объекты и массив и по нему проверять. у кого какие есть идеи) Буду очень рад за подсказки
  • Вопрос задан
  • 209 просмотров
Подписаться 2 Простой 8 комментариев
Решения вопроса 1
@AndryG
Основная фишка задачи в том, что вы указали даты, разбили прямую времени на диапазоны и прокомментировали лишь часть из них. А еще есть другие диапазоны. Например, между 17 часов 31 дек и 0 часов 1 янв, который в задаче не указан и если не указать на него ЗАКРЫТО, то так дойдем до диапазона по умолчанию и получим ОТКРЫТО.

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

код
<?php

header('Content-type: text/plain');

?>31 Декабря с 8:00 до 17:00
  1 Января выходной день
  Со 2 января по 8 Января 10:00 до 23:00
  9 Января с 11:00 до 23:00

<?
$dtList = [
      ['12/31', '12/31', false, [['08:00', '17:00', true]]], // открыто
      ['01/01', '01/02', false, []], // закрыто (пустой диапазон времени)
      ['01/02', '01/08', false, [['10:00', '23:00', true]]],
      ['01/09', '01/09', false, [['11:00', '23:00', true]]],
      ['01/01', '12/31', true, [['06:00', '08:00', false]]],
];

$dt = new dt('2020-12-28');
$finish = (new dt('2021-01-14'))->getTimestamp();

do {
    $res = false;
    foreach ($dtList as [$a1, $b1, $def, $subList]) {
        $a1 = $dt->_clone($a1);
        $b1 = $dt->_clone($b1);
        if (h::testTimeRange($dt, $a1, $b1)) {
            foreach($subList as [$a2, $b2, $c2]){
                $a2 = $dt->_clone($a2);
                $b2 = $dt->_clone($b2);
                if (h::testTimeRange($dt, $a2, $b2)) {
                  $res = $c2;
                  break 2; // выход с обоих циклов
                }
            }
            $res = $def; // первый уровень сработал, а второй не имеет подх. диапазона, значит значение по умолчанию для перв. уровня
            break;
        }
    }
    echo "\n ", $dt->format(), $res ? ' open' : ' close';
    $dt->modify('+'.rand(1, 1).' hour');
} while ($dt->getTimestamp() < $finish);


результат
31 Декабря с 8:00 до 17:00
1 Января выходной день
Со 2 января по 8 Января 10:00 до 23:00
9 Января с 11:00 до 23:00

28.12.2020 00:00 open
28.12.2020 03:00 open
28.12.2020 05:00 open
28.12.2020 08:00 open
28.12.2020 09:00 open
28.12.2020 11:00 open
28.12.2020 12:00 open
28.12.2020 13:00 open
28.12.2020 15:00 open
28.12.2020 16:00 open
28.12.2020 18:00 open
28.12.2020 19:00 open
28.12.2020 20:00 open
28.12.2020 23:00 open
29.12.2020 02:00 open
29.12.2020 05:00 open
29.12.2020 06:00 close
29.12.2020 09:00 open
29.12.2020 12:00 open
29.12.2020 15:00 open
29.12.2020 17:00 open
29.12.2020 20:00 open
29.12.2020 22:00 open
29.12.2020 23:00 open
30.12.2020 02:00 open
30.12.2020 03:00 open
30.12.2020 06:00 close
30.12.2020 07:00 close
30.12.2020 10:00 open
30.12.2020 12:00 open
30.12.2020 15:00 open
30.12.2020 17:00 open
30.12.2020 19:00 open
30.12.2020 20:00 open
30.12.2020 23:00 open
31.12.2020 02:00 close
31.12.2020 05:00 close
31.12.2020 07:00 close
31.12.2020 09:00 close
31.12.2020 10:00 close
31.12.2020 13:00 close
31.12.2020 16:00 close
31.12.2020 19:00 close
31.12.2020 20:00 close
31.12.2020 23:00 close
01.01.2021 01:00 close
01.01.2021 02:00 close
01.01.2021 03:00 close
01.01.2021 04:00 close
01.01.2021 06:00 close
01.01.2021 09:00 close
01.01.2021 10:00 close
01.01.2021 11:00 close
01.01.2021 12:00 close
01.01.2021 13:00 close
01.01.2021 15:00 close
01.01.2021 16:00 close
01.01.2021 18:00 close
01.01.2021 20:00 close
01.01.2021 23:00 close
02.01.2021 00:00 close
02.01.2021 03:00 close
02.01.2021 06:00 close
02.01.2021 07:00 close
02.01.2021 10:00 open
02.01.2021 11:00 open
02.01.2021 12:00 open
02.01.2021 13:00 open
02.01.2021 14:00 open
02.01.2021 15:00 open
02.01.2021 16:00 open
02.01.2021 17:00 open
02.01.2021 18:00 open
02.01.2021 20:00 open
02.01.2021 23:00 close
03.01.2021 02:00 close
03.01.2021 04:00 close
03.01.2021 07:00 close
03.01.2021 10:00 open
03.01.2021 12:00 open
03.01.2021 13:00 open
03.01.2021 16:00 open
03.01.2021 17:00 open
03.01.2021 20:00 open
03.01.2021 22:00 open
03.01.2021 23:00 close
04.01.2021 00:00 close
04.01.2021 02:00 close
04.01.2021 05:00 close
04.01.2021 06:00 close
04.01.2021 09:00 close
04.01.2021 12:00 open
04.01.2021 13:00 open
04.01.2021 14:00 open
04.01.2021 15:00 open
04.01.2021 17:00 open
04.01.2021 19:00 open
04.01.2021 22:00 open
04.01.2021 23:00 close
05.01.2021 01:00 close
05.01.2021 02:00 close
05.01.2021 05:00 close
05.01.2021 06:00 close
05.01.2021 08:00 close
05.01.2021 10:00 open
05.01.2021 11:00 open
05.01.2021 14:00 open
05.01.2021 16:00 open
05.01.2021 17:00 open
05.01.2021 20:00 open
05.01.2021 23:00 close
06.01.2021 01:00 close
06.01.2021 03:00 close
06.01.2021 04:00 close
06.01.2021 05:00 close
06.01.2021 08:00 close
06.01.2021 09:00 close
06.01.2021 11:00 open
06.01.2021 13:00 open
06.01.2021 15:00 open
06.01.2021 18:00 open
06.01.2021 20:00 open
06.01.2021 22:00 open
07.01.2021 00:00 close
07.01.2021 01:00 close
07.01.2021 02:00 close
07.01.2021 03:00 close
07.01.2021 06:00 close
07.01.2021 07:00 close
07.01.2021 09:00 close
07.01.2021 10:00 open
07.01.2021 13:00 open
07.01.2021 14:00 open
07.01.2021 16:00 open
07.01.2021 17:00 open
07.01.2021 20:00 open
07.01.2021 23:00 close
08.01.2021 01:00 open
08.01.2021 02:00 open
08.01.2021 04:00 open
08.01.2021 05:00 open
08.01.2021 07:00 close
08.01.2021 09:00 open
08.01.2021 11:00 open
08.01.2021 14:00 open
08.01.2021 17:00 open
08.01.2021 20:00 open
08.01.2021 23:00 open
09.01.2021 00:00 open
09.01.2021 01:00 open
09.01.2021 02:00 open
09.01.2021 05:00 open
09.01.2021 07:00 close
09.01.2021 10:00 open
09.01.2021 12:00 open
09.01.2021 14:00 open
09.01.2021 17:00 open
09.01.2021 20:00 open
09.01.2021 22:00 open
09.01.2021 23:00 open
10.01.2021 01:00 open
10.01.2021 04:00 open
10.01.2021 05:00 open
10.01.2021 07:00 close
10.01.2021 10:00 open
10.01.2021 12:00 open
10.01.2021 14:00 open
10.01.2021 17:00 open
10.01.2021 19:00 open
10.01.2021 20:00 open
10.01.2021 23:00 open


класс dt
<?php
class dt extends DateTime{

  /** Формат отображения даты-времени по умолчанию в игре */
  const F_DEFAULT = 'd.m.Y H:i';

  /**
  * Создает
  *
  * @param mixed $time
  * @param DateTimeZone $timezone
  */
  public static function createRand($time = null, DateTimeZone $timezone = null){
    $time = preg_replace_callback('@/(\d+)-(\d+)/@', function($m){
         return (string)h::rand($m[1], $m[2]);
      }, $time);
    return new self($time, $timezone);
  }

  /**
  * $time допускает указание нескольких доп. параметров для modify() через разделитель |
  *
  * @param mixed $time
  * @param DateTimeZone $timezone
  * @return DateTime
  */
  public function __construct($time = null, DateTimeZone $timezone = null){
    $time = explode('|', $time);
    parent::__construct($time[0], $timezone);
    while($s = next($time)){
      $this->modify($s);
    }
  }

  /**
  * Вывод даты согласно формату
  *
  * @param string Мо умолчнию будет общепринятый в игре вариант F_DEFAULT
  * @return string
  */
  public function format($format = null){
    return parent::format(is_null($format) ? self::F_DEFAULT : $format);
  }

  /**
  * Клонирует текущий объект.
  * @return dt
  */
  public function _clone($modify = null){
    $res = clone $this;
    if(!is_null($modify)){
      $res->modify($modify);
    }
    return $res;
  }

  public function __toString(){
    return $this->format();
  }

}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Можно как-то так:
$schedule = [
  'weekdays' => [
    1 => [[0, 24]],
    2 => [[0, 24]],
    ...
    7 => [[0, 6], [8, 24]]
  ],
  'dates' => [
    '2020-12-31' => [[0, 6], [8, 17]],
    '2021-01-01' => [[0, 0]],
    '2020-01-02' => [[10, 23]],
    ...
  ]
];
function isWorkTime($schedule) {
  $date = date('Y-m-d');
  $weekday = intval(date('N'));
  $hour = intval(date('H'));
  $daySchedule = $schedule['weekdays'][$weekday];
  if (array_key_exists($date, $schedule['dates']]) {
    $daySchedule = $schedule['dates'][$date];
  }
  foreach ($daySchedule as $workTime) {
    if ($hour >= $workTime[0] && $hour < $workTime[1]) {
      return true;
    }
  }
  return false;
}
Ответ написан
Комментировать
FanatPHP
@FanatPHP
Чебуратор тега РНР
Решение очевидное - все нестандартные интервалы записать в массив, и проходить по нему
Проверять надо разумеется одновременно дату и время, а не по отдельности
Начни с 1 января - там самый простой интервал.
и дальше продолжай добавлять.

потом проходишь по массиву и сравниваешь текущее время с интервалами. если входит - то ставим флаг и выходим из цикла
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы