Banner Carbon 2.0

Desde Laravel 5.8 tenemos incluido la nueva versión de Carbon 2.0 la cual trae novedades para la manipulación de fechas en nuestros proyectos. En este artículo vamos a conocer las características más importantes que nos trae Carbon desde su versión 2.0 y además aprenderás cómo migrar de la versión 1.x a la 2.x.

Carbon 2 es oficialmente compatible con Laravel desde la versión 5.8 y en Laravel 6 es la única versión soportada. Entonces si tienes algún proyecto hecho en 5.7 o 5.6 y quieres actualizar de la versión 1 a la 2 sigue los siguientes pasos:

Actualización de Carbon en Laravel 5.7 o versión menor

1. Vamos a establecer explícitamente la versión de Carbon y un adaptador en nuestro composer.json:

{
    "require": {
        "nesbot/carbon": "2.20.0 as 1.34.0"
        "kylekatarnls/laravel-carbon-2": "^1.0.0"
    }
}

En este código usamos el alias 1.34.0 el cual es compatible con Laravel 5.7, el 1.25.0 es el compatible con la versión 5.6.  Laravel tiene su propio rango de compatibilidad con Carbon, nosotros tomamos la versión 2.20.0 como la versión real utilizada y luego elegimos un alias entre las versiones que admite Laravel.

Para estar seguros de que un alias sea compatible con todas sus dependencias actuales, podemos elegir la versión de Carbon que tiene instalada antes de actualizar a Carbon 2 usando el comando:

composer show nesbot/carbon

Finalmente después de aplicar los cambios actualizamos el proyecto con:

composer update

Nuevas Características

750 nuevas configuraciones para localización

Con Carbon 2 la localización ha cambiado mucho con respecto a la versión anterior, pues tiene un soporte  mucho más completo con la incorporación de 750 nuevas configuraciones regionales, además de incluir formatos para nombres de días, nombres de meses, sufijos ordinales, meridiem, inicio de semana y entre otras características.

Para aplicar una localización específica a una instancia de Carbon:

<?php

$date = Carbon\Carbon::create(2019, 7, 16, 0, 0, 0)->locale('es');

$date->monthName; // "julio"

$date->isoFormat('LLLL'); // "martes, 16 de julio de 2019 0:00"

El método locale solo se aplica individualmente a una instancia.

En Carbon 2.0 se puede seguir usando el método formatLocalized para traducir fechas pero recomienda sustituirlo a isoFormat que usa el formato ISO, en vez del formato específico de PHP que necesita ser instalado donde se encuentre la aplicación. Además, la nueva forma es compatible con el formato de la librería moment.js.

<?php

$date = Carbon::parse('2019-06-15 17:34:15.984512', 'UTC')->locale('es');
echo $date->isoFormat('MMMM Do YYYY, h:mm:ss a'); // junio 15º 2019, 5:34:15 p. m.
echo "\n";
echo $date->isoFormat('dddd'); // viernes
echo "\n";
echo $date->isoFormat('YYYY [escapado] YYYY'); // 2019 escapado 2019

Puedes ver el listado completo de formatos ISO en la documentación

Si deseas personalizar las traducciones se recomienda crear tu propio lenguaje/variante en vez de sobreescribir los que vienen incluidos en el paquete como se presenta a continuación:

<?php

$studyLenguage = 'es_Estudios';
$translator = \Carbon\Translator::get($studyLenguage);
$translator->setTranslations([
    'day' => ':count día de estudio|:count días de estudio',
]);

$date1 = Carbon::create(2019, 5, 10, 0, 0, 0);
$date2 = Carbon::create(2019, 5, 13, 4, 0, 0);

echo $date1->locale($studyLenguage)->diffForHumans($date2); // 3 días de estudio antes

$translator->setTranslations([
    'before' => function ($time) {
        return '['.strtoupper($time).']';
    },
]);

echo $date1->locale($studyLenguage)->diffForHumans($date2); // [3 DÍAS DE ESTUDIO]

Si deseas conocer más sobre las nuevas opciones te invito a ingresar a la sección de localización de la documentación oficial.

Fechas Inmutables

Uno de los detalles de Carbon antes de la versión 2.0 es que los objetos creados usando la clase Carbon\Carbon son objetos mutables ya que esta clase extiende de la clase DateTime de PHP. Por tanto, a los objetos creados se les puede modificar su valor, como por ejemplo:

$date = Carbon::createFromDate(2019, 6, 8); 
echo $date; // 2019-6-8 09:25:31 

$dateWithDays = $date->addDays(3);

echo $dateWithDays; // 2019-6-11 09:25:31 
echo $date; // 2019-6-11 09:25:31

Si usamos la fecha $date para crear $dateWithDays añadiendo 3 días a $date entonces las dos fechas tienen el mismo valor, ya que $date ha cambiado su valor por ser un objeto mutable.

Ahora con esta nueva versión de Carbon podemos crear un objeto fecha inmutable utilizando la nueva clase CarbonImmutable. Al obtener como resultado un objeto inmutable, no va a ser modificado una vez creado, como lo veremos a continuación:

$dateNow = CarbonImmutable::createFromDate(2019, 6, 8);
echo $dateNow; //  2019-6-8 09:25:31

$dateWithMonths = $dateNow->addMonths(3);
echo $dateWithMonths; //  2019-9-8 09:25:31 

echo $dateNow; //  2019-6-8 09:25:31

Con este ejemplo podemos observar que al crear una fecha inmutable podemos generar nuevas fechas a partir de ella sin afectarla, es decir, en el ejemplo el objeto $dateNow no se modificó aun cuando usamos el método addMonths sobre él para crear la fecha $dateWithMonths. Por tanto, se sigue el concepto de la inmutabilidad.

La clase Factory

Con Carbon, podemos usar una de sus clases llamada Factory la cual es una forma de agrupar en una configuración una llamada de configuración regional, zona horaria, desbordamiento de meses / año, etc. Esta la mejor manera de mantener el código organizado y aislado. Siempre que sea posible, te recomendamos que trabajes con fechas UTC, luego apliques localmente (o con una clase Factory) la zona horaria y el idioma antes de mostrar las fechas al usuario.

Veamos este ejemplo para que nos quede más claro:

// Digamos que Clemir desde Caracas y Duilio desde Londres juegan ajedrez

$clemirDateFactory = new Factory([
    'locale' => 'es_VE',
    'timezone' => 'America/Caracas',
]);

$duilioDateFactory = new Factory([
    'locale' => 'en_UK',
    'timezone' => 'Europe/London',
]);

// Cada uno verá la fecha en su propio idioma y zona horaria

// Cuando Clemir mueve una pieza, mostramos las fechas en español, pero notificamos a Duilio en inglés:
$gameStart = Carbon::parse('2019-06-15 12:34:00', 'UTC');
$move = Carbon::now('UTC');

$toDisplay = $clemirDateFactory->make($gameStart)->isoFormat('lll')."\n".
    $clemirDateFactory->make($move)->calendar()."\n";

$notificationForDuilio = $duilioDateFactory->make($gameStart)->isoFormat('lll')."\n".
    $duilioDateFactory->make($move)->calendar()."\n";

echo $toDisplay;
/*
15 de Junio del 2019 12:34
Hoy a las 16:42
*/

echo $notificationForDuilio;
/*
Jun 15, 2018 12:34 PM
Today at 4:42 PM
*/

Cambios en el método create

Los valores predeterminados (cuando se omiten los parámetros) para $month y $day en el método create() ahora son 01 (estos parámetros eran obligatorios en Carbon 1). De igual forma, los valores predeterminados para $hour, $minute y $second cuando estos parámetros son omitidos ahora son 0. Sin embargo, puedes pasar explícitamente null para $month y $day y los valores tomarán el mes y día actual (comportamiento similar al de Carbon 1).

// Carbon colocara el día y mes en 1 si no pasamos nada.
echo Carbon\Carbon::create(2019); // 2019-01-01T00:00:00.000000Z

// En caso de pasar nulo tomará el mes y el día actual.
echo Carbon\Carbon::create(2019, null, null); // 2019-07-11T00:00:00.000000Z

Si estás haciendo la migración de la versión 1.x a 2.x debes revisar si este cambio afecta tu aplicación.

Precisión en microsegundos

Ahora puedes obtener precisión en microsegundos en todas partes, también significa que 2 fechas pueden ser creadas en el mismo segundo, pero no en el mismo microsegundo, esto significa que ya no son iguales.

Si estás haciendo la migración de la versión 1.x a 2.x debes revisar si este cambio afecta tu aplicación.

Transformación de un objeto a JSON

$date->jsonSerialize()json_encode($date) ya no devuelve un arreglo sino una cadena por ejemplo "2017-06-27T13:14:15.000000Z". Esto permite crear fechas a partir de ella fácilmente en JavaScript. Aún se puede obtener el comportamiento anterior en Carbon 2.0 usando:

Carbon::serializeUsing(function ($date) {
    return [
        'date' => $date->toDateTimeString(),
        'timezone_type' => $date->timezone_type,
        'timezone' => $date->tzName,
    ];
});

Si estás haciendo la migración de la versión 1.x a 2.x debes revisar si este cambio afecta tu aplicación.

Cambios a los métodos isSameMonth y isCurrentMonth

Los métodos isSameMonthisCurrentMonth ahora devuelven false para el mismo mes en un año diferente, pero puede pasar false como segundo argumento de isSameMonth o primer argumento de isCurrentMonth para comparar ignorando el año.

Si estás haciendo la migración de la versión 1.x a 2.x debes revisar si este cambio afecta tu aplicación.

Cambios a la propiedad dayOfYear

En Carbon 1 la propiedad dayOfYear comienza con 0. Ahora en esta nueva versión comienza en 1.

Si estás haciendo la migración de la versión 1.x a 2.x debes revisar si este cambio afecta tu aplicación.

Con esto terminamos, si deseas conocer aun más sobre esta versión pueden visitar en su documentación oficial. Adicionalmente, te sugerimos que si todavía usas la versión anterior de Carbon en tus proyectos realices la migración a la versión 2.0 pues la anterior ha quedado obsoleta y Laravel 6.0 solo soporta Carbon 2.

Además, si te ha gusto este artículo compártelo con tus compañeros para que estén al tanto de estos cambios.

Suscríbete a nuestro boletín

Te enviaremos publicaciones con consejos útiles y múltiples recursos para que sigas aprendiendo.

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.