Создание календаря средствами PHP и CSS

27-08-2010

Сейчас мы попробуем сделать простенький календарь для сайта или еще для чего нибудь, не знаю ). Календарь будет не совсем простым можно будет переключатся между месяцами, а текущий день будет выделен среди других дней также другим цветом(красным) будут выделены выходные, правда только воскресения субботы я чето не стал выделять, ну это не важно.
Так как календарь будет переключатся между месяцами мы должны это как то передавать например методом GET т.е. через url адрес. Также напишем для календаря простенькие CSS чтоб можно было смотреть)) так это календарь удобней всего оформить его в виде таблицы. Внешне календарь будет выглядеть примерно так:

cakendar witht-css

На PHP мы создадим две переменные $calendar_head и $calendar_body соответственно в $calendar_head мы будем записывать html код верхней части календаря т.е. название месяца, дни недели и две ссылки по краям для выбора месяца. А в $calendar_body будем сохранять остальной код то есть таблицу дней недели. Ниже на скрине показано:

Теперь рассмотрим сам php код:

// проверяем передали ли нам месяц и год
if(isset($_GET["ym"])){

	$year  = (int)substr($_GET["ym"], 0, 4);
	$month = (int)substr($_GET["ym"], 4, 2);

}
else{ // иначе выводить текущие месяц и год

	$month = date("m", mktime(0,0,0,date('m'),1,date('Y')));
	$year  = date("Y", mktime(0,0,0,date('m'),1,date('Y')));

}

$skip          = date("w", mktime(0,0,0,$month,1,$year)) - 1; // узнаем номер дня недели
if($skip < 0){ 
	$skip = 6; 
}
$daysInMonth   = date("t", mktime(0,0,0,$month,1,$year));	// узнаем число дней в месяце
$calendar_head = '';	// обнуляем calendar head
$calendar_body = '';	// обнуляем calendar boday
$day = 1;	// для цикла далее будем увеличивать значение

for($i = 0; $i < 6; $i++){ // Внешний цикл для недель 6 с неполыми

	$calendar_body .= '<tr>';	// открываем тэг строки
	for($j = 0; $j < 7; $j++){	// Внутренний цикл для дней недели
	
		if(($skip > 0)or($day > $daysInMonth)){ // выводим пустые ячейки до 1 го дня ип после полного количства дней
		
			$calendar_body .= '<td class="none"> </td>'; 
			$skip--;

		}
		else{
			
			if($j == 0)	// если воскресенье то омечаем выходной
				$calendar_body .= '<td class="holiday">'.$day.'</td>'; 
			else{	// в противном случае просто выводим день в ячейке
				if ((date(j)==$day)(date(m)==$month)(date(Y)==$year)){//проверяем на текущий день
					$calendar_body .= '<td class="today">'.$day.'</td>';
				}	
				else{ 
					$calendar_body .= '<td class="day">'.$day.'</td>'; 
				   }
				 }
			$day++; // увеличиваем $day
		}
		
	}
	$calendar_body .= '</tr>'; // закрываем тэг строки
}

// заголовок календаря
$calendar_head = '
  <tr>  	
	<th colspan="2"><a href="?ym='.date("Ym", mktime(0,0,0,$month-1,1,$year)).'">« Пред</a></th>
  	<th colspan="3">'.date("F, Y", mktime(0,0,0,$month,1,$year)).'</th>
  	<th colspan="2"><a href="?ym='.date("Ym", mktime(0,0,0,$month+1,1,$year)).'">След »</a></th>
  </tr>
  <tr>
    <th>Понедельник</th>
    <th>Вторник</th>
    <th>Среда</th>
    <th>Четверг</th>
    <th>Пятница</th>
    <th>Суббота</th>
    <th>Воскресенье</th>
  </tr>';

