web-dev-qa-db-fra.com

PHP - strtotime, spécifier le fuseau horaire

J'ai une chaîne de date, disons '2008-09-11'. Je souhaite obtenir un horodatage, mais je dois spécifier un fuseau horaire de manière dynamique (plutôt que PHP par défaut). 

Donc, pour récapituler, j'ai deux chaînes:

$dateStr = '2008-09-11';
$timezone = 'Americas/New_York';

Comment puis-je obtenir l'horodatage pour cela?

EDIT: L’heure de la journée sera le minuit de la journée .... $ dateStr = '2008-09-11 00:00:00';

48
Andy Hin
$date = new DateTime($dateStr, new DateTimeZone($timezone));

$timestamp = $date->format('U');

69
salathe

La réponse acceptée est excellente si vous utilisez PHP> 5.2 (je pense que c'est la version à laquelle ils ont ajouté la classe DateTime). Si vous souhaitez prendre en charge une ancienne version, vous ne souhaitez pas taper autant, ou si vous préférez simplement l'approche fonctionnelle, il existe un autre moyen de ne pas modifier les paramètres globaux:

$dateStr = '2008-09-11 00:00:00';
$timezone = 'America/New_York';
$dtUtcDate = strtotime($dateStr. ' '. $timezone);
22
krowe

Cela fonctionnera si, pour une raison quelconque, vous utilisez <5.2 (Dieu nous préserve).

$reset = date_default_timezone_get();
date_default_timezone_set('America/New_York');
$stamp = strtotime($dateStr);
date_default_timezone_set($reset);

Mais pour les versions 5.2 et supérieures, je vous recommande fortement de choisir la réponse de @ salathe.

16
Jonah

Si vous envisagez d'utiliser des fuseaux horaires, je vous propose d'utiliser la classe DateTime et, dans ce cas, la fonction DateTime :: createFromFormat (), qui vous permettra de créer un effet semblable à celui-ci:

$start = "2015-01-14 11:59:43";
$timezone = "America/Montreal";

$tz = new DateTimeZone($timezone);
$dt = DateTime::createFromFormat('Y-m-d H:i:s', $start, $tz);

Lorsque vous placez $ tz dans la fonction DateTime :: createFromFormat, vous lui indiquez le fuseau horaire de la date que vous avez indiquée. Ainsi, lorsque vous devez le convertir en un autre fuseau horaire, il vous suffit de procéder comme suit:

$start = $dt->setTimeZone(new DateTimeZone('UTC'));
4
Philippe Gilbert

Chaque fois que vous vous référez à un moment exact dans le temps, persistez-le selon une norme unifiée qui ne soit pas affectée par l'heure d'été. (GMT et UTC sont équivalents à cet égard, mais il est préférable d'utiliser le terme UTC. Notez que UTC est également appelé temps zoulou ou z.)

Si, au lieu de cela, vous choisissez de conserver une heure en utilisant une valeur d'heure locale, incluez le décalage de l'heure locale par rapport à l'heure UTC, de sorte que l'horodatage puisse être interprété ultérieurement sans ambiguïté.

Dans certains cas, vous devrez peut-être stocker l'heure UTC et l'heure locale équivalente. Cela se fait souvent avec deux champs distincts, mais certaines plates-formes prennent en charge un type datetimeoffset pouvant stocker les deux dans un seul champ.

Lorsque vous stockez des horodatages sous forme de valeur numérique, utilisez le temps Unix, qui correspond au nombre de secondes entières écoulées depuis le 1970-01-01T00: 00: 00Z (à l’exclusion des secondes intercalaires). Si vous avez besoin d'une plus grande précision, utilisez plutôt les millisecondes. Cette valeur doit toujours être basée sur UTC, sans aucun ajustement de fuseau horaire.

Si vous devez éventuellement modifier l'horodatage ultérieurement, incluez l'ID de fuseau horaire d'origine afin de déterminer si le décalage peut avoir été modifié par rapport à la valeur d'origine enregistrée.

Lors de la planification d'événements futurs, l'heure locale est généralement préférée à l'heure UTC, car il est courant que le décalage change. Voir la réponse et l'article du blog.

N'oubliez pas que les décalages de fuseaux horaires ne représentent pas toujours un nombre entier d'heures (par exemple, l'heure standard indienne est l'heure UTC + 05: 30 et le Népal utilise l'heure UTC + 05: 45).

Si vous utilisez Java, utilisez Java.time pour Java 8 ou Joda Time pour Java 7 ou une version inférieure . Si vous utilisez .NET, envisagez d’utiliser Noda Time . Si vous utilisez .NET sans Noda Time, considérez que DateTimeOffset est C'est souvent un meilleur choix que DateTime . Si vous utilisez Perl, utilisez DateTime .. Si vous utilisez Python, utilisez pytz ou dateutil . Si vous utilisez JavaScript, utilisez moment.js avec l'extension moment-timezone . Si vous utilisez PHP> 5.2, utilisez les conversions de fuseaux horaires natifs fournies par les classes DateTime et DateTimeZone. Soyez prudent lorsque vous utilisez.

DateTimeZone :: listAbbreviations () - voir la réponse. Pour conserver PHP avec les données Olson à jour, installez périodiquement le paquet PECL timezonedb; voir la réponse.

Si vous utilisez C++, veillez à utiliser une bibliothèque utilisant correctement la base de données de fuseau horaire IANA. Ceux-ci incluent cctz, ICU et la bibliothèque "tz" de Howard Hinnant.

N'utilisez pas Boost pour les conversions de fuseaux horaires. Alors que son API prétend prendre en charge les identifiants IANA standard (ou "zoneinfo"), elle les mappe grossièrement avec des décalages fixes sans tenir compte de la riche histoire des modifications que chaque zone a pu avoir.

(Le fichier n'est plus en maintenance.)

La plupart des règles commerciales utilisent le temps civil, plutôt que UTC ou GMT. Par conséquent, prévoyez de convertir les horodatages UTC en un fuseau horaire local avant d'appliquer la logique d'application.

N'oubliez pas que les fuseaux horaires et les décalages ne sont pas fixes et peuvent changer. Par exemple, historiquement, les États-Unis et le Royaume-Uni ont utilisé les mêmes dates pour «avancer» et «se replier».

Cependant, en 2007, les États-Unis ont modifié les dates auxquelles les horloges sont modifiées. Cela signifie maintenant que pour 48 semaines de l'année, la différence entre l'heure de Londres et l'heure de New York est de 5 heures et pour 4 semaines (3 au printemps, 1 à l'automne), de 4 heures. Tenez compte des éléments de ce type dans tous les calculs impliquant plusieurs zones.

Considérez le type d’heure (heure réelle de l’événement, heure de diffusion, heure relative, heure historique, heure récurrente), quels éléments (horodatage, décalage de fuseau horaire et nom de fuseau horaire) que vous devez enregistrer pour une récupération correcte - voir "Types d’heure" dans réponse.

Maintenez synchronisés vos fichiers tzdata de système d’exploitation, de base de données et d’applications, entre eux et le reste du monde.

Sur les serveurs, définissez les horloges matérielles et OS sur UTC plutôt que sur un fuseau horaire local.

Indépendamment du point précédent, le code côté serveur, y compris les sites Web, ne doit jamais s’attendre à ce que le fuseau horaire local du serveur soit particulier. voir la réponse.

Utilisez les services NTP sur tous les serveurs.

Si vous utilisez FAT32, rappelez-vous que les horodatages sont stockés à l'heure locale et non à l'heure UTC.

Lorsqu’il s’agit d’événements récurrents (émission télévisée hebdomadaire, par exemple), n’oubliez pas que l’heure change avec DST et sera différente selon les fuseaux horaires.

Interrogez toujours les valeurs date-heure en tant que limite inférieure incluse, exclusive supérieure (> =, <).

2
Charu

Laconic Answer (inutile de modifier le fuseau horaire par défaut)

$dateStr = '2008-09-11';
$timezone = 'America/New_York';
$time = strtotime(
    $dateStr, 
    // convert timezone to offset seconds
    (new \DateTimeZone($timezone))->getOffset(new \DateTime) - (new \DateTimeZone(date_default_timezone_get()))->getOffset(new \DateTime) . ' seconds'
);

Réponse parlante

Utilisez la deuxième option de strtotime qui modifie le cadre de référence de la fonction. En passant, je préfère ne pas mettre à jour le fuseau horaire par défaut du script:

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

int strtotime (chaîne $ time [ int $ now = time ()])} _

La fonction s'attend à recevoir une chaîne contenant un format de date anglais et essaiera d’analyser ce format dans un horodatage Unix (le nombre de secondes depuis le 1er janvier 1970 à 00:00:00 UTC), par rapport à l’horodatage. donné dans maintenant, ou l'heure actuelle si maintenant n'est pas fournie.

Et un assistant

/**
 * Returns the timestamp of the provided time string using a specific timezone as the reference
 * 
 * @param string $str
 * @param string $timezone
 * @return int number of the seconds
 */
function strtotimetz($str, $timezone)
{
    return strtotime(
        $str, strtotime(
            // convert timezone to offset seconds
            (new \DateTimeZone($timezone))->getOffset(new \DateTime) - (new \DateTimeZone(date_default_timezone_get()))->getOffset(new \DateTime) . ' seconds'
        )
    );
}

var_export(
    date(
        'Y-m-d', 
        strtotimetz('this monday', 'America/New_York')
    )
);

Peut-être pas l’approche la plus performante, mais elle fonctionne bien lorsque vous connaissez le fuseau horaire et le décalage par défaut. Par exemple, si le fuseau horaire par défaut est UTC et que le décalage est -8 heures:

var_dump(
    date(
        'Y-m-d', 
        strtotime('this tuesday', strtotime(-8 . ' hours'))
    )
);
0
HPM