Advertisement
  1. Code
  2. PHP

Fechas y hora: la forma OOP

Scroll to top
Read Time: 7 min

Spanish (Español) translation by Juan Pablo Diaz Cuartas (you can also view the original English article)

La extensión PHP Date / Time es un conjunto de clases que le permiten trabajar con casi todas las tareas relacionadas con la fecha y la hora. Ha estado disponible desde el lanzamiento de PHP 5.2 y la extensión introdujo varias clases nuevas, todas las cuales están mapeadas a escenarios de la vida real:

  • Una fecha o una hora se representan mediante un objeto DateTime.
  • Una zona horaria del mundo está representada por un objeto DateTimeZone.
  • Los objetos DateInterval representan un intervalo. Por ejemplo, cuando decimos dos días a partir de ahora, los "dos días" son el intervalo. El objeto DateInterval no se basa en una fecha u hora específica.
  • Los objetos DatePeriod representan un período entre dos fechas.

Ahora no dejes que los dos últimos te denuncien, vamos a ver el uso del mundo real de estos dos en un momento.


Desde  date() hasta DateTime

Cada vez que queremos mostrar una fecha, usamos date (), es simple y funciona. Solo necesita pasar el formato de fecha que necesita. Pero es un verdadero dolor manipular, un buen ejemplo es formatear fechas y horas de acuerdo con una zona horaria personalizada.

DateTime hace más que simplemente devolver una fecha formateada, pero antes de ir más allá, debe iniciar un nuevo objeto DateTime que represente su fecha y hora. Entonces podemos hacer todo tipo de cosas interesantes con él. Se crea una nueva instancia al igual que cualquier otra clase de PHP.

1
$date = new DateTime();

El constructor de DateTime acepta un parámetro de cadena que por defecto es "ahora", la hora y fecha actuales. Para crear un objeto para una fecha específica, debe pasarle la fecha y hora específicas. El formateo del parámetro es autoexplicativo en la mayoría de los casos. A continuación puede encontrar algunos ejemplos diferentes de cómo construir su objeto DateTime:

1
new DateTime('2013, March 24') //DateTime representing 2013, March 24

2
new DateTime('2013-03-24') //DateTime representing 2013, March 24

3
new DateTime('+2 days') //DateTime representing 2 days from now on.

4
new DateTime('tomorrow')

Cuando PHP tiene dificultades para entender el formato, lanzará una excepción. Se puede encontrar una lista completa del formato disponible en la documentación

Si no hay un formato que coincida con sus necesidades, puede especificar su propio formato utilizando DateTime :: createFromFormat

1
DateTime::createFromFormat('j-M-Y', '24-Mar-2013');

Ahora que tenemos un objeto DateTime en la mano, podemos hacer un montón de cosas, con bastante facilidad.

Marca de tiempo de Unix

1
$date->getTimestamp(); //returns a unix timestamp

Modificación de fecha / hora

1
$date->setDate(2013, 12, 30); //yyyy, mm, dd will set the the specified date

2
$date->setTime(12, 3, 20); //hh, mm, ss (optional) will modify the time

3
$date->modify('tomorrow'); //string based manipulation

4
$date->setTimestamp(1364798550); //modify using a unix timestamp

Tenga en cuenta que cuando se establecen valores fuera de rango, PHP modificará la fecha en consecuencia. Por ejemplo, $date-> setDate (2013, 12, 35); generará 2014-01-04, lo mismo vale para el tiempo.


Trabajando con fechas múltiples

Ahora que estás obsesionado con DateTime, lo siguiente que sabes es que tus aplicaciones estarán llenas de objetos DateTime. Comenzarás a amar las fechas y los tiempos como nunca antes. De ahora en adelante, tendrás que lidiar con objetos DateTime, no con "strings" que debes pasar a la función strtotime cuando necesites hacer un poco de matemática.

Digamos, por ejemplo, que necesitas comparar dos cumpleaños:

1
$sheldon = new DateTime('May 20th, 1980');
2
$neo     = new DateTime('March 11th, 1962');
3
4
if ($sheldon > $neo)
5
    echo 'Sheldon is younger than neo';

Otro escenario podría estar comparando dos fechas. Podemos comparar fechas uno contra el otro como así:

1
$diff = $neo->diff($sheldon);

La llamada diff devuelve un objeto DateInterval. Si volcamos el valor de retorno:

1
DateInterval Object
2
(
3
    [y] => 18
4
    [m] => 2
5
    [d] => 9
6
    [h] => 0
7
    [i] => 0
8
    [s] => 0
9
    [invert] => 0
10
    [days] => 6645
11
)

Estas son propiedades públicas. Puede generar algún resultado amigable desde un objeto DateInterval:

1
$diff->format('Neo is older by %Y years and %m months older'); //Neo is older by 18 years and 2 months

Lo mejor del objeto DateInterval es que puede aplicar el intervalo a otro objeto DateTime:

1
$neo->add($diff); //neo's birthday changed to sheldon's

Nota: las modificaciones de DateTime, como agregar, no devuelven nuevos objetos DateTime, sino que afectan al objeto original. Siempre ten esto en cuenta cuando pases objetos DateTime a través de tu aplicación. PHP 5.5 introdujo una nueva clase que devuelve nuevos objetos luego de la modificación.

diff no es el único lugar donde puede generar un objeto DateInterval. Como es una clase, los objetos nuevos se pueden iniciar como de costumbre:

1
$new_diff = new DateInterval('P2Y');

La cantidad de años / meses / días, etc., se transfieren como una cadena al constructor. Se puede encontrar más información en la documentación del constructor.


Trabajando con Timezones

Al crear nuevos objetos DateTime, el segundo argumento del constructor define una zona horaria. Si omitimos esto, se tomará una zona horaria predeterminada de la date.timezone de php.ini. Puede modificar esto en tiempo de ejecución llamando a date_default_timezone_set:

1
date_default_timezone_set('America/New_York');
2
new DateTime('today'); //datetime object is on New York time

También puede cambiar las zonas horarias sobre la marcha. Como habrás adivinado, primero necesitamos un objeto Timezone.

1
$timezone = new DateTimeZone('America/New_York');
2
$sheldon->setTimezone($timezone); //sheldon's birthday now on to New York

Puede definir la zona horaria al crear su nuevo objeto DateTime:

1
$sheldon = new DateTime('May 20th, 1980', $timezone);

Sin embargo, una cosa importante a tener en cuenta es que setTimezone modifica el objeto DateTime original. Lo que básicamente estamos preguntando es, "formatee esta fecha, a esta zona horaria" siempre que llamemos al método setTimezone. Ahora, por otro lado, en el último ejemplo donde pasamos la zona horaria al constructor DateTime, estamos diciendo, "la fecha que estoy creando está en esta zona horaria".

Una lista de zonas horarias válidas está disponible en la documentación en línea.


DatePeriods

Creo que el manual oficial proporciona la mejor explicación:

Un período de fecha permite la iteración sobre un conjunto de fechas y horas, que se repiten a intervalos regulares, durante un período determinado.

DatePeriod nos permite generar un conjunto de DateTimes utilizando dos días que definimos entre un intervalo. Pasamos una fecha de inicio, un intervalo y una fecha de finalización. En cada intervalo, se crea un nuevo objeto DateTime.

Digamos que queremos obtener todas las fechas de nacimiento de Sheldon, desde su nacimiento:

1
//since birthdays occur every year, the interval is one year

2
$interval = new DateInterval('P1Y');
3
4
//third argument is the end date, new DateTime() == right now

5
$period   = new DatePeriod($sheldon, $interval, new DateTime());
6
7
foreach($period as $dt) {
8
    //DateTime objects

9
    echo $dt->format('Y-m-d - D'), "\n";    
10
}

El resultado sería:

1
1981-05-20 - Wed
2
1982-05-20 - Thu
3
1983-05-20 - Fri
4
1984-05-20 - Sun
5
1985-05-20 - Mon
6
1986-05-20 - Tue
7
...

Ahora, de forma predeterminada, DatePeriod incluye la fecha de inicio que pasamos. Sin embargo, el cuarto argumento para el constructor nos permite omitir la fecha de inicio:

1
$period   = new DatePeriod($sheldon, $interval, new DateTime(), DatePeriod::EXCLUDE_START_DATE);

Veamos cuántas fiestas de cumpleaños ha tenido Neo antes de que naciera Sheldon:

1
$bdays   = new DatePeriod($neo, $interval, $sheldon, DatePeriod::EXCLUDE_START_DATE);
2
echo iterator_count($bdays);

Extensión

Todas las clases que hemos cubierto hoy pueden ampliarse para usar con sus propios métodos. Un uso popular es extender DateTime con un método __toString para que pueda imprimir correctamente un objeto DateTime sin tener que llamar al formato.


Un par de escenarios de uso

  • Uno de mis enfoques personales para usar objetos DateTime es cuando trato con columnas de fecha / hora en bases de datos. Todas las fechas se almacenan como fechas de zona horaria UTC. El código de la aplicación solo funciona con los objetos DateTime, pero antes de que se genere la consulta final, todas las fechas tienen el formato UTC. Este enfoque me ha permitido trabajar con múltiples entradas de zona horaria fácilmente.

    Puedo pasar un objeto de hora de Nueva York y olvidarme por completo de formatearlo, antes de ir a la base de datos. Puedo cambiar fácilmente entre las marcas de tiempo de Unix y el formato de fecha y hora en mi base de datos en cualquier momento, a mi código de aplicación no le importa siempre que reciba un objeto DateTime.

  • También utilicé DateInterval para simplificar la lógica de pago de la suscripción. Usar los objetos de DateInterval para definir el tiempo entre la suscripción ha hecho las cosas realmente fáciles. Solo necesito aplicar el intervalo a la última fecha de pago.

¿Tiene algún buen ejemplo de uso de fecha / hora? Compártelos en los comentarios.


Envolver

La extensión de la fecha y hora tiene mucho que ofrecer, si está en la vanguardia, hay nuevas clases e interfaces introducidas desde PHP 5.5. Asegúrese de revisar el manual. Gracias por leer.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.