Publi

Extraer fechas de inicio y fin de un evento periódico con PHP


Si estamos trabajando con calendarios y organizando eventos puede que nos encontremos con un evento repetitivo en el tiempo, por ejemplo entre dos fechas determinadas, cada X días tenemos que realizar una tarea determinada. Sólo tenemos una fecha de inicio y de fin, queremos saber en este caso cuántas veces se va a repetir nuestra tarea y en qué fechas serán todos los eventos.

Para poner un ejemplo concreto, entre el 15/12/2012 y el 31/12/2012 tenemos, cada 3 días una reunión… ¿qué días tenemos reunión?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
function getFechas($inicio, $fin, $intervalo)
{
  $_inicio=new DateTime($inicio);
  $_fin = new DateTime($fin);  

  $_intervalo = new DateInterval($intervalo);
  $fechas = new DatePeriod($_inicio, $_intervalo ,$_fin);

  $ret = array();
  foreach ($fechas as $fecha)
    {
      $ret[]=$fecha->format('d/m/Y H:i');
    }

  return $ret;
}

/* Inicio el 15/12/2012 a las 10:00 */
/* Fin el 31/12/2012 a las 10:00 */
print_r(getFechas('2012-12-15 10:00', '2012-12-31 10:00', 'P3D'));
?>

El resultado será:

Array
(
[0] => 15/12/2012 10:00
[1] => 18/12/2012 10:00
[2] => 21/12/2012 10:00
[3] => 24/12/2012 10:00
[4] => 27/12/2012 10:00
[5] => 30/12/2012 10:00
)

Pero nos damos cuenta de que el día 30 de diciembre cae en domingo, y no apetece hacer una reunión en domingo, por lo que modificamos el algoritmo para que la reunión de los domingos la pase al día siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
function getFechas($inicio, $fin, $intervalo, $sundays=false)
{
  $_inicio=new DateTime($inicio);
  $_fin = new DateTime($fin);  

  $_intervalo = new DateInterval($intervalo);
  $fechas = new DatePeriod($_inicio, $_intervalo ,$_fin);

  $ret = array();
  foreach ($fechas as $fecha)
    {
      if (($sundays) && ($fecha->format('w')==0) )
    $fecha->modify('+1 day');

      $ret[]=$fecha->format('d/m/Y H:i');
    }

  return $ret;
}

/* Inicio el 15/12/2012 a las 10:00 */
/* Fin el 31/12/2012 a las 10:00 */
print_r(getFechas('2012-12-15 10:00', '2012-12-31 10:00', 'P3D', true));
?>

El formato de las fechas debe ser Año-mes-día Hora:minuto:segundo, pero si queremos crear un objeto DateTime() con un formato personalizado, por ejemplo (día/mes/año) podemos hacer lo siguiente:

1
$fecha = DateTime::createFromFormat('d/m/Y H:i', '15/12/2012 10:00');

Podemos incorporarlo en el código anterior así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
function getFechas($inicio, $fin, $intervalo, $sundays=false)
{
  $_intervalo = new DateInterval($intervalo);
  $fechas = new DatePeriod($inicio, $_intervalo ,$fin);

  $ret = array();
  foreach ($fechas as $fecha)
    {
      if (($sundays) && ($fecha->format('w')==0) )
    $fecha->modify('+1 day');

      $ret[]=$fecha->format('d/m/Y H:i');
    }

  return $ret;
}

/* Inicio el 15/12/2012 a las 10:00 */
/* Fin el 31/12/2012 a las 10:00 */
$inicio=DateTime::createFromFormat('d/m/Y H:i', '15/12/2012 10:00');
$fin   =DateTime::createFromFormat('d/m/Y H:i', '31/12/2012 10:00');
print_r(getFechas($inicio, $fin, 'P3D', true));
?>

En lo que respecta al intervalo, podemos consultar el manual, básicamente tenemos que poner una P (período) y luego especifiar número de días (D), como en el ejemplo P3D, meses con M, años con Y y si entramos en tiempo (horas, minutos y segundos), debemos poner una T (tiempo), horas (H), minutos (M) y segundos (S). Por ejemplo, 1 mes, 5 días, 20 horas, 5 minutos y 2 segundos sería “P1M5DT20H5M2S”

Aunque podemos crear un DateInterval de una forma un poco más intuitiva, podemos por ejemplo, si queremos hacer una reunión todos los meses, el primer viernes, podemos decir:

1
  $_intervalo = DateInterval::createFromDateString("first friday of +1 month");

Eventos con duración

Pero imaginémonos que el evento tiene fecha de inicio y de fin, por ejemplo cada 2 meses, tenemos una competición deportiva que dura 3 días. Empezamos a contar el 12/12/2012 y terminaremos el 13/12/2013 ¿Qué días tendremos competición deportiva?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
function getFechas($inicio, $fin, $intervalo, $duracion)
{
  $_intervalo = new DateInterval($intervalo);
  $fechas = new DatePeriod($inicio, $_intervalo ,$fin);

  $ret = array();
  foreach ($fechas as $fecha)
    {
      $inicioEvento = $fecha;
      $finEvento= clone $fecha;
      $finEvento->modify($duracion);
     
      if ($finEvento<=$fin)
    $ret[]=array('Inicio' => $inicioEvento->format('d/m/Y H:i'),
             'Fin' => $finEvento->format('d/m/Y H:i'));
    }

  return $ret;
}

/* Inicio el 15/12/2012 a las 10:00 */
/* Fin el 31/12/2012 a las 10:00 */
$inicio=DateTime::createFromFormat('d/m/Y', '12/12/2012');
$fin   =DateTime::createFromFormat('d/m/Y', '13/12/2013');
print_r(getFechas($inicio, $fin, 'P2M', '+3 day'));
?>

Cuyo resultado es:

Array
(
[0] => Array
(
[Inicio] => 12/12/2012 22:07
[Fin] => 15/12/2012 22:07
)

[1] => Array
(
[Inicio] => 12/02/2013 22:07
[Fin] => 15/02/2013 22:07
)

[2] => Array
(
[Inicio] => 12/04/2013 22:07
[Fin] => 15/04/2013 22:07
)

[3] => Array
(
[Inicio] => 12/06/2013 22:07
[Fin] => 15/06/2013 22:07
)

[4] => Array
(
[Inicio] => 12/08/2013 22:07
[Fin] => 15/08/2013 22:07
)

[5] => Array
(
[Inicio] => 12/10/2013 22:07
[Fin] => 15/10/2013 22:07
)

)

Foto: Phillie Casablanca (Flickr) CC-by a 11/11/2012

También podría interesarte...

Only 1 comment left Ir a comentario

  1. Pingback: Bitacoras.com /

Leave a Reply