Получение всех дат по понедельникам и вторникам на следующий год

Мне нужно вывести список дат (только по понедельникам и вторникам) в течение следующих 12 месяцев с текущей даты, например:

Январь 2010 г.
Вт 12 янв 2010
Пн 18 янв 2010
Вт 19 янв 2010
Пн 25 янв 2010
Февраль 2010 г.
Вт 02 фев 2010
Пн 08 Фев 2010
Вт 09 Фев 2010
Пн 15 Фев 2010
Вт 16 фев 2010
Пн 22 фев 2010
Март 2010 г.
Вт 09 Мар 2010
Пн 15 Мар 2010
Вт 16 мар 2010

Будучи новичком в PHP, я решил, что strtotime и цикл в течение следующих 52 недель – лучший способ.

$blockedDatesInput = "08 Mar 2010,12 Apr 2010"; // dont show these dates $blockedDates = explode ("," , $blockedDatesInput); // convert to array $currentMonth = ""; // current month marker // loop over the next 52 weeks to find Mondays and Tuesdays for($i=0; $i<=52; $i++){ // build the month header $monthReference = date("MY", strtotime('+'.$i.' Week')); // check if date exists in $blockeddate if (!in_array(date("d MY", strtotime('+'.$i.' Monday')), $blockedDates) || !in_array(date("d MY", strtotime('+'.$i.' Tuesday')), $blockedDates) ) { // check if we have to show a new month if(strcmp($monthReference, $currentMonth) <> 0){ echo $monthReference.'<br />',"\n"; }else{ // output the dates echo date("D d MY", strtotime('+'.$i.' Monday')).'<br />',"\n"; echo date("D d MY", strtotime('+'.$i.' Tuesday')).'<br />',"\n"; } $currentMonth = date("MY", strtotime('+'.$i.' Week')); } } 

Однако вывод моего кода

Январь 2010 г.
Пн 18 янв 2010
Вт 12 янв 2010
Пн 25 янв 2010
Вт 19 янв 2010
Февраль 2010 г.
Пн 08 Фев 2010
Вт 02 фев 2010
Пн 15 Фев 2010
Вт 09 Фев 2010
Пн 22 фев 2010
Вт 16 фев 2010
Март 2010 г.
Пн 08 Мар 2010
Вт 02 Мар 2010
Пн 15 Мар 2010
Вт 09 Мар 2010
Пн 22 Мар 2010
Вт 16 мар 2010
Пн 29 Мар 2010
Вт 23 мар 2010

Как вы можете видеть, даты не в правильном порядке, и я в недоумении, где я ошибаюсь.

Есть ли более элегантный / простой способ решить эту проблему?

Версия используемого PHP – 5.2.11, и в ближайшее время не ожидается перехода к 5.3 🙁

Спасибо за вашу помощь.

Код ниже модификации, предложенный Али. Изменена дата компьютера от Tue, 12/01/2010 до Wed, 13/01/2010, чтобы проверить выход.

 $blockedDatesInput = "08 Mar 2010,12 Apr 2010"; // dont show these dates $blockedDates = explode ("," , $blockedDatesInput); // convert to array $currentMonth = ""; // current month marker // loop over the next 52 weeks to find Mondays and Tuesdays for($i=0; $i<=52; $i++){ // build the month header $monthReference = date("MY", strtotime('+'.$i.' Week')); // check if date exists in $blockeddate if (!in_array(date("d MY", strtotime('+'.$i.' Monday')), $blockedDates) || !in_array(date("d MY", strtotime('+'.$i.' Tuesday')), $blockedDates) ) { // check if we have to show a new month if(strcmp($monthReference, $currentMonth) <> 0){ echo $monthReference.'<br />',"\n"; }else{ // output the dates (changed the order as suggested by Aly) echo date("D d MY", strtotime('+'.$i.' Tuesday')).'<br />',"\n"; echo date("D d MY", strtotime('+'.$i.' Monday')).'<br />',"\n"; } $currentMonth = date("MY", strtotime('+'.$i.' Week')); } } 

