web-dev-qa-db-fra.com

php: définition d'un fuseau horaire par décalage UTC

Utilisation de javascript Je sais que le fuseau horaire de mon utilisateur est UTC +3. 

Maintenant, je veux créer un objet DateTime avec cette connaissance:

$usersNow = new DateTime('now', new DateTimeZone("+3"));

Je reçois en réponse:

'Unknown or bad timezone (+2)'

Qu'est-ce que je fais mal? Comment puis-je réparer?

29
shealtiel

que dis-tu de ça...

$original = new DateTime("now", new DateTimeZone('UTC'));
$timezoneName = timezone_name_from_abbr("", 3*3600, false);
$modified = $original->setTimezone(new DateTimezone($timezoneName));
35
minaz

Tu as dit:

Utilisation de javascript Je sais que le fuseau horaire de mon utilisateur est UTC +3.

Vous avez probablement exécuté quelque chose comme ceci:

var offset = new Date().getTimezoneOffset();

Cela renvoie le décalage actuel à UTC en minutes, avec les valeurs positives tombant à l'ouest de UTC. Pas renvoie un fuseau horaire!

Un fuseau horaire n'est pas un décalage. Un fuseau horaire a un décalage. Il peut avoir plusieurs décalages différents. Il y a souvent deux décalages, un pour l'heure standard et un pour l'heure avancée. Une seule valeur numérique ne peut représenter cela seul.

  • Exemple de fuseau horaire: "America/New_York"
    • Offset standard correspondant: UTC-5
    • Décalage de la lumière du jour correspondant: UTC-4

Outre les deux décalages, les dates et heures de la transition entre les deux décalages sont également résumées dans ce fuseau horaire afin que vous sachiez quand ils s'appliquent. Il existe également un historique de la manière dont les décalages et les transitions peuvent avoir changé au fil du temps.

Voir aussi "Fuseau horaire! = Décalé" dans la balise de fuseau horaire wiki .

Dans votre exemple, vous avez probablement reçu une valeur de -180 de javascript, représentant un décalage actuel de UTC + 3. Mais ce n'est que le décalage pour ce moment particulier! Si vous suivez la réponse de minaz , vous obtiendrez un fuseau horaire qui suppose que UTC + 3 est toujours le décalage correct. Cela fonctionnerait si le fuseau horaire réel est quelque chose comme "Africa/Nairobi" qui n’a jamais utilisé autre chose que UTC + 3. Mais sachez que votre utilisateur pourrait se trouver dans "Europe/Istanbul" , qui utilise UTC + 3 en été et UTC + 2 en hiver.

10
Matt Johnson

Depuis PHP 5.5.10, DateTimeZone accepte un décalage du type "+3":

https://3v4l.org/NUGSv

4
Matthew

Réponse moderne:

$usersNow = new DateTime('now', new DateTimeZone('+0300'));

Documentation:

http://php.net/manual/en/datetimezone.construct.php

3
William Entriken

Pour tous ceux qui rencontraient cela, je faisais face au même problème. J'ai donc finalement étendu la classe DateTime et remplacé la méthode __construct() pour accepter un décalage (en minutes) au lieu d'un fuseau horaire.

À partir de là, ma __construct() personnalisée détermine le décalage en heures et en minutes (par exemple -660 = +11: 00), puis utilise parent::__construct() pour remettre ma date, formatée de manière personnalisée pour inclure mon décalage, à la date d'origine.

Comme je traite toujours avec les heures UTC dans mon application, ma classe modifie également l'heure UTC en soustrayant l'offset, donc passer à minuit UTC et un offset de -660 me montreront 11h.

Ma solution est détaillée ici: https://stackoverflow.com/a/35916440/2301484

1
Grayda

Autant que je sache, d'après la documentation sur DateTimeZone , vous devez indiquer un fuseau horaire valide. Voici les valid . Vérifiez les autres , quelque chose peut vous aider. 

1
Joey Rivera

avez-vous essayé cela

http://php.net/manual/en/function.strtotime.php

 <?php
    echo strtotime("now"), "\n";
    echo strtotime("10 September 2000"), "\n";
     echo strtotime("+5 hours");
    echo strtotime("+1 day"), "\n";
    echo strtotime("+1 week"), "\n";
    echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
    echo strtotime("next Thursday"), "\n";
    echo strtotime("last Monday"), "\n";
    ?>
1
zod

J'ai été dirigé vers une solution grâce au lien de Joey Rivera. Comme ce que les autres ont dit ici, le fuseau horaire n'est pas un décalage, vous avez besoin d'un fuseau horaire valide. 

C'est ce que je me sers

$singapore_time = new DateTime("now", new DateTimeZone('Asia/Singapore'));


var_dump( $singapore_time );

J'ai moi-même trouvé beaucoup plus pratique de travailler avec le format AAAA-MM-JJ HH: MM. Exemple.

$original = new DateTime("2017-05-29 13:14", new DateTimeZone('Asia/Singapore'));
0
Bruce Tong

Celui-ci va un peu plus loin dans la réponse de Matthew pour changer le fuseau horaire d'une date en un décalage entier.

public static function applyHourOffset(DateTime $dateTime, int $hourOffset):DateTime
{
    $dateWithTimezone = clone $dateTime;

    $sign = $hourOffset < 0 ? '-' : '+';
    $timezone = new DateTimeZone($sign . abs($hourOffset));
    $dateWithTimezone->setTimezone($timezone);

    return $dateWithTimezone;
}

Remarque: j'ai eu une rupture de production en raison de la réponse acceptée.

0
Michael Clark

DateTimeZone nécessite un fuseau horaire et non un décalage

0
user557846