Я не знаю, как это сделать. Я создаю календарь на PHP и нуждаюсь в том, чтобы пользователи могли добавлять повторяющееся событие, которое следует следующему правилу:
Последний [DOW] месяца (так последний [Mon / Вт / Wed / etc] недели)
У меня есть правило, которое хранится, я просто не уверен, как лучше всего экстраполировать последний Mon / Tue / Wed месяца в PHP? Я упал, как будто делаю это более сложным, чем нужно.
Предполагая, что у вас есть переменные для $month=4
, $dow=3
и $year=2011
как бы мне лучше всего это сделать?
Для всех связанных с датой, которые вы можете выразить на должном английском языке, но с трудом strtotime
с помощью чисел, strtotime
– ваш лучший друг.
echo strtotime("last Monday of June 2011");
Это возвращает временную метку, которую вы можете использовать в качестве второго параметра на date
и любит получать правильную, удобочитаемую человеком дату. Поскольку это встроенная функция, написанная на C, это решение также намного быстрее, чем почти все, что вы могли бы придумать на PHP (хотя я уверен, что это не имеет большого значения в реальном сценарии).
Предположим, что у вас есть $month=4
, $dow=3
и $year=2011
, вам понадобится массив, сопоставляющий значения $month
с их текстовыми представлениями на английском языке и другой массив, сопоставляющий значения $dow
с их текстовыми представлениями.
Вот альтернатива:
<? function lastDayOfMonth($month, $year) { switch ($month) { case 2: # if year is divisible by 4 and not divisible by 100 if (($year % 4 == 0) && ($year % 100) > 0) return 29; # or if year is divisible by 400 if ($year % 400 == 0) return 29; return 28; case 4: case 6: case 9: case 11: return 30; default: return 31; } } function lastDayOfWeek($month, $year, $dow) { $d = new DateTime(); #Finding the last day of month $d = $d->setDate($year, $month, lastDayOfMonth($month, $year)); #Getting the day of week of last day of month $date_parts = getdate($d->getTimestamp()); $diff = 0; #if we can't find the $dow in this week... (cause it would lie on next month) if ($dow > $date_parts['wday']) { # ...we go back a week. $diff -= 7; } return $date_parts['mday'] + $diff + ($dow - $date_parts['wday']); } # checking the algorithm for this month... for ($i=0; $i < 7; $i++) { echo lastDayOfWeek(6,2011,$i) . "<br>"; } ?>
У меня есть общая функция для вычисления n-го числа месяца. Надеюсь, это поможет вам решить вашу проблему.
function get_Nth_dow($dow, $occurence, $m, $y) { $numdays = date('t', mktime(0, 0, 0, $m, 1, $y)); $add = 7 * ($occurence - 1); $firstdow = date('w', mktime(0, 0, 0, $m, 1, $y)); $diff = $firstdow - $dow; $day_of_month = 1; if ($diff > 0) { $day_of_month += ($add - $diff); } elseif ($diff < $numdays) { $day_of_month -= ($diff - $add); } return $day_of_month; }
$DOW
= день недели (0 = воскресенье, 6 = суббота).
$X
= встречаемость (1 = первая, 2 = третья и т. Д.). Если данный месяц
не имеет вхождения, то он вернет последнее. Например, если
вы просите 7-ое пятно пятницы, оно вернет последнее
Пятница месяца. $M
= месяц $Y
= год
Например, get_Nth_DOW(2,3,7,2009)
вернется в третий вторник 7-го 2009 года.