Вывод снова в неправильном порядке.

Январь 2010 г.
Вт 19 янв 2010
Пн 18 янв 2010
Вт 26 янв 2010
Пн 25 янв 2010
Февраль 2010 г.
Вт 09 Фев 2010
Пн 08 Фев 2010
Вт 16 фев 2010
Пн 15 Фев 2010
Вт 23 фев 2010
Пн 22 фев 2010

Это интересно. Вот как я буду делать это с функциями, хотя он может гарантировать, что его собственный класс действительно будет модульным и многоразовым:

 Set up my date formats and excluded dates define('INTERNAL_FORMAT', 'Ym-d'); define('DISPLAY_MONTH_FORMAT', 'M Y'); define('DISPLAY_DAY_FORMAT', 'D d M Y'); // format excluded dates as YYYY-MM-DD, date('Ym-d'): $excluded_dates = array( '2010-03-09', '2010-04-13', ); 

Затем мне нужны некоторые функции утилиты, чтобы увидеть, как выполняются даты и какие даты исключаются:

 // date('w') returns a string numeral as follows: // '0' Sunday // '1' Monday // '2' Tuesday // '3' Wednesday // '4' Thursday // '5' Friday // '6' Saturday function isTuesday($date) { return date('w', strtotime($date)) === '2'; } function isWednesday($date) { return date('w', strtotime($date)) === '3'; } // handle the excluded dates function isExcludedDate($internal_date) { global $excluded_dates; return in_array($internal_date, $excluded_dates); } 

Теперь нам просто нужно перебирать каждый день следующего 365 (в следующем году) и проверять, есть ли они во вторник или среду, а не в исключенном списке. Мы сохраняем это в $months_and_dates :

 $start_date = date(INTERNAL_FORMAT); // something to store months and days $months_and_dates = array(); // loop over 365 days and look for tuesdays or wednesdays not in the excluded list foreach(range(0,365) as $day) { $internal_date = date(INTERNAL_FORMAT, strtotime("{$start_date} + {$day} days")); $this_day = date(DISPLAY_DAY_FORMAT, strtotime($internal_date)); $this_month = date(DISPLAY_MONTH_FORMAT, strtotime($internal_date)); if ((isTuesday($internal_date) || isWednesday($internal_date)) && !isExcludedDate($internal_date)) { $months_and_dates[$this_month][] = $this_day; } } 

Вы можете print_r() , или, чтобы получить нужный дисплей, мы делаем следующее:

 foreach($months_and_dates as $month => $days) { print $month . "<br>"; print implode('<br>', $days); print "<br>"; } 

