Hace poco hice un calendario en PHP para prácticar.
Estas son algunas de las clases que creé:
Esta es una clase con métodos estáticos que sirven para hacer diferentes cálculos con fechas.
/* Clase Fechas */
class Fechas
{
/* Obtiene el día de la semana a partir del año, del mes y del día */
public static function getDiaSemana($anyo, $mes, $dia)
{
/*Módulos acumulados del número de días antes del inicio de mes para años normales y bisisestos*/
$modMeses = array(0,3,3,6,1,4,6,2,5,0,3,5);
$modMesesBis = array(0,3,4,0,2,5,0,3,6,1,4,6);
/*Se comprueba si el año es bisiesto para saber cual de los dos vectores anteriores usar*/
if( 1 == Fechas::esBisiesto($anyo))
{
$dMes = $modMesesBis[$mes-1];
}
else
{
$dMes = $modMeses[$mes-1];
}
/*Se calcula el día de la semana correspondiente a la fecha*/
$divEntera1 = (int) ( ($anyo - 1.0) / 4.0 );
$divEntera2 = (int) ( ($anyo - 1.0) / 100.0 );
$divEntera3 = (int) ( ($divEntera2 + 1.0) / 4.0 );
$divEntera4 =(int) ( $divEntera1 - 3 * $divEntera3 );
/*Fórmula del día de la semana*/
$diaSemana = ( (($anyo - 1) % 7) + ($divEntera4 % 7) + $dMes + ($dia % 7) ) % 7;
/*El 0 corresponde al Domingo*/
if( 0 == $diaSemana)
{
$diaSemana = 7;
}
return $diaSemana;
}
/* Calcula la semana del año a partir del día, el mes y el año */
public static function getSemanaAnyo($anyo, $mes, $dia)
{
//Valores de los días acumulados antes del principio de cada mes
$ordinalesNormal=array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
$ordinalesBisiesto=array(0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335);
//Según el año sea bisiesto o no se usan unos valores u otros
if( 1 == Fechas::esBisiesto($anyo))
{
$ordinal= $ordinalesBisiesto[$mes - 1];
}
{
$ordinal= $ordinalesNormal[$mes - 1];
}
//Se calcula el día ordinal
$ordinal = $ordinal + $dia;
//Se obtiene el número del día de la semana correspondiente a la fecha (L=1,...,D=7)
$diaSemana = Fechas::getDiaSemana($anyo,$mes,$dia);
//Se calcula la semana del año
$semanaAnyo=(int) (( $ordinal - $diaSemana + 10)/7);
//Si es cero quiere decir que es la última semana del año anterior
if($semanaAnyo == 0)
{
$semanaAnyo = 53;
}
//Si es 53 es la última semana del año anterior
else if($semanaAnyo == 53)
{
if( ( Fechas::getDiaSemana($anyo, $mes, 31) - 1 ) <= 2)
{
$semanaAnyo = 1;
}
}
return $semanaAnyo;
}
/* Comprueba si un año es bisiesto */
public static function esBisiesto($anyo)
{
$a = (0 == $anyo%4); /*Año divisible por 4*/
$b = (0 == $anyo%100); /*Año divisible por 100*/
$c = (0 == $anyo%400);/*Año divisible por 400*/
/*Un año es bisiesto si es divisible por 4 y por 400
o si es divisible por 4 pero no por 100 */
$loEs = $a && ($c || !$b);
return $loEs;
}
/* Devuelve el día en que acaba un mes */
public static function getFinMes($anyo,$mes)
{
/*Número de días de cada mes*/
$diasMeses=array(31,28,31,30,31,30,31,31,30,31,30,31);
$diasMesesBis=array(31,29,31,30,31,30,31,31,30,31,30,31);
/*Según el año sea bisiesto o no, se usan unos valores u otros*/
if( 1 == Fechas::esBisiesto($anyo) )
{
$finMes = $diasMesesBis[$mes-1];
}
else
{
$finMes = $diasMeses[$mes-1];
}
return $finMes;
}
}