Ver Mensaje Individual
  #11 (permalink)  
Antiguo 17/07/2003, 16:57
leonardop
 
Fecha de Ingreso: julio-2003
Mensajes: 165
Antigüedad: 20 años, 9 meses
Puntos: 1
Hola Pablo,

Me alegra que tu aplicación ya está tomando forma y te sientas cómodo discutiendo los problemas que van apareciendo en el camino. El aprendizaje siempre es muy bonito y más cuando se trata de cosas tan interesantes como la programación... :)

Bueno, en tu caso se me ocurre una solución del siguiente tipo:

Código:
<?php

// Retomemos los valores de los que parte el programa. Las fechas de
// entrada y salida.

$fecha_entrada_dia  = 5;
$fecha_entrada_mes  = 3;
$fecha_entrada_anyo = 2003;

$fecha_salida_dia  = 28;
$fecha_salida_mes  = 3;
$fecha_salida_anyo = 2003;


// Antes de continuar, tomemos la precaucion de "traducir" de una vez
// las fechas a un formato mas comodo.

$fecha_entrada_unix = mktime (0, 0, 0,
                              $fecha_entrada_mes, $fecha_entrada_dia,
                              $fecha_entrada_anyo);

$fecha_salida_unix = mktime (0, 0, 0,
                             $fecha_salida_mes, $fecha_salida_dia,
                             $fecha_salida_anyo);


// Ahora, concentremonos en las tarifas. Para efectos de simplicidad,
// vamos a usar un arreglo, aunque no sea una solucion muy
// flexible. Si se usara este tipo de solucion en una aplicacion real,
// habria que modificar directamente el codigo fuente cada vez que las
// tarifas cambiaran, lo cual no parece muy buena idea. Sin embargo,
// hacer las modificaciones necesarias para adaptar la carga de datos
// desde una fuente externa (como una base de datos relacional) no
// debe resultar dificil.

// A continuacion se presenta un arreglo que contiene la informacion
// de las tarifas, que a su vez se almacenan en arreglos
// asociativos. La informacion que nos importa tener es basicamente:
// valor de la tarifa, fecha en la que empieza a regir, y fecha en la
// que finaliza. Es importante notar que, internamente, vamos a usar
// el valor -1 como indicador de que para un periodo determinado no
// hay disponibilidad de servicio.

// Tambien, por comodidad, hemos asumido que los valores de las
// tarifas son _diarios_. Es decir, una tarifa de $750 por semana, por
// ejemplo, tendria un valor de mas o menos $107 por dia.

$tarifas = array (array ('valor'      => 107,
                         'inicio_dia' => 1,
                         'inicio_mes' => 1,
                         'fin_dia'    => 20,
                         'fin_mes'    => 3),

                  array ('valor'      => 114,
                         'inicio_dia' => 21,
                         'inicio_mes' => 3,
                         'fin_dia'    => 3,
                         'fin_mes'    => 6),

                  array ('valor'      => -1,
                         'inicio_dia' => 4,
                         'inicio_mes' => 6,
                         'fin_dia'    => 10,
                         'fin_mes'    => 6));

// Los valores anteriores, por ejemplo, definen que existen dos
// tarifas; una que se aplica del 1 de Enero al 20 de Marzo y es de
// $107 diarios, otra que se aplica del 21 de Marzo al 3 de Junio y es
// de $114 diarios, y además se define que del 4 de Junio al 10 de
// Junio no hay disponibilidad de servicio.


$num_tarifas = count ($tarifas);  // Es mejor calcular solo una vez el
                                  // numero de tarifas que existe.


// A continuacion, y solo "por si las moscas", vamos a definir una
// variable que sera utilizada como el valor por defecto de la tarifa
// en aquellos dias que no hacen parte de ninguno de los intervalos
// definidos en $tarifas.

$tarifa_por_defecto = 100;


// Ahora si, vamos a calcular la tarifa total. El ciclo que se
// presenta a continuacion podria recibir ciertos retoques con fines
// de optimizacion, pero su apariencia actual se debe a que por ahora
// preferimos la legibilidad y la simpleza a la eficacia.

$tarifa_total = 0;  // La tarifa inicia en ceros.


// La comparacion aqui es un "menor o igual" ya que se desea contar el
// periodo entre fecha de entrada y fecha de salida con estos dias
// inclusive. Recuerde tambien que 86400 es aproximadamente la
// cantidad de segundos que hay en un dia.

for ($dia = $fecha_entrada_unix; $dia <= $fecha_salida_unix; $dia += 86400) {

    // Busquemos una tarifa que se aplique en el dia que estamos analizando

    // Inicialmente, no se ha encontrado ninguna tarifa
    // aplicable. (Resulta un poco obvio, dado que no hemos analizado
    // ninguna todavia).

    $tarifa_encontrada = false; 

    for ($i = 0; $i < $num_tarifas; $i++) {

        // Usamos los anyos de las fechas de entrada y salida para las
        // tarifas tambien.

        $tarifa_inicio_unix = mktime (0, 0, 0,
                                      $tarifas[$i]['inicio_mes'],
                                      $tarifas[$i]['inicio_dia'],
                                      $fecha_entrada_anyo);

        $tarifa_fin_unix = mktime (0, 0, 0,
                                   $tarifas[$i]['fin_mes'],
                                   $tarifas[$i]['fin_dia'],
                                   $fecha_salida_anyo);

        if ($dia >= $tarifa_inicio_unix and $dia <= $tarifa_fin_unix) {

            // Se ha encontrado una tarifa aplicable. La vida es
            // bella.
            $tarifa_encontrada = true;

            if ($tarifas[$i]['valor'] == -1)
                print "<strong>Atencion:</strong> no hay disponibilidad " .
                    "de servicio para la fecha " . date ('j-n-Y', $dia) .
                    "<br />\n";

            else
                $tarifa_total += $tarifas[$i]['valor'];


            break;
        }
    }


    // Si no hubo una tarifa aplicable, no temais! La tarifa por
    // defecto viene al rescate.

    if (! $tarifa_encontrada)
        $tarifa_total += $tarifa_por_defecto;
}


// Finalmente, la respuesta que todos esperabamos.

print "La tarifa total es \$$tarifa_total\n";


// Eso fue todo. Este ejemplo muestra un mensaje de advertencia por
// cada dia que hace parte del periodo a estudiar y para el que no hay
// disponibilidad de servicio. Puede que no sea buena idea contar con
// ese comportamiento, pero por otra parte, puede que el usuario lo
// piense dos veces antes de volver a seleccionar periodos de tiempo
// en los que no hay servicio... :)

?>
Espero que los comentarios que he puesto te faciliten la digestión de este ejemplo. Sin embargo, ten en mente que casi siempre es más importante la habilidad de entender los algoritmos y sentencias de un programa leyendo el código mismo, en lugar de sus comentarios.

Saludos.