PHP и MySQL: сравнение месяца и дня с динамическим годом

У меня возникли проблемы с приложением, над которым я работаю, и я надеюсь получить руководство.

У меня простая система бронирования: у каждого товара есть стандартная цена, но есть периоды, когда цена может измениться.

Например:

  • Стандартная цена 100 / день

  • От Oct. 1st в Feb. 1st каждого года цена 80 / день

  • От Jun. 1st в Aug. 31st каждого года цена 120 / день

  • […] до 6 различных ценовых изменений (сезонов)

Поскольку это событие происходит ежегодно, мне нужны только месяц и день, но я не знаю, как сохранить эти значения в базе данных. Я думал о том, чтобы иметь два поля, одно для месяца и одно для дня, которые содержат числовые значения (01-12 на месяц, 01-31 на день). Эти значения устанавливаются самим пользователем, и они относятся к самому элементу, он не установлен для всех.

Проблема в том, что когда кто-то делает бронирование, мне нужно проверить, нужно ли менять цену, и я не понимаю, как составить запрос, чтобы это проверить. Что еще хуже, цена может иметь несколько значений за забронированный период.

Следуя приведенному выше примеру, если бы я забронировал предмет из Sep. 1st (current year) в Jul. 1st (next year), цена будет следующим:

  • 100 / день от Sep. 1st в Sep. 30th

  • 80 / день от Oct. 1st в Feb. 1st

  • 100 / день от Feb. 2nd to May 31st

  • 120 / день от Jun. 1st в Jul. 1st

Есть ли какой-нибудь способ проверки этих случаев без ежедневного цикла и проверки соответствия базы данных?

Спасибо

2

Решение

Вы можете использовать MySQL date_format функция при проверке даты.

Например:

select date_format('2016-05-18', '%m%d');
+-----------------------------------+
| date_format('2016-05-18', '%m%d') |
+-----------------------------------+
| 0518                              |
+-----------------------------------+
1 row in set (0,01 sec)

Итак, вы можете просто проверить с простым интервалом: сегодня 0518 и между 2 февраля и 31 мая:

0202 <= 0518 <= 0531

Полный пример:

desc mytable;
+-----------+---------+------+-----+---------+-------+
| Field     | Type    | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| date_from | char(4) | YES  |     | NULL    |       |
| date_to   | char(4) | YES  |     | NULL    |       |
| price     | int(11) | YES  |     | NULL    |       |
+-----------+---------+------+-----+---------+-------+
3 rows in set (0,00 sec)

select * from mytable;
+-----------+---------+-------+
| date_from | date_to | price |
+-----------+---------+-------+
| 0901      | 0930    |   100 |
| 1001      | 0201    |    80 |
| 0202      | 0531    |   100 |
| 0601      | 0701    |   120 |
+-----------+---------+-------+
4 rows in set (0,00 sec)

Пример запроса:

select price, date_from, date_to from mytable where date_format(now(), '%m%d') between date_from and date_to;
+-------+-----------+---------+
| price | date_from | date_to |
+-------+-----------+---------+
|   100 | 0202      | 0531    |
+-------+-----------+---------+
1 row in set (0,01 sec)

РЕДАКТИРОВАТЬ:

Прочитайте ваш комментарий к ответу @ FelipeDuarte … В период с 10/01 (1 октября) по 02/01 (1 февраля) мы должны рассмотреть новый год …

Вы можете обмануть, разделив период на два: с 10 января по 31 декабря и с 01 января по 02 января

2

Другие решения

Я не знаю ваших таблиц базы данных, но я думаю, что вы могли бы сделать так:

  1. Получите ваш период, iniDay, iniMonth, endDay, endMonth
  2. Ваша таблица должна иметь следующие поля: ini_day, ini_month, ini_daymonth, end_day, end_month, end_daymonth, price_day
  3. SELECT * from table
    WHERE iniDay >= booking_ini_day AND iniMonth >= booking_ini_month -- get initial period
    AND iniDay <= booking_end_day AND iniMonth <= booking_end_month
    UNION ALL
    SELECT * from table
    WHERE iniDay <= booking_ini_day AND iniMonth <= booking_ini_month -- get middle periods
    AND endDay >= booking_end_day AND endMonth >= booking_end_month
    UNION ALL
    SELECT * from table
    WHERE
    endDay >= booking_ini_day AND endMonth >= booking_ini_month
    AND endDay <= booking_end_day AND endMonth <= booking_end_month -- get end period
  4. Подсчитайте дни для каждого периода / строки в вашем запросе результатов и покажите их вашему пользователю.

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

2

По вопросам рекламы [email protected]