Я думаю здесь уже нечего объяснять комментариев кажется достаточно, единственно я бы хотел пояснить почему 6 строк ведь недель в месяце всего четыре так вот, так как мы месяц начинаем выводить не с понедельника, то есть месяц не всегда начинается с понедельника, у нас появляются неполные недели и посчитав максимальное количество неполных и полных недель вы получите шесть недель вот поэтому и шесть). Но так как 6 недель встречаются не очень часто, то последняя строка в таблице чаще всего будет пустой.
Далее осталось написать HTML код и вывести в нужных местах $calendar_head и $calendar_body, ну и прописать CSS стили. Рассмотрим содержание тега <body>:

<!-- таблица для вывода календаря -->
<table id="calendar" width="710" border="1" cellspacing="0" cellpadding="5">
	<thead>
		<?php echo $calendar_head; ?>
	</thead>
	<tbody>
		<?php echo $calendar_body; ?>
	</tbody>
</table>
<!-- таблица для вывода календаря -->

Как видим календарь состоит полностью из таблицы заголовка и тела. Теперь наш календарь выглядит примерно аот так:

calendar without css

То есть осталось прописать CSS стили, ну примерно вот такие:

body{
	margin:0 auto;
	width:800px; 
	padding:10px;
}
#calendar{
	border:0px;
}
#calendar tbody tr{
	height:40px;
}
#calendar td{ 
	width:80px; 
	border:0px; 
	border:solid 1px #99FF99; 
	font-size:22px; 
	text-align:center;
}
#calendar th{
	background-color:#4DDBFF; 
	border:solid 1px #00CCFF; 
	color:#ffffff;
}
#calendar td.none{
	border:0px;
}
#calendar td.holiday{ 
	background-color:#FF6633; 
	border-color:#FF531A; 
	color:#94E4FF;
}
.day{ 
	background-color:#CCFFCC; 
	color:#00B32D;
}
#calendar td.today{
	background-color:#FFFF99; 
	border-color:#FF531A;
}

Ну вот и все теперь календарь выглядит примерно так:

cakendar witht-css

Весь исходный код можете посмотреть здесь

