0
votes

Changement du fuseau horaire de l'application Laravel, l'heure obtenue à partir de la base de données n'a pas changé

Supposons d'avoir un modèle Eloquent appelé Request avec la colonne next_check autocastée comme date (protected $ dates = ['next_check'];).

APP_TIMEZONE est la première Europe / Helsinki (+02: 00)

>>> Request::find(1)->next_check;
=> Illuminate\Support\Carbon @1603977424 {#2900
     date: 2020-10-29 14:17:04.0 Europe/Berlin (+01:00),
   }

Cela semble très bien et nous avons économisé 14:17:04 en supposant que nous sommes à Helsinki.

En changeant maintenant le fuseau horaire en Europe / Berlin (+01: 00), je suppose que 13:17:04 est renvoyé.

$ artisan tinker
Psy Shell v0.10.4 (PHP 7.4.11 — cli) by Justin Hileman
>>> $pr = Request::find(1);
>>> $pr->next_check = Carbon\Carbon::now();
>>> $pr->save();
>>> Request::find(1)->next_check;
=> Illuminate\Support\Carbon @1603973824 {#2900
     date: 2020-10-29 14:17:04.0 Europe/Helsinki (+02:00),
   }

Le fuseau horaire est changé mais il y a toujours l'heure retournée, qui a été initialement enregistrée dans l'heure Europe / Helsinki.

Est-ce un comportement attendu et comment puis-je obtenir mon comportement souhaité qu'un changement de fuseau horaire de l'application entraînerait des temps convertis?

ps: le fuseau horaire db configuré dans laravel est toujours celui par défaut '+00: 00'


4 commentaires

Que devez-vous accomplir? Voulez-vous afficher la date / l'heure différemment selon les utilisateurs en fonction de leur fuseau horaire actuel?


En fait, j'ai posé cette question davantage pour comprendre la gestion du fuseau horaire dans Laravel et je veux faire confiance aux heures, je vois. Lorsque mon application est en +02: 00 et que j'enregistre un horodatage dans la base de données, il doit être enregistré en interne en tant qu'horodatage UTC. Ce que je vois une autre fois dans phpMyAdmin est dû à la configuration du fuseau horaire. Mais maintenant, lorsque j'obtiens l'heure avec un fuseau horaire d'application +01: 00, ne devrait-il pas être converti de l'horodatage UTC de la base de données dans le fuseau horaire de mon application? Le fait qu'il ajoute simplement un fuseau horaire sans convertir l'heure ne me donne aucune confiance en ces données et je me demande si je devrais passer au champ datetime?


peut-être que laravel ne pense pas que les horodatages sont toujours en UTC mais dans le fuseau horaire de l'application? J'aurais donc besoin de toujours changer le fuseau horaire de la base de données lors du changement du fuseau horaire de l'application?


Vous ne pouvez pas modifier le fuseau horaire de la base de données avec la date existante. Veuillez envisager d'utiliser UTC sur le côté back-end medium.com/@kylekatarnls/ ... c'est le chemin. Le fuseau horaire d'Helsinki / Berlin devrait être mis en forme pour l'utilisateur.


3 Réponses :


1
votes

Si vous souhaitez localiser les heures afin qu'elles s'affichent à l'utilisateur dans le fuseau horaire de l'utilisateur, vous devez CONVERTIR une date / heure existante:

$users_timezone = 'Europe/Berlin';
$datetime->setTimezone($users_timezone);

Cela changera en fait l'heure en fonction de la différence entre le fuseau horaire de l'application et celui converti.


2 commentaires

Merci pour votre réponse. Oui je voulais dire que j'ai changé le fuseau horaire dans la config. Je n'ai pas besoin de savoir dans quel fuseau horaire l'enregistrement a été enregistré. Pour autant que je sache, l'heure sera enregistrée comme horodatage UTC dans le type de données d'horodatage mysql. Ainsi, lorsque je change le fuseau horaire de configuration, je suppose que l'heure que j'obtiens lorsque j'accède au champ changera. Donc dans mon exemple 13:17 +01: 00 au lieu de 14:17 +02: 00


Ah oui je vois. C'est parce que l'heure ne change pas en tant que telle - vous la mettez simplement dans un fuseau horaire différent, donc la seule chose qui change ... est le fuseau horaire.



0
votes

Pour obtenir mon comportement attendu, j'ai maintenant trouvé une solution. Si quelqu'un d'autre veut exactement le même comportement, cela pourrait être la solution:

Ajoutez l'appel suivant dans la méthode de démarrage de votre AppServiceProvider:

// according to https://www.sitepoint.com/synchronize-php-mysql-timezone-configuration/
private function setUTCOffsetInDBConnection() {

    $now = new \DateTime();
    $mins = $now->getOffset() / 60;

    $sgn = ($mins < 0 ? -1 : 1);
    $mins = abs($mins);
    $hrs = floor($mins / 60);
    $mins -= $hrs * 60;

    $offset = sprintf('%+d:%02d', $hrs*$sgn, $mins);

    DB::statement("SET time_zone='".$offset."';");
}

Le code de la méthode setUTCOffsetInDBConnection est le suivant:

$this->setUTCOffsetInDBConnection();

Cela synchronisera toujours le fuseau horaire en fonction du fuseau horaire de votre application et enregistrera les horodatages au format UTC dans la base de données.

Lorsque vous enregistrez maintenant un horodatage 2020-10-29 15:28:00 de votre application avec APP_TIMEZONE = Europe / Berlin dans votre .env, il l'enregistrera au format UTC dans la base de données (2020-10-29 15:28:00 ). Lorsque vous changez votre APP_TIMEZONE en Europe / Helsinki maintenant, vous obtiendrez 2020-10-29 16:28:00 retourné.

Sachez que votre phpMyAdmin peut toujours ne pas afficher les heures UTC enregistrées dans votre base de données puisque phpMyAdmin définit également le fuseau horaire des serveurs lors de l'ouverture de la connexion. Donc, si votre serveur qui exécute phpMyAdmin est également en Europe / Berlin, vous verrez 2020-10-29 15:28:00 et non la date UTC enregistrée dans la base de données.


1 commentaires

N'utilisez pas le décalage du fuseau horaire, il sera interrompu pour la date dans une autre saison DST.



0
votes

La réponse à "Est-ce un comportement attendu" est OUI

Pour «enregistrer» le fuseau horaire avec les données de date, vous devez également l'enregistrer en tant que colonne supplémentaire.

Ainsi, avoir à la fois "2020-10-29 14: 17: 04.0" et "Europe / Helsinki" dans DB vous permettra de vous rappeler quel fuseau horaire a été utilisé pour enregistrer cette date, donc si elle est modifiée, vous pouvez convertir.

Mais d'abord, vous devez envisager de ne pas modifier votre application et le fuseau horaire de la base de données, les deux doivent rester UTC.

Voir https://medium.com/@kylekatarnls/always-use-utc-dates-and-times-8a8200ca3164

Ainsi, vous pouvez facilement les convertir dans n'importe quel fuseau horaire et l'afficher correctement en fonction du fuseau horaire de l'utilisateur tout en conservant un format standard bien connu dans DB.


0 commentaires