Вот результат на сегодня, 11 января 2010 года:

 Jan 2010 Tue 12 Jan 2010 Wed 13 Jan 2010 Tue 19 Jan 2010 Wed 20 Jan 2010 Tue 26 Jan 2010 Wed 27 Jan 2010 Feb 2010 Tue 02 Feb 2010 Wed 03 Feb 2010 Tue 09 Feb 2010 Wed 10 Feb 2010 Tue 16 Feb 2010 Wed 17 Feb 2010 Tue 23 Feb 2010 Wed 24 Feb 2010 Mar 2010 Tue 02 Mar 2010 Wed 03 Mar 2010 Wed 10 Mar 2010 Tue 16 Mar 2010 Wed 17 Mar 2010 Tue 23 Mar 2010 Wed 24 Mar 2010 Tue 30 Mar 2010 Wed 31 Mar 2010 Apr 2010 Tue 06 Apr 2010 Wed 07 Apr 2010 Wed 14 Apr 2010 Tue 20 Apr 2010 Wed 21 Apr 2010 Tue 27 Apr 2010 Wed 28 Apr 2010 May 2010 Tue 04 May 2010 Wed 05 May 2010 Tue 11 May 2010 Wed 12 May 2010 Tue 18 May 2010 Wed 19 May 2010 Tue 25 May 2010 Wed 26 May 2010 Jun 2010 Tue 01 Jun 2010 Wed 02 Jun 2010 Tue 08 Jun 2010 Wed 09 Jun 2010 Tue 15 Jun 2010 Wed 16 Jun 2010 Tue 22 Jun 2010 Wed 23 Jun 2010 Tue 29 Jun 2010 Wed 30 Jun 2010 Jul 2010 Tue 06 Jul 2010 Wed 07 Jul 2010 Tue 13 Jul 2010 Wed 14 Jul 2010 Tue 20 Jul 2010 Wed 21 Jul 2010 Tue 27 Jul 2010 Wed 28 Jul 2010 Aug 2010 Tue 03 Aug 2010 Wed 04 Aug 2010 Tue 10 Aug 2010 Wed 11 Aug 2010 Tue 17 Aug 2010 Wed 18 Aug 2010 Tue 24 Aug 2010 Wed 25 Aug 2010 Tue 31 Aug 2010 Sep 2010 Wed 01 Sep 2010 Tue 07 Sep 2010 Wed 08 Sep 2010 Tue 14 Sep 2010 Wed 15 Sep 2010 Tue 21 Sep 2010 Wed 22 Sep 2010 Tue 28 Sep 2010 Wed 29 Sep 2010 Oct 2010 Tue 05 Oct 2010 Wed 06 Oct 2010 Tue 12 Oct 2010 Wed 13 Oct 2010 Tue 19 Oct 2010 Wed 20 Oct 2010 Tue 26 Oct 2010 Wed 27 Oct 2010 Nov 2010 Tue 02 Nov 2010 Wed 03 Nov 2010 Tue 09 Nov 2010 Wed 10 Nov 2010 Tue 16 Nov 2010 Wed 17 Nov 2010 Tue 23 Nov 2010 Wed 24 Nov 2010 Tue 30 Nov 2010 Dec 2010 Wed 01 Dec 2010 Tue 07 Dec 2010 Wed 08 Dec 2010 Tue 14 Dec 2010 Wed 15 Dec 2010 Tue 21 Dec 2010 Wed 22 Dec 2010 Tue 28 Dec 2010 Wed 29 Dec 2010 Jan 2011 Tue 04 Jan 2011 Wed 05 Jan 2011 Tue 11 Jan 2011 

в смешном совпадении, потому что сегодня понедельник, он пропускает одно понедельное значение, поэтому они выглядят не по порядку. вчера это сработало бы хорошо.

т.е. ваш «+ 0 понедельник» СЛЕДУЮЩИЙ понедельник, а не сегодня.

вы можете захотеть просмотреть символ формата «N» для даты ().

Теперь, когда ваша дата компьютера – среда, вы хотите распечатать понедельники до вторника, так как следующий понедельник ближе к среду, чем в следующий вторник. Поэтому попробуйте следующее:

 $blockedDatesInput = "08 Mar 2010,12 Apr 2010"; // dont show these dates $blockedDates = explode ("," , $blockedDatesInput); // convert to array $currentMonth = ""; // current month marker // loop over the next 52 weeks to find Mondays and Tuesdays for($i=0; $i<=52; $i++){ // build the month header $monthReference = date("MY", strtotime('+'.$i.' Week')); // check if date exists in $blockeddate if (!in_array(date("d MY", strtotime('+'.$i.' Monday')), $blockedDates) || !in_array(date("d MY", strtotime('+'.$i.' Tuesday')), $blockedDates) ) { // check if we have to show a new month if(strcmp($monthReference, $currentMonth) <> 0){ echo $monthReference.'<br />',"\n"; }else{ // output the dates (changed the order as suggested by Aly) echo date("D d MY", strtotime('+'.$i.' Monday')).'<br />',"\n"; echo date("D d MY", strtotime('+'.$i.' Tuesday')).'<br />',"\n"; } $currentMonth = date("MY", strtotime('+'.$i.' Week')); } }