Tuesday, March 23, 2010

Agenda mensual con calendario en PHP (I)

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;
    }

}

No comments:

Post a Comment