Еремин6.18.2010 04:06
Актуально. Хотелось бы на одном из сайтов усовершенствовать календарик. У меня задача немного сложнее сейчас мне нужно вывести 2 последующих месяца и определенные промежутки к примеру с сегодняшнего числа по 10ое число каждого месяца выделять другим цветом. К примеру заказы на сентябрь можно успеть сделать до 10го июля, у вас осталось X дней.
Mak6.21.2010 01:06
В принципе не плохо. Вот бы ещё ячейки с датами сделать с закругленными краями.
Аёха1.27.2011 10:01
Можно использовать календарь, написанный на java script, календарь динамический. Пример календаря:
Макс4.10.2011 10:04
В цикле создания таблицы, после закрытия тега (т.е. перед закрытием внешнего цикла) можно добавить ... $calendar_body .= '';//это уже есть if ($day > $daysInMonth) break;//это можно добавить ... Это позволит не создавать лишнюю 6-ю строку таблицы, если там нет дней.
Макс4.10.2011 10:04
Как коряво отобразился комментарий
Макс4.10.2011 11:04
чтобы календарь стал русским(т.е. первый день понедельник), после определения дня недели добавляем $skip=$skip - 1; if ($skip == -1) $skip=6; //Ну и соответственно дни недели в таблице меняем.
    LEmax9.18.2011 08:09
    тогда в строке "if($j==0)//если воскресенье то отмечаем выходной" нужно заменить 0 на 6. И еще, я долго не мог понять, почему у меня не высвечивался сегодняшний день недели. Потом дошло, что просто нужно поменять местами определения, т.е. сначала нужно определить сегодняшний ли день мы получили, если да - отмечаем, если нет - то проверка на выходной или будний день. if((date(j)==$day)&&(date(m)==$month)&&(date(Y)==$year)){//проверяем на текущий день $calendar_body .= ''.$day.''; } else{ if($j ==6) // если воскресенье то отмечаем выходной $calendar_body .= ''.$day.''; else $calendar_body .= ''.$day.''; // в противном случае просто выводим день в ячейке }
      Алексей10.8.2011 08:10
      Люди, пожалуйста, пришлите полностью исправленный код с переводом календаря в русский формат и с правильной проверкой заранее благодарен
      e)I(11.21.2012 07:11
      Тогда уж вместо "if($j==0) надо бы "if($j>=5), чтоб и субботы выходными заделать для полной дебуржуизации можно добавить: $Month_Text['1'] = 'Январь'; $Month_Text['2'] = 'Февраль'; $Month_Text['3'] = 'Март'; $Month_Text['4'] = 'Апрель'; $Month_Text['5'] = 'Май'; $Month_Text['6'] = 'Июнь'; $Month_Text['7'] = 'Июль'; $Month_Text['8'] = 'Август'; $Month_Text['9'] = 'Сентябрь'; $Month_Text['10'] = 'Октябрь'; $Month_Text['11'] = 'Ноябрь'; $Month_Text['12'] = 'Декабрь'; а вместо: '.date("F, Y", mktime(0,0,0,$month,1,$year)).' это: '.$Month_Text[$month].' - '.$year.' г
      Andrey3003.20.2013 09:03
      Спасибо!
Игорь8.7.2011 09:08
Спасибо за скрипт. Я тут себе позволил немного извратиться в css, получилось очень здорово. Примерно так - http://cs5341.vkontakte.ru/u589298/140315676/x_8afab68a.jpg Извините, что выкладываю картинку вКонтакте, на сайте просто нет возможности прикрепить фото, а на хостинге у меня место закончилось :( З.Ы. Кому интересно - пишите, css вышлю на мыло
    Алексей9.9.2011 01:09
    Игорь. Вышли css на мыло - leha_74rus@mail.ru если не сложно... Заранее спасибо)))
    Алексей10.8.2011 08:10
    Игорь пришлите пожалуйста css на alex.pudovkin@freenet.de
    Екатерина1.18.2012 07:01
    Здравствуйте, Игорь! Очень понравился календарь Пришлите css. ekaterinafb@gmail.com
    Nurs7.31.2012 12:07
    a mojno mne?
    Роман9.10.2012 09:09
    Игорь, вышлите пожалуйста, на мыло css. toxi22 {at} mail.ru
    Владимир10.9.2012 01:10
    И мне, пожалуйста! :) temp0555@mail.ru
    Андрей2.9.2013 12:02
    Пришлите пожалуйста ваш css на почту torg10@bk.ru
    Артем5.16.2013 04:05
    Игорь, вышли мне, пожалуйста, код css календаря.
    Сергей12.23.2013 02:12
    Игорь, если еще актуально , вышлите пож. на мыло guschin_s82@mail.ru
Serg9.2.2011 05:09
Здорово. Игорь- прикольно получилось)
александра1.17.2012 10:01
Доброго времени суток. очень хорош календарь, а не подскажите как в нем сделать ссылку на дате?
    dzantiev1.17.2012 10:01
    ну добовлять ссылку при выводе вот здесь:
    if($j == 0)     // если воскресенье то омечаем выходной
            $calendar_body .= '<td class="holiday"><a href="/* тут url */">'.$day.'</a></td>';
    else{   // в противном случае просто выводим день в ячейке
            if ((date(j)==$day)&&(date(m)==$month)&&(date(Y)==$year)){//проверяем на текущий день
                    $calendar_body .= '<td class="today"><a href="/* тут url */">'.$day.'</a></td>';
            }
            else{
                    $calendar_body .= '<td class="day"><a href="/* тут url */">'.$day.'</a></td>';
               }
    }
    
    ну и наверное пригодятся переменные $year , $month , $day в них храниться полная дата текущего дня
      shabda10.21.2012 01:10
      А как сделать ссылку на определённое число, скажем, 15? Не подскажете?
      Тарас8.4.2013 08:08
      Не знаю актуально ли, но может кому згодится: { if($j == 0) // если воскресенье то омечаем выходной $calendar_body .= ''.$day.''; else { // в противном случае просто выводим день в ячейке if ((date(j)==$day)&&(date(m)==$month)&&(date(Y)==$year)){//проверяем на текущий день $calendar_body .= ''.$day.''; } else{ $calendar_body .= ''.$day.''; } } $day++; // увеличиваем $day }
      Тарас8.4.2013 08:08
      $calendar_body .= ''.$day.'';
Сергей2.16.2012 01:02
а почему понедельник красный? а не воскресенье?
Азиз3.21.2012 10:03
Спасибо большое... Долго пытался понять, как реализовать календарь, в котором бы выводился набор дат исходя из текущей и в, котором можно было бы отмечались даты, на которые была заключена бронь.. Ваш пример натолкнул меня на решения поставленной задачи.. Так что у меня все вышло)) Еще раз спасибо
    Алексей7.5.2012 06:07
    Здравствуйте, скажите как вы реализовали бронь. Спасибо meverikxp@gmail.com
    Шурик6.11.2013 08:06
    Доброго времени суток, всем, Особенно Азизу и Александру, ребят, не могли бы вы мне объяснить как делать бронь??? Я голову ломаю над этим делом уже неделю и всё никак не знаю как их обозначить! RAHAAON-thetiger@hotmail.com А за скрип, автору, огромное спасибо и удачи в будущих начинаниях! Замечательно спрогил!
