@rusgayfer

Как планировать даты по указанному расписанию (из списка времен)?

У меня пользователь выбирает время в которое будут выходить его посты (скриншот):

613b03dc66b8b766560107.png

Все эти времена хранятся в базе в столбце в таком формате: 09:20,09:40,11:20, 11:40 (списком через запятую).

Проблема в том, что когда все эти даты на текущий день планируются, то время остается пустое, так как я запланированные удаляю из массива. Поэтому когда уже пустой массив $dates то мне приходится из базы брать последнюю строку datetime и прибавлять к ней + 1 час.

А должно быть так: если на текущий день уже эти все времена запланированы, то должен начинать планировать заноного уже на следующий день:

Вот так должно планировать:
2021-09-10 09:20
2021-09-10 09:40
2021-09-10 11:20
2021-09-10 11:40
2021-09-11 09:20
2021-09-11 09:40
2021-09-11 11:20
2021-09-11 11:40
2021-09-12 09:20
2021-09-12 09:40


Вот часть этого кода:
$dateTime = date('Y-m-d H:i:s');

$wallGet = $main->requestVkAPI('wall.getById', "posts=-".$cal[0]['id_group']."_".$_POST['post_id']."&extended=1&access_token={$user[0]['token']}");

        foreach($wallGet['items'] as $wall) {

        // По расписанию
          if ($cal[0]['posting_date'] == 1) {

$dates_time = explode(",", mb_strtolower('09:20,09:40,11:20,11:40')); // указал примерно, тут до 50 таких времен может быть
$dates = array_merge($dates_time);

            // Если есть уже отложка на это время, то берем следующее
            $sql = $db->dbStream->prepare(" SELECT * FROM `autoposting_planned` WHERE `id_group` = ? ORDER BY `datetime` DESC ");
            $sql->bindValue(1, $wall['owner_id'], PDO::PARAM_INT);
            try {
              $sql->execute();
            } catch (PDOException $error) {
              trigger_error("Ошибка при работе с базой данных: {$error}");
            }
            $rowInfo = $sql->fetchAll(PDO::FETCH_ASSOC);

// Делаю выборку, если пост на это время уже сегодня запланирован, то время убираю из списка
            foreach ($rowInfo as $g) {
              $value_to_delete = date('H:i', strtotime($g['datetime']) );
              $dates = array_flip($dates);
              unset($dates[$value_to_delete]);
              $dates = array_flip($dates);
            }

            function closest($dates, $findate)
            {
              $newDates = array();

              foreach ($dates as $date) {
                $newDates[] = strtotime($date);
              }

              sort($newDates);
              foreach ($newDates as $a) {
                if ($a >= strtotime($findate))
                  return $a;
              }
              return strtotime( date('Y-m-d H:i', next($newDates)) . '+ 1 days');
            }

            $values = closest($dates, $dateTime);
            $timeposting = date('Y-m-d H:i', $values);

// Если дата этого времени прошла переводим на +1 час вперед от последней даты
// Вот это и добавил (это не нужно)!! Должно планировать на следующий день уже если времена закончились на сегодня
            if( strtotime($timeposting) < strtotime(date('Y-m-d H:i')) ) {
              $timeposting = date('Y-m-d H:i', strtotime( $rowInfo[0]['datetime']. '+ 1 hour'));
            }

// Заносим отложенный пост в базу
 $sql = $db->dbStream->prepare(" INSERT INTO `autoposting_planned` (`post_id`, `id_group`, `owner_id`, `datetime`) VALUES (?,?,?,?) ");
            $sql->bindValue(1, $wall['id'], PDO::PARAM_INT);
            $sql->bindValue(2, $wall['owner_id'], PDO::PARAM_INT);
            $sql->bindValue(3, $user[0]['id'], PDO::PARAM_INT);
            $sql->bindValue(4, $timeposting, PDO::PARAM_STR);
            try {
            $sql->execute();
            } catch (PDOException $error) {
            trigger_error("Ошибка при работе с базой данных: {$error}");
            }

}

}


Наверное можно сделать намного проще и быстрее, НО Я НЕ МОГУ ПОНЯТЬ КАК ЭТО СДЕЛАТЬ. Пока только до такого додумался.
  • Вопрос задан
  • 112 просмотров
Пригласить эксперта
Ответы на вопрос 1
@Akina
Сетевой и системный админ, SQL-программист.
Упрощённый пример того, как ежедневно в 09:20, 09:40, 11:20 и 11:40 вставлять в таблицу запись с заданными значениями.

Таблицы:

1. Значения для вставки
CREATE TABLE data ( 
    data_id INT AUTO_INCREMENT PRIMARY KEY,
    data_for_insertion VARCHAR(255) );
INSERT INTO data VALUES (1, 'Новое сообщение по расписанию', DEFAULT);

2.Расписание.
CREATE TABLE schedule ( 
    schedule_id INT AUTO_INCREMENT PRIMARY KEY,
    data_id INT,
    FOREIGN KEY (data_id) REFERENCES data (data_id) ON DELETE CASCADE ON UPDATE CASCADE,
    shedule_time TIME );
INSERT INTO schedule VALUES 
(NULL, 1, '09:20'), 
(NULL, 1, '09:40'), 
(NULL, 1, '11:20'), 
(NULL, 1, '11:40');

3. Таблица, куда надо вставлять записи
CREATE TABLE main ( 
    main_id INT AUTO_INCREMENT PRIMARY KEY,
    inserted_data VARCHAR(255),
    created_as DATETIME DEFAULT CURRENT_TIMESTAMP );

Процедура, которая будет вставлять данные
CREATE EVENT schedule
ON SCHEDULE EVERY 1 MINUTE
DO
    INSERT INTO main (inserted_data)
    SELECT data.data_for_insertion
    FROM data
    JOIN schedule USING (data_id)
    WHERE schedule_time > CURRENT_TIME - INTERVAL 1 MINUTE
      AND schedule_time <= CURRENT_TIME;

Всё. Осталось только разрешить использование Event Scheduler и запустить его.

Теперь только знай себе в своей программе на PHP правь данные в таблицах 1 и 2. Причём в любое время... В части выполнения нужного действия в нужное время MySQL всё будет делать сам, и никакого PHP ему не требуется.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы