Comment gérer DateTime avec Carbon dans Laravel PHP

A un moment donné, presque toutes les applications Laravel ont besoin de travailler avec des dates et des heures. Mais la gestion des dates et des heures est parfois ridiculement complexe, à cause des fuseaux horaires. Dans quel fuseau horaire stockez-vous les dates et les heures ? Comment calculez-vous les différences entre les heures ?

Heureusement, il y a Carbon: une simple extension de l’API PHP pour DateTime. Cela peut sembler très complexe, mais ça ne l’est pas vraiment. Laravel utilise Carbon par défaut, mais la documentation en parle à peine. Dans ce tutoriel, je vais vous montrer tous les moyens importants pour que vous puissiez… utiliser Carbon pour gérer DateTime et les fuseaux horaires dans Laravel.

Qu’est-ce que le carbone ?

Carbon est un packet PHP qui permet de traiter avec temps et fuseaux horaires beaucoup plus fluide et lisible. Il traite de beaucoup de choses, comme :

  1. Création de dates
  2. Conversion des dates entre différents fuseaux horaires
  3. Ajout de et soustraction des temps
  4. Calculer les différences entre les temps
  5. Convertir les dates dans un format lisible par l’homme

Tout d’abord, qu’est-ce qu’un datetime? Pour faire simple, une date signifie que moment. Il se compose de trois parties :

  1. Date
  2. Heure
  3. Fuseau horaire (s’il n’est pas défini, il utilise la valeur par défaut, généralement UTC (+0))

Ces trois caractéristiques vous permettent d’indiquer juste ce moment précis. Après avoir défini vos moments, vous pouvez commencer à jouer avec eux en les convertissant dans d’autres fuseaux horaires et en calculant les différences.

Vous stockez un datetime (qui est en fait une instance de la classe Carbon ) dans une variable, et vous pouvez ensuite l’utiliser ou la modifier :

$now = now();

$trialExpires = $now->addDays(30);
  // Ou
$trialExpires = now()->addDays(30);

Comment utiliser Carbon

Pour ce tutoriel, je suppose que vous avez une installation Laravel. Si vous voulez utiliser le Carbon:: dans un fichier, Importez l’aide IlluminateSupportCarbon ou CarbonCarbon en haut de votre fichier :

<?php

use IlluminateSupportCarbon;

Obtenir des dates ou des heures spécifiques avec Carbon

Voici quelques exemples de la façon d’obtenir spécifique dates et temps avec Carbon dans Laravel :

Obtenir l’heure actuelle avec Carbon

Ceci permet d’obtenir une instance de Carbon avec l’option heure actuelle:

$now = now();
$today = today(); 

Le site now() est une méthode que vous utiliserez probablement le plus souvent. Il existe également quelques autres aides, mais pour celles-ci, vous devez les appeler sur la fonction Carbon:: façade :

$now = Carbon::now();
$today = Carbon::today();
$tomorrow = Carbon::tomorrow('Europe/London');
$yesterday = Carbon::yesterday();

Ces méthodes acceptent un fuseau horaire (si ce n’est pas le cas, l’heure sera fixée par défaut à UTC) et l’heure sera fixée à minuit (00:00:00).

Sachez que les deux exemples ci-dessous ne sont pas identiques, car le premier exemple crée une date-heure pour demain, à minuit dans le fichier Europe/London . Alors que le deuxième exemple crée une date pour demain, minuit dans le fuseau horaire Europe/London . UTC (UTC+0) et le fuseau horaire alors le convertit enEurope/Londonfuseau horaire. Je vais expliquer les fuseaux horaires ci-dessous.

$tomorrow = Carbon::now()->tomorrow('Europe/London');
$tomorrow = Carbon::now()->tomorrow()->tz('Europe/London');

Création manuelle de dates/heures avec Carbon

Il existe également quelques aides pratiques qui vous permettent de de créer manuellement des dates et des heures avec des valeurs que vous introduisez vous-même. Voir les exemples ci-dessous. Veuillez noter que lorsque vous passez dans null quelque part, la valeur par défaut sera la valeur actuelle de ce paramètre. Ainsi, en passant par null pour le mois prendra le mois en cours. Si le mois n’est pas pertinent dans une situation donnée, je recommanderais de passer dansnullpour le mois courant. 1 pour le mois de janvier.

Carbon::createFromDate($year, $month, $day, $tz);
Carbon::createMidnightDate($year, $month, $day, $tz);
Carbon::createFromTime($hour, $minute, $second, $tz);
Carbon::createFromTimeString("$hour:$minute:$second", $tz);
Carbon::create($year, $month, $day, $hour, $minute, $second, $tz);

Gestion des fuseaux horaires avec Carbon

Gestion des fuseaux horaires dans Laravel et PHP n’est pas très difficile, mais c’est une chose à laquelle vous devez vous habituer. Voici la règle la plus élémentaire de gestion des fuseaux horaires dans Laravel:

Dans le config/app.php vous pouvez définir la valeur par défaut timezone pour votre application. Par défaut, cette valeur est fixée à UTCdonc, en théorie, vous pouvez le modifier. Veuillez noter que le stockage des heures dans un fuseau horaire autre que UTC+0 est fortement déconseillé.

Veuillez toujours stocker vos dates en UTC dans la base de données et ne les convertissez que lorsque vous en avez besoin dans le fuseau horaire correct..

Quels fuseaux horaires peut-on utiliser dans Carbon et PHP ?

Quel est le site fuseaux horaires pouvons-nous choisir vous pourriez vous demander ? Il existe une fonction PHP appelée timezone_identifiers_list()qui renvoie un tableau de tous les fuseaux horaires supportés en PHP.

$tzs = timezone_identifiers_list();

echo $tzs;

=> [
     "Africa/Abidjan",
     "Africa/Accra",
     "Africa/Addis_Ababa",
     "Africa/Algiers",
     "Africa/Asmara",
     "Africa/Bamako",
     "Africa/Bangui",
     "Africa/Banjul",
     "Africa/Bissau",
     "Africa/Blantyre",
     "Africa/Brazzaville",
     "Africa/Bujumbura",
     "Africa/Cairo",
     "Africa/Casablanca",
     "Africa/Ceuta",
     //

En théorie, si vos utilisateurs sont en différents fuseaux horairesvous stocker toutes les heures et les dates dans UTC et les convertir au bon fuseau horaire lorsque vous les affichez.

Comment obtenir le fuseau horaire de l’utilisateur actuel dans Laravel ?

Pour simplifier trouver le fuseau horaire actuel de l’utilisateur, il existe un paquet appelé jamesmills/laravel timezone. Ce paquet crée un timezone sur le fichier users table pour l’Eloquent User . Chaque fois qu’un utilisateur se connecte ou seulement la première fois (ce que vous souhaitez), il sera détecter automatiquement le fuseau horaire et met à jour le timezone en conséquence.

Le paquet a quelques aides pratiques, comme :

Timezone::convertToLocal($post->created_at, 'Y-m-d g:i', true);
Timezone::convertFromLocal($request->get('publish_at'));

J’utilise généralement ce paquet pour récupérer le fuseau horaire de l’utilisateur lors de sa première connexion, puis j’ajoute une option pour le modifier dans les paramètres.

Comment ajouter un choisissez votre fuseau horaire dans les paramètres ? Vous pourriez ajouter une sorte de liste déroulante avec tous les résultats de l’option[1945135]. timezone_identifiers_list(); à la page des paramètres de chaque utilisateur et laisser l’utilisateur mettre à jour le fuseau horaire lui-même. Veillez à mettre à jour le fichier timezone sur la page User avec le nouveau fuseau horaire.

Conversion des dates et heures entre différents fuseaux horaires

Alors, comment faire pour convertir les dates et les heures dans un autre fuseau horaire? C’est très simple. Sur chaque instance de Carbon, vous pouvez enchaîner (->) les tz() aide. Cette aide convertit l’heure dans le nouveau fuseau horaire.

now()->tz('Europe/Amsterdam');

Ou vous pouvez insérer un paramètre de fuseau horaire partout où vous voyez $tz paramètre :

Carbon::create($year, $month, $day, $hour, $minute, $second, $tz);

Mais vous devez être conscient de ce qui suit, ce que j’ai également dit ci-dessus. Ce n’est pas la même chose :

$tomorrow = Carbon::now()->tomorrow('Europe/London');
$tomorrow = Carbon::now()->tomorrow()->tz('Europe/London');

Vous devez voir le deuxième point comme : « J’ai une date et une heure précises, qui décrivent en fait un certain… moment. Je veux afficher que moment dans un autre fuseau horaire, alors je fais $moment->tz($tz). Le site moment reste exactement le même, mais le fuseau horaire est différent.

Il faut peut-être s’habituer un peu, mais dès que vous aurez acquis le bon état d’esprit, travailler avec les fuseaux horaires dans Laravel et PHP ne sera pas complexe. plus.

Convertir une chaîne anglaise en date

Carbon prend également en charge analyse syntaxique d’une chaîne de caractères anglaise en une date:

$lastDayOfFeb2021 = Carbon::parse('last day of February 2021');   // 2021-02-28 00:00:00.0 UTC (+00:00)

$lastDayOfFeb2020 = Carbon::parse('last day of February 2020');   // 2020-02-29 00:00:00.0 UTC (+00:00)

C’est vraiment magique, mais c’est quelque chose que je ne préfère généralement pas. Pour moi, c’est comme si vous laissiez une certaine place à l' »interprétation » dans votre code, en comptant sur le fait que Carbon comprenne ce que vous voulez dire. Et si ce n’est pas le cas, votre code sera cassé.

Mais la conversion de chaînes anglaises en dates n’est pas la seule utilisation de la fonction Carbon::parse() n’est pas le seul usage de la fonction Carbon::parse() . Vous pouvez également l’utiliser pour analyser n’importe quoi. Vous avez un timestamp dans un format ISO que vous ne savez pas comment analyser ? Voici Carbon::parse() à la rescousse !

Test pour savoir si Carbon retournera toujours la même date

Si vous obtenez cette chaîne de caractères, allez-vous toujours renvoyer exactement la même date ou non ? Par exemple, en disant last day of February 2020 renverra toujours une seule date. Mais dire last day of next month renverra différentes dates, en fonction de la date et du mois actuels.

Pour vérifier si Carbon renvoie toujours une chaîne de date/heure dite absolue, vous pouvez utiliser la fonction Carbon::hasRelativeKeywords($string) .

$string = 'first day of next month';
if (strtotime($string) === false) {
    echo "'$string' is not a valid date/time string.";
} elseif (Carbon::hasRelativeKeywords($string)) {
    echo "'$string' is a relative valid date/time string, it will returns different dates depending on the current date.";
} else {
    echo "'$string' is an absolute date/time string, it will always returns the same date.";
}

Tester ceci à chaque fois que vous utilisez Carbon::parse()est un peu fastidieux et ne vaut pas vraiment la peine à mon avis.

Ajout ou soustraction de dates et d’heures dans Carbon

L’une des fonctionnalités les plus importantes de Carbon est la possibilité de d’ajouter ou de soustraire des heures et des dates d’autres heures et dates. Cette opération est généralement très simple et ressemble à ceci :

now()->addDays(3);
now()->subWeekDays(3);

Pour chaque méthode, il y a généralement un addSomething() et un subSomething() méthode. Chaque méthode a généralement aussi un addSomethings($howMany) et subSomethings($howMany) méthode.

Ajout d’années

Tout d’abord, un exemple d’unité unique. Vous pouvez ajouter ou soustraire des jours avec les méthodes suivantes :

now()->addDay();
now()->addDays(30);
now()->subDay();
now()->subDays(30);

Le fait que la dernière période se termine dans un nouveau mois n’a pas d’importance.

Ajout ou soustraction d’unités

Découvrez le exemples d’addition et de soustraction de dates carbone ci-dessous tirés de la documentation. Notez qu’il existe un très grand nombre d’unités disponibles parmi lesquelles vous pouvez choisir.

$dt = Carbon::create(2012, 1, 31, 0);

echo $dt->toDateTimeString();            // 2012-01-31 00:00:00

echo $dt->addCenturies(5);               // 2512-01-31 00:00:00
echo $dt->addCentury();                  // 2612-01-31 00:00:00
echo $dt->subCentury();                  // 2512-01-31 00:00:00
echo $dt->subCenturies(5);               // 2012-01-31 00:00:00

echo $dt->addYears(5);                   // 2017-01-31 00:00:00
echo $dt->addYear();                     // 2018-01-31 00:00:00
echo $dt->subYear();                     // 2017-01-31 00:00:00
echo $dt->subYears(5);                   // 2012-01-31 00:00:00

echo $dt->addQuarters(2);                // 2012-07-31 00:00:00
echo $dt->addQuarter();                  // 2012-10-31 00:00:00
echo $dt->subQuarter();                  // 2012-07-31 00:00:00
echo $dt->subQuarters(2);                // 2012-01-31 00:00:00

echo $dt->addMonths(60);                 // 2017-01-31 00:00:00
echo $dt->addMonth();                    // 2017-03-03 00:00:00 equivalent of $dt->month($dt->month + 1); so it wraps
echo $dt->subMonth();                    // 2017-02-03 00:00:00
echo $dt->subMonths(60);                 // 2012-02-03 00:00:00

echo $dt->addDays(29);                   // 2012-03-03 00:00:00
echo $dt->addDay();                      // 2012-03-04 00:00:00
echo $dt->subDay();                      // 2012-03-03 00:00:00
echo $dt->subDays(29);                   // 2012-02-03 00:00:00

echo $dt->addWeekdays(4);                // 2012-02-09 00:00:00
echo $dt->addWeekday();                  // 2012-02-10 00:00:00
echo $dt->subWeekday();                  // 2012-02-09 00:00:00
echo $dt->subWeekdays(4);                // 2012-02-03 00:00:00

echo $dt->addWeeks(3);                   // 2012-02-24 00:00:00
echo $dt->addWeek();                     // 2012-03-02 00:00:00
echo $dt->subWeek();                     // 2012-02-24 00:00:00
echo $dt->subWeeks(3);                   // 2012-02-03 00:00:00

echo $dt->addHours(24);                  // 2012-02-04 00:00:00
echo $dt->addHour();                     // 2012-02-04 01:00:00
echo $dt->subHour();                     // 2012-02-04 00:00:00
echo $dt->subHours(24);                  // 2012-02-03 00:00:00

echo $dt->addMinutes(61);                // 2012-02-03 01:01:00
echo $dt->addMinute();                   // 2012-02-03 01:02:00
echo $dt->subMinute();                   // 2012-02-03 01:01:00
echo $dt->subMinutes(61);                // 2012-02-03 00:00:00

echo $dt->addSeconds(61);                // 2012-02-03 00:01:01
echo $dt->addSecond();                   // 2012-02-03 00:01:02
echo $dt->subSecond();                   // 2012-02-03 00:01:01
echo $dt->subSeconds(61);                // 2012-02-03 00:00:00

echo $dt->addMilliseconds(61);           // 2012-02-03 00:00:00
echo $dt->addMillisecond();              // 2012-02-03 00:00:00
echo $dt->subMillisecond();              // 2012-02-03 00:00:00
echo $dt->subMillisecond(61);            // 2012-02-03 00:00:00

echo $dt->addMicroseconds(61);           // 2012-02-03 00:00:00
echo $dt->addMicrosecond();              // 2012-02-03 00:00:00
echo $dt->subMicrosecond();              // 2012-02-03 00:00:00
echo $dt->subMicroseconds(61);           // 2012-02-03 00:00:00

// and so on for any unit: millenium, century, decade, year, quarter, month, week, day, weekday,
// hour, minute, second, microsecond.

// Generic methods add/sub (or subtract alias) can take many different arguments:
echo $dt->add(61, 'seconds');                      // 2012-02-03 00:01:01
echo $dt->sub('1 day');                            // 2012-02-02 00:01:01
echo $dt->add(CarbonInterval::months(2));          // 2012-04-02 00:01:01
echo $dt->subtract(new DateInterval('PT1H'));      // 2012-04-01 23:01:01

Calculer les différences entre deux temps

Calculer les différences entre deux dates n’est pas difficile avec Carbon. Carbon offre une large palette d’outils de diff() méthodes.

La première méthode s’appelle juste diff() et c’est très simple. Vous prenez une date, une chaîne ->diff($dateToCompare) sur elle et insérez une seconde date comme paramètre :

$date1 = now();
$date2 = now()->addDay();

$difference = $date1->diff($date2);
// This gives a DateInterval instance

Il existe également des méthodes qui vous donnent le différence en jours, heures ou minutes. Consultez l’exemple suivant tiré de la documentation :

$dtOttawa = Carbon::createMidnightDate(2021, 1, 1, 'America/Toronto');
$dtVancouver = Carbon::createMidnightDate(2021, 1, 1, 'America/Vancouver');
echo $dtOttawa->diffInHours($dtVancouver);                             // 3
echo $dtVancouver->diffInHours($dtOttawa);                             // 3

echo $dtOttawa->diffInHours($dtVancouver, false);                      // 3
echo $dtVancouver->diffInHours($dtOttawa, false);                      // -3

$dt = Carbon::createMidnightDate(2021, 1, 31);
echo $dt->diffInDays($dt->copy()->addMonth());                         // 31
echo $dt->diffInDays($dt->copy()->subMonth(), false);                  // -31

$dt = Carbon::createMidnightDate(2021, 4, 30);
echo $dt->diffInDays($dt->copy()->addMonth());                         // 30
echo $dt->diffInDays($dt->copy()->addWeek());                          // 7

$dt = Carbon::createMidnightDate(2021, 1, 1);
echo $dt->diffInMinutes($dt->copy()->addSeconds(59));                  // 0
echo $dt->diffInMinutes($dt->copy()->addSeconds(60));                  // 1
echo $dt->diffInMinutes($dt->copy()->addSeconds(119));                 // 1
echo $dt->diffInMinutes($dt->copy()->addSeconds(120));                 // 2

Soyez conscient que les valeurs retournées ici sont tronquées et arrondies. Cela signifie qu’une différence de 2,6 heures donnera 3.

Pour obtenir de meilleures différences, utilisez floatDiff():

echo Carbon::parse('06:01:23.252987')->floatDiffInSeconds('06:02:34.321450');    // 71.068463
echo Carbon::parse('06:01:23')->floatDiffInMinutes('06:02:34');                  // 1.1833333333333
echo Carbon::parse('06:01:23')->floatDiffInHours('06:02:34');                    // 0.019722222222222
// Those methods are absolute by default but can return negative value
// setting the second argument to false when start date is greater than end date
echo Carbon::parse('12:01:23')->floatDiffInHours('06:02:34', false);             // -5.9802777777778
echo Carbon::parse('2000-01-01 12:00')->floatDiffInDays('2000-02-11 06:00');     // 40.75
echo Carbon::parse('2000-01-01')->floatDiffInWeeks('2000-02-11');                // 5.8571428571429
echo Carbon::parse('2000-01-15')->floatDiffInMonths('2000-02-24');               // 1.3103448275862
// floatDiffInMonths count as many full months as possible from the start date
// (for instance 31 days if the start is in January), then consider the number
// of days in the months for ending chunks to reach the end date.
// So the following result (ending with 24 march is different from previous one with 24 february):
echo Carbon::parse('2000-02-15 12:00')->floatDiffInMonths('2000-03-24 06:00');   // 1.2822580645161
// floatDiffInYears apply the same logic (and so different results with leap years)
echo Carbon::parse('2000-02-15 12:00')->floatDiffInYears('2010-03-24 06:00');    // 10.100684931507

Affichage des différences de date pour les humains

Maintenant, voici la vraie magie part : afficher les différences de date de manière lisible pour l’homme. Oubliez l’utilisation de toutes sortes d’outils complexes if pour afficher un horodatage, utilisez plutôt Carbon !

Il existe quatre possibilités pour comparer des dates :

  1. Comparer un moment dans le passé à maintenant
    • il y a 2 heures
    • il y a 4 semaines
  2. Comparer un moment dans le passé à un autre moment dans le passé
    • 2 heures avant
    • 4 semaines avant
  3. Comparaison d’un moment dans le futur à maintenant
    • Dans 2 heures
    • Dans 4 semaines
  4. Comparer un moment dans le futur à un autre moment dans le futur
    • 2 heures après
    • 4 semaines après

Comment afficher les différences de date pour les humains ?

La syntaxe de afficher les différences de date de carbone est très simple. Cela se passe comme suit :

$date->diffForHumans($dateToCompareWith);

Le premier $date est toujours nécessaire, mais la deuxième variable $dateToCompareWith non. Si vous laissez cette variable vide, la valeur par défaut sera le moment actuel, now.

Comparaison entre un moment du passé et le moment présent

now()->subDays(5)->diffForHumans();
// "5 days ago"

Notez que now()->subDays(5) est le $date variable.

Comparer un moment du passé à un autre moment du passé

now()->subDays(5)->diffForHumans( now()->subDays(3) );
// "2 days before"

Comparer un moment dans le futur à un moment dans le présent

now()->addDays(5)->diffForHumans();
// "2 days before"

Comparer un moment dans le futur à un autre moment dans le futur.

now()->addDays(7)->diffForHumans( now()->addDays(5) );
// "1 day after"

// This might seem weird, but in fact it is 1 day and 23 hours

En règle générale : le site diffForHumans() compare si le $date est avant ou après le $dateToCompareWith.

Ainsi, si vous comparez deux moments dans le futur, vous pouvez également obtenir une déclaration « avant » :

now()->addDays(5)->diffForHumans( now()->addDays(7) );
// "2 days before"

Il existe quelques autres méthodes Carbon que vous pouvez utiliser, mais à mon avis, celles-ci sont plus que suffisantes pour le développeur moyen qui débute avec Carbon.

Conclusion

Comme nous l’avons vu dans cette Tutoriel sur le carbone pour les débutantsLa maîtrise de Carbon n’est absolument pas difficile. Il suffit de comprendre un peu son fonctionnement et de savoir ce qu’un moment est exactement. Je suis sûr que vous maîtriserez parfaitement cela dès que vous jouerez un peu plus avec Carbon, alors n’hésitez pas à laisser cet onglet de navigateur ouvert pendant que vous codez 😉.

Nouveau Tutoriel

Newsletter

Ne manquez jamais les nouveaux conseils, tutoriels et autres.

Pas de spam, jamais. Nous ne partagerons jamais votre adresse électronique et vous pouvez vous désabonner à tout moment.