Александр6.14.2012 07:06
Азиз, не подскажите как вы реализовали бронь в календаре? union-busines@mail.ru
    Шурик6.11.2013 08:06
    Доброго времени суток, всем, Особенно Азизу и Александру, ребят, не могли бы вы мне объяснить как делать бронь??? Я голову ломаю над этим делом уже неделю и всё никак не знаю как их обозначить! А за скрип, автору, огромное спасибо и удачи в будущих начинаниях! Замечательно спрогил!
Николай7.4.2012 07:07
Спасибо огромное - все отлично работает, а главное просто и понятно!
Дмитрий8.1.2012 07:08
Подскажите, как можно переделать данный скрипт под такой календарь _http://freeb.com.ua/raspisanie.html Необходимо, чтобы изменялись только дни недели и последние числа (28,29,30,31)в зависимости от месяца. При этом чтоб подсвечивался текущий день. Заранее спасибо.
Богдан1.13.2013 10:01
Спасибо за скрипт. Очень помог мне. Но не подскажите ли, что нужно прописать, чтобы в пустых ячейках дополнительно оторбажались последние дни предыдущего месяца и первые дни следующего? И как скрыть последнуюю строку, если месяц занимает не 6, а 5 недель, или даже 4? mail@botikho.ru
тест1.23.2013 09:01
Notice: Use of undefined constant j - assumed 'j' in /home/user/htdocs/abon/dogovor/kalendar.php on line 69 Notice: Use of undefined constant j - assumed 'j' in /home/user/htdocs/abon/dogovor/kalendar.php on line 69
Andrik3.3.2013 04:03
дякую. пригодился. переделал под рус. по комментам - работает.
Александр3.22.2013 12:03
А почему вместо этого: $month = date("m", mktime(0,0,0,date('m'),1,date('Y'))); $year = date("Y", mktime(0,0,0,date('m'),1,date('Y'))); не написать короче, вот так: $month = date("m"); $year = date("Y"); Я не учу и не подсказываю, так как я сам начинающий, но мне интересно зачем писать второй параметр в "date", если мы выводим текущую дату?
Пётр3.31.2013 08:03
Игорь, вышлите мне пожалуйста, CSS на почту werd_34@rambler.ru
Шурик6.12.2013 07:06
Доброго времени суток, всем, Особенно Азизу и Александру, ребят, не могли бы вы мне объяснить как делать бронь??? Я голову ломаю над этим делом уже неделю и всё никак не знаю как их обозначить! А за скрип, автору, огромное спасибо и удачи в будущих начинаниях! Замечательно спрогил!
Артём10.8.2013 05:10
А как сделать что бы можно было кликать на даты, т.е. кликнул и отобразилось то что в ней, короче что бы все даты были ссылками, описывать каждую дату бред, может у кого то есть такой пример?
mish-ka-mishka12.11.2013 11:12
А какой здесь часовой пояс? Просто у меня в 3:13 в Москве 12.12.13 до сих пор 11.12.13 отмечается как сегодняшнее число :(
ОСТАВИТЬ КОММЕНТАРИЙ