:::: MENÚ ::::

[PHP] Crear un calendario

Actualizado el 15 de Octubre de 2012

Actualmente encuentras en internet calendarios de todo tipo con una simple búsqueda y algunos de ellos programados bastante mal, por ello he preferido crearlo por mi cuenta, así practico y descubro como se hacen.

Para este calendario no voy a usar nada que tenga que ver con JavaScript ni Ajax, será puramente PHP y HTML5, un calendario sencillo.

Lo primero que necesitamos saber es cuántos días tiene el mes que pueden ser 30, 31, 28 ó 29, para ello usamos date('t') que nos devolverá el número de días del mes actual.

<?php echo date('t'); ?>

Esto nos devolverá el número de días del mes, en mi caso 29, ya que es febrero de 2012 y el año es bisiesto.

Para poder crear la “tabla” para el calendario voy a usar un Array bidimensional, ya que dentro de ella existirá una tabla “imaginaria” separada por X (filas/semanas) e Y (columnas/día de la semana) y será más fácil después mostrarlo por HTML5.

Ahora vamos a sacar todos los días del mes a un Array, para ello usaré un for y en cada “casilla” (llave) vamos añadiendo un número correlativo (1, 2, 3, …), y pararemos cuando lleguemos al último día del mes, para ese límite usaremos el anterior date('t').

<?php 

	for($i=1;$i<=date('t');$i++) {

		$calendar[] = $i;

	}

?>

Ya tenemos todos los días del mes dentro de nuestra Array $calendar pero, ¿cómo sabemos que día de la semana va a caer? para poder saber si el día 29 (por ejemplo) es Miércoles, usaremos date('N') que nos devolverá desde el “1” (Lunes) hasta el “7” (Domingo), y lo usaremos como key para nuestro $calendar.

La mejor forma es consultarlo dentro del for anterior que día de la semana es. Volveremos a usar date() de nuevo para especificar el año, el mes y el día ($i) exacto que queremos saber, pasándolo como segundo valor al date() escrito anteriormente, pero deberemos pasarlo a fecha unix, lo haremos gracias a strtotime().

<?php

	for($i=1;$i<=date('t');$i++) {

		$day_week = date('N', strtotime(date('Y-m').'-'.$i));

		$calendar[$day_week] = $i;

	}

?>

Con date('Y-m').'-'.$i) le decimos el año (Y), el mes (m) y el día $i, en formato Inglés (yyyy/mm/d).

Pasamos a obtener el número de las semanas (semana 1, semana 2, etc.), simplemente cada vez que sea un 7 (Domingo), sabemos que al día siguiente comienza una nueva semana. Para ello usaremos un if dentro del propio for para comprobar si ese día es Domingo (7), si es así, incrementamos una semana, pasando de la semana 1 a la semana 2.

Es importante decirle al calendario que la primera semana empieza con el número “1”, así que crearemos una variable para almacenar ese dato fuera del for para que no se vea involucrado en la iteración y se reinicie de nuevo a “1”.

<?php 

	$week = 1;

	for($i=1;$i<=date('t');$i++) {

		$day_week = date('N', strtotime(date('Y-m').'-'.$i));

		$calendar[$week][$day_week] = $i;

		if ($day_week == 7) { $week++; };

	}

?>

Pues ya está, ya tenemos nuestra Array bidimensional con nuestro calendario perfectamente estructurado dentro de $calendar, ahora sólo nos queda crear la estructura en HTML5.

<?php 

	$week = 1;

	for($i=1;$i<=date('t');$i++) {

		$day_week = date('N', strtotime(date('Y-m').'-'.$i));

		$calendar[$week][$day_week] = $i;

		if ($day_week == 7) { $week++; };

	}
 
?>

<!DOCTYPE html>
<html>

	<head>
	</head>
 
	<body>

		<table border="1">

			<thead>

				<tr>

					<td>Lunes</td>
					<td>Martes</td>   
					<td>Miércoles</td>   
					<td>Jueves</td>   
					<td>Viernes</td>   
					<td>Sábado</td>   
					<td>Domingo</td>   

				</tr>

			</thead>

			<tbody>

			</tbody>

		</table> 

	</body>

</html>

Ahora, sacaremos nuestra tabla de $calendar y la montaremos en <tbody>. Primero empezaremos por las semanas, usaremos un foreach para que vaya automáticamente recoriendo el Array y vaya añadido filas a la tabla.

<?php 

	$week = 1;

	for($i=1;$i<=date('t');$i++) {

		$day_week = date('N', strtotime(date('Y-m').'-'.$i));

		$calendar[$week][$day_week] = $i;

		if ($day_week == 7) { $week++; };

	}
 
?>

<!DOCTYPE html>
<html>

	<head>
	</head>
 
	<body>

		<table border="1">

			<thead>

				<tr>

					<td>Lunes</td>
					<td>Martes</td>   
					<td>Miércoles</td>   
					<td>Jueves</td>   
					<td>Viernes</td>   
					<td>Sábado</td>   
					<td>Domingo</td>   

				</tr>

			</thead>

			<tbody>

				<?php foreach ($calendar as $days) : ?>

					<tr>

					</tr>

				<?php endforeach ?>

			</tbody>

		</table>

	</body>

</html>

Sólo nos queda añadir los días dentro de cada semana, para ello usaremos for para ir recorriendo uno a uno los días de las semana y un if, para saber si ese día exactamente entra dentro de éste mes o hay que dajar la casilla en blanco.

<?php 

	$week = 1;

	for($i=1;$i<=date('t');$i++) {

		$day_week = date('N', strtotime(date('Y-m').'-'.$i));

		$calendar[$week][$day_week] = $i;

		if ($day_week == 7) { $week++; };

	}
 
?>

<!DOCTYPE html>
<html>

	<head>
	</head>
 
	<body>

		<table border="1">

		<thead>

			<tr>

				<td>Lunes</td>
				<td>Martes</td>   
				<td>Miércoles</td>   
				<td>Jueves</td>   
				<td>Viernes</td>   
				<td>Sábado</td>   
				<td>Domingo</td>   

			</tr>

		</thead>

		<tbody>

			<?php foreach ($calendar as $days) : ?>

				<tr>

					<?php for ($i=1;$i<=7;$i++) : ?>

						<td>

							<?php echo isset($days[$i]) ? $days[$i] : ''; ?>

						</td>

					<?php endfor; ?>

				</tr>

			<?php endforeach ?>

		</tbody>

		</table> 

	</body>

</html>

Ya está, hemos terminado, tenemos un calendario funcionando y dando la fecha y los días correctamente, sólo nos queda añadir cualquier detalle que desees poner, por ejemplo poder seleccionar otro mes y año, marcar el día de hoy, CSS3, etc.

Para que podáis ver el código completamente y con la posibilidad de seleccionar otro mes y año, dejo el código en mi perfíl de Github.

Calendar PHP/HTML5

Share on Facebook0Tweet about this on TwitterShare on Google+1Share on LinkedIn1Share on Tumblr0Pin on Pinterest0Email this to someone

  • Ariel Talad

    hola, el codigo es excelente y me sirvio de mucho, pero te hago una consulta, como puedo hacer para crear el mismo calendario pero en inglés, donde el primer dia es el domungo, en lugar de lunes?
    muchas gracias

    • Es muy sencillo, tendrás que cambiar un par de valores:

      – Linea 7: Cambiar “N” por “w” (minúscula).
      – Linea 11: el número 7 por 6.
      – Linea 30: Añadimos el domingo: <td>Domingo</td>
      – Linea 37: Eliminamos Domingo
      – Linea 49: Cambiar $i=1 por $i=0, y, $i<=7 por $i<=6.

      Con esos cambios conseguirás que el Domingo se el primer día de la semana.

      • Ariel Talad

        mil gracias por la respuesta
        saludos cordiales

  • Pingback: PHP: Cómo crear un calendario en formato americano | Rubén Martín()

  • Guest

    consulta, si hago tal cual los cambios que me recomendaste, no me muestra nada

    • A lo mejor te ha pasado igual que Ariel Talad y has puesto la uve doble en mayúscula, pero tiene que ser en minúscula.

  • Ariel Talad

    haciendo las modificaciones tal cual me recomendaste, no me mostraba nada, pero encontre la solucion, era simple, en lugar de poner W puse w (minuscula) y resuelto el problema
    muchas gracias

    • Exacto, es con uve doble y en minúscula, ya que en mayúscula tiene otro significado

  • Javier

    Buenas, he intentado implementar el codigo y funciona perfectamente. Pero intentanto mejoralo he intentado resaltar la fecha de hoy pero No lo he conseguido, Podrias darme alguna pista ?. Gracias

    • Puedes usar date() con el valor j y comprobar si el día que se monta en ese momento, es igual al de hoy, a partir de la linea 45.

  • Javier

    Ok Gracias ya esta !

    No se si es muy ortodoxo pero lo he solucionado asi:

    He añadido las siguientes lineas aparti de la linea 70

    $FechaHoy=date(“j”);

    if ($days[ $i ] == $FechaHoy) {
    echo ”.$FechaHoy.”;

    } else {
    echo isset( $days[ $i ] ) ? $days[ $i ] : ”;
    }

    Quizas sea mejor de otra manera No se,……..

    • No hay linea 70, podría ser de la 50 :P

      Recomendarte que cambies la etiqueta <font>, porque se ha eliminado en HTML5. Lo mejor es que uses CSS: <span style=”color: blue”>[…]</span>

      • Javier

        Ok Muchas gracias por el apunte. Saludos

  • Raul Rodas

    Buenos días Rubén, excelente código, una consulta, estoy necesitando asociar el día, mes y año con un archivo específico, este archivo está relacionado con la fecha es decir que cada día tiene un nombre diferente, el usuario al clickear sobre una fecha determinada será enlazado a ese archivo específico, por ejemplo el usuario clickea sobre el día 1 de octubre del 2013, entonces será redireccionado a una direccion http://www.mipagina.com/01-10-2013.txt, y asi sucesivamente si cambia de mes y de año y clickea sobre una fecha de ese periodo seria redireccionado a esa fecha (25 de marzo del 2010), http://www.mipagina.com/25-03-2010.txt, espero tu ayuda. Gracias.

  • Juan

    Buenas, enhorabuena por este tutorial y magnifico blog, me gustaría utilizar este calendario para mostrar los días que está ocupada mi casa de alquiler de vacaciones, no sé como implementarlo, estoy pensando utilizar un array con las fechas.
    Grácias, un saludo.

  • jonathan

    Hola martin, tengo un problema, noto que cuando le mando un parametro en la funcion date con los meses que tiene 30 dias o menos me los muestra siempre como si tuvieran 31, que solucion puedo implementar?

    • ¿A que te refieres exactamente?

      • jonathan

        te comento que cuando intente jalar un mes diferente al actual lo hacia pero siempre con 31 dias todos los meses, la solucion que implemente fue esta:
        $ano=$row_regis[‘ano’];
        $mes=$row_regis[‘mes’];
        $fecha = “$ano-$mes”;
        if($mes==”02″){
        $week = 1;
        for($i=1;$i<=28;$i++) {
        $day_week = date('N', strtotime(date("$fecha").'-'.$i));
        $calendar[$week][$day_week] = $i;
        if ($day_week == 7) { $week++; };
        }
        }elseif($mes=="04"){
        $week = 1;
        for($i=1;$i<=30;$i++) {
        $day_week = date('N', strtotime(date("$fecha").'-'.$i));
        $calendar[$week][$day_week] = $i;
        if ($day_week == 7) { $week++; };
        }
        los parametros los jalo desde mysql

        • He estado haciendo pruebas, cambiando de mes e incluso cambiando la fecha del servidor, y siempre devuelve correctamente el número total de días.

          • jonathan

            podrias decirme como? en mi caso el problema lo tuve con el primer for con date(‘t’) donde devuelve la cantidad de dias del mes dado ya que siempre me devuelve la cantidad de dias del mes actual, tuve que espicificar la cantidad de dias segun el mes si tenia 30 o 31 o 28 ya que lo uso para hacer un horario de trabajo del mes siguiente o el anterior.

          • Exacto, el código del post es exclusivamente para el mes actual. Si quieres tener la posibilidad de cambiar de mes, en los archivos de Github tiene un código que sí lo hace. Te permite elegir el mes y el año.

  • gera

    Hola, soy nueva en php y la verdad es que me gustó mucho el código y resulta muy útil, pero estoy realizando una tarea en donde debo poder hacer click en una semana completa del mes (cualquiera) y poder ir a otra página del sitio, e intentado hacer varios cambios, pero nada me resulta… escribía para ver si existe la posibilidad de que me des una ayudita en esto

  • Darius

    Dario: el codigo funciona de maravilla estaba bus can do alto ask con solo php , mi problems es agora Como Hager que casa dia cargue Una variable URL ej: click on el dia 19 y me mande a dia.php?dia=19

  • Darius

    Perdon por los errores es este autocorrector que estaba en ingles
    día.php?día=19 esto es para que pueda escoger una fecha e iingresarla a la base de datos en un formato especifico

  • Juan Pablo Lopez

    solo te falto poner el para que mostrara los acentos xD

  • Efren Carrillo Barreto

    Hola soy nuevo en php, tengo una consulta, seria bueno que existan botones y cambie al siguiente mes o al anterior

    • Justamente si pinchas en el botón de Git “Calendar PHP/HTML5” (final del artículo) podrás encontrar el mismo calendario con la posibilidad de elegir el mes y el año, es lo más cercano que podrás encontrar hecho por mí en el artículo al siguiente y anterior. De todos modos hacerlo no debería llevar mucho tiempo.

      • Erik Ramirez Cardenas

        hola ruben mira es q a mi me pasa lo mismo q a muchos de los q te han escrito alguien activo el modo avion en mi compu y ahora no me deja activar wifi y ya desactive el modo avion por fa si me puedes ayudar te lo agradeceria.

  • Policarpo Nchuchuma Nguema Nfu

    Hola, tengo un proyecto de donde se basa en gestionar los en eventos en los calendarios. Lo que me piden es poder mostrar en una plantilla varios meses al mismo tiempo. Tengo el calendario hecho pero la forma de mostrar distintos meses. Si alguien sabe como hacer esto por favor que me diga.

  • Maylin

    Como estas Ruben? este código esta excelente!….pero tengo una duda sobre una modificación que quiero hacerle, y es que quiero que muestre dos semanas a la vez (actualmente solo muestra una)?
    Gracias

  • Esteban

    Una consulta, como debería hacerlo para que muestre en los espacios en blanco los dias del mes anterior?? esto debido a que debo mostrar en la “tabla” los días comprendidos entre 2 fechas, por ejemplo, 2 de enero de 2014 y 15 de marzo 2014.