Trabajando con DateTime en PHP 5.3

Trabajando con DateTime en PHP 5.3

Aunque no escribo mucho sobre programación esta vez tocó.

Estoy trabajando actualmente con un proyecto personal, donde me ha tocado preparar sistema de fechas para reservas.

Si bien nunca me gustó como PHP trabaja las fechas; “que si unix time stamp, que si str, que si ingles que la mar en coche”.
Me pregunté si tanto hablar de OOP en PHP no tendrá una clase “digna” de trabajo con fechas…

Y casi la tienen, creo que aun la pueden mejorar, pulir y hacerla más completa, pero al menos con lo que hay, se puede trabajar con un estándar más o menos preciso.

Las primeras críticas que me llovieron fueron las cantidades de NEW pero si quiero que los datos se interrelaciones bien, sin problemas, debo usar la base de ejemplos que esta online (php.net).

A mi ver me parce totalmente valido, donde un lenguaje una simple $variable puede ser un array o un fichero o una clase, no creo que por los news sea preocupante.

Lo bueno de todo esto es que al final para mi, lo han simplificado mucho el modo de trabajar, de poder recorrer las fechas con un simple bucle, aunque para ello hay que definir cosas previas.

Lo que use:

Clase DateTime (http://php.net/manual/es/class.datetime.php)
Clase DateInterval (http://www.php.net/manual/es/class.dateinterval.php)
Clase DatePeriod (http://www.php.net/manual/es/class.dateperiod.php)

Una aclaración el código que muestro es a ejemplo para aprender a utilizarlo no es el más pulido ni optimizado, lo que intento es que puedas amigarte con estas hermosas clases y su potenciales.

Es más me fui encontrando cosas que a mi entender no son lo mejor, pero bueno andan. ( :-/ )

Dejare un txt con el código para que lo puedan descargar.

Defino que trabajo en castellano y otras cosas:

setlocale(LC_ALL,”es_ES@euro”,”es_ES”,”esp”);

Lo primero crear una fecha

$init = new DateTime(“2013-09-17 00:00”); // Fecha de inicio
$end = new DateTime(“2014-09-30 23:59”); // Fecha Final (Atención a este detalle 23:59)

Bien, comienza lo lindo, los intervalos, que son? Pues es un modo de recorrer la fecha por el periodo definido en mi caso el primero es el de un mes

$interval = new DateInterval(‘P1M’); // Intervalo de un mes para el bucle

Y ahora otro new, que seria el periodo, esto hace falta para el foreach, por asi decirlo 😉

$daterange = new DatePeriod($init, $interval ,$end); //Bien esto creara algo que recorrer, pueden ver que las fechas son Fecha inicio – Intervalo de tiempo por el cual saltar – Fecha tope.

Y ahora el foreach

foreach($daterange as $date) { // Iré mes a mes

Dentro del foreach quiero recorrer cada mes con sus correspondientes días. Acá es donde me encontré un problema básico, quería saber según el día que tengo, cual es su último día, en el caso de septiembre es el 30, pensé con mi ilusión que existía algo, pero es en pecl así simplifique lo que pude.

$str_mes = “1-“.$date->format(“m-Y”); // Y nos pasamos a los string =( Como $date es el mes actual, pues de aqui consigo el primero de mes.

Creo una nueva fecha

$fin_mes = new Datetime($str_mes); // En este caso seria 1-09-2013

Y mi truco para obtener el fin de mes!!!

$fin_mes ->add(new DateInterval(‘P1M’)); // A la fecha le agrego un mes! (P1M)
$fin_mes ->sub(new DateInterval(‘P1D’)); // A la fecha le resto un dia!

Y wala! tengo el 30-09-2013, pero me encontré una sorpresa con el bucle, al amigo le gustan los datos totales para recorrerlo, parece ser que si no tienes las 23 horas, mas los 59 minutos y sus 59 segundos el día no es 30!
Ser o no ser, pues tranquilos, se lo agregamos!

Al principio pensé que pasaría un día mas por el tiempo, pero no, no se suma!

$fin_mes ->add(new DateInterval(‘PT23H59M59S’)); // Arreglo para que cuente el 30/31 (raro no?)

Ahora ya tengo mi fecha lista! A recorrerla según vamos necesitando.

Creo mi nuevo intervalo de un día P1D

$intervalo_dias = new DateInterval(‘P1D’);

Bueno, necesito controlar los meses:

$control_mes = $date->format(“m-Y”); // Mes actual mas año! para poder recorrer
$control_init_mes = $init->format(“m-Y”); // Mes de inicio del bucle
$control_end_mes = $end->format(“m-Y”); // Mes de final de bucle

Imprimo nombre del mes:

echo “<br/>”.strftime(“%B”, strtotime($date->format(“y-m-d”))).”<br /><br />”;

Bueno mi control de movimiento para el futuro bucle que recorrerá el mes

Algo que pongo en este caso y es muy útil, lo pongo a modo debug, pero para calcular cosas es lo más importante.
Calcular la diferencia entre dos fechas, $date ->diff($fin_mes); (http://php.net/manual/en/datetime.diff.php)
Defino 3 segmentos para hacer el bucle, fecha inicial, entre inicio y final, fecha final.
Esto lo hago porque no siempre empezaremos desde el día 1 y terminaremos el día 30/31

// Fecha inicial hasta fin de ese mes
if($control_init_mes == $control_mes) {
$dias_final_mes = $date ->diff($fin_mes); // Diferencia entre día de venta inicial y final de mes
echo “Días hasta el final del mes: “.$dias_final_mes->format(‘%r%a’).”<br /><br />”; // Simple debug
$dias_venta = new DatePeriod($init, $intervalo_dias,$fin_mes); //rango dentro del mes
}
//Fecha final, debo obtener el 1 de mes
else if($control_end_mes == $control_mes) {
// Genero fecha 1 de mes
$str_mes_fin = “1-“.$date->format(“m-Y”); // mas texto!
$dia_pri_fin_promo = new Datetime($str_mes_fin); // Fecha al día 1 de el ultimo mes
$dias_hasta_mes = $dia_pri_fin_promo ->diff($end); // Diferencia entre ultimo día de $end y el primero de ese mes
echo “Días hasta final de la promo: “.$dias_hasta_mes->format(‘%r%a’).”<br /><br />”; // Otro simple debug
$dias_venta = new DatePeriod($dia_pri_fin_promo, $intervalo_dias,$end); //Rango dentro del ultimo mes
} else {
// Meses que hay entre INICIO y FIN
$str_inicio_mes = “1-“.$date->format(“m-Y”);
$dia_inicio_mes = new Datetime($str_inicio_mes);
$dias_venta = new DatePeriod($dia_inicio_mes, $intervalo_dias,$fin_mes); //rango dentro del mes
}

// Muestro en pantalla la salida
foreach($dias_venta as $dias){
echo $dias->format(“d-m-Y”).”<br/>”;
}

}

?>
</pre>
</body>

Bien con esto no pretendo más que dar simples ideas y nociones de uso de esta excelente clase y sus clases amigas!

Un detalle interesante que me encontré a la hora de estar haciendo pruebas!
Usando diff y la salida con signo – para saber si era un valor negativo me encontré con que el valor 0 y -0 son cosas distintas,
Me quede flipando con lo cuántico de esto jijijiij

2013-09-13 00:00 diff 2013-09-13 18:19 => 0
2013-09-14 00:00 diff 2013-09-13 18:19 => -0
next -1 ….

Descargar txt del ejemplo: http://poisonclub.g1.re/ejemplo-date-time-php.txt
Saludos!

Un pensamiento en “Trabajando con DateTime en PHP 5.3

  1. Jose Nieves

    Estuve revisando tu articulo Trabajando con DateTime en PHP 5.3, y queiria saber si me puedes ayudar en lo siguiente:
    tengo una fecha inicial 16/08/2013 y una fecha final 25/12/2013, necesito desglosar mes a mes y conocer los dias de cada mes, para calcular interes de saldo, ilustro:
    fecha 1 fecha 2 dias Int saldo Interes mes
    16/08/2013 – 31/08/2013 – 15 dias – 12% – 10000 – 50
    01/09/2013 – 30/09/2013 – 30 dias – 12% – 10000 – 100
    01/10/2013 – 31/10/2013 – 31 dias – 12% – 10000 – 100
    01/11/2013 – 30/11/2013 – 30 dias – 12% – 10000 – 100
    01/12/2013 – 25/12/2013 – 25 dias – 12% – 10000 – 83.33

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *