web-dev-qa-db-ger.com

PHP - strtotime, Zeitzone angeben

Ich habe eine Datumszeichenfolge, sagen Sie "2008-09-11". Ich möchte einen Zeitstempel daraus erhalten, aber ich muss eine Zeitzone dynamisch angeben (anstatt PHP Standard). 

Um es zusammenzufassen: Ich habe zwei Saiten:

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

Wie bekomme ich den Zeitstempel dafür?

BEARBEITEN: Die Uhrzeit wird um Mitternacht dieses Tages sein. $ DateStr = '2008-09-11 00:00:00';

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

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

69
salathe

Die akzeptierte Antwort ist großartig, wenn Sie PHP> 5.2 ausführen (ich denke, dies ist die Version, in der die DateTime-Klasse hinzugefügt wurde). Wenn Sie eine ältere Version unterstützen möchten, möchten Sie nicht so viel eingeben, oder wenn Sie nur den funktionalen Ansatz bevorzugen, gibt es eine andere Möglichkeit, die globale Einstellungen nicht zu ändern:

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

Dies funktioniert, wenn Sie aus irgendeinem Grund <5.2 verwenden (Himmelsverbot).

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

Aber alles 5.2 und höher würde ich dringend empfehlen, dass Sie sich für die Antwort von @ salathe entscheiden.

16
Jonah

Wenn Sie Timezones verwenden möchten, schlage ich vor, dass Sie die DateTime-Klasse und in diesem Fall die DateTime :: createFromFormat () - Funktion verwenden, mit der Sie Semothing wie folgt ausführen können:

$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);

Wenn Sie $ tz in die DateTime :: createFromFormat-Funktion eingeben, sagen Sie ihr, in welcher Zeitzone das Datum eingegeben wurde. Wenn Sie es in eine andere Zeitzone konvertieren müssen, müssen Sie nur Folgendes tun:

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

Wenn Sie sich auf einen genauen Zeitpunkt beziehen, sollten Sie die Zeit nach einem einheitlichen Standard beibehalten, der nicht von der Sommerzeit beeinflusst wird. (GMT und UTC sind diesbezüglich gleichwertig, es wird jedoch bevorzugt, den Begriff UTC zu verwenden. Beachten Sie, dass UTC auch als Zulu oder Z-Zeit bezeichnet wird.)

Wenn Sie stattdessen eine Zeit mit einem lokalen Zeitwert beibehalten möchten, schließen Sie den lokalen Zeitversatz von UTC ein, sodass der Zeitstempel später eindeutig interpretiert werden kann.

In einigen Fällen müssen Sie möglicherweise sowohl die UTC-Zeit als auch die entsprechende Ortszeit speichern. Dies geschieht häufig mit zwei separaten Feldern, aber einige Plattformen unterstützen einen Datetimeoffset-Typ, der beide in einem einzigen Feld speichern kann.

Wenn Sie Zeitstempel als numerischen Wert speichern, verwenden Sie die Unix-Zeit. Dies ist die Anzahl der ganzen Sekunden seit 1970-01-01T00: 00: 00Z (ohne Schaltsekunden). Wenn Sie eine höhere Genauigkeit benötigen, verwenden Sie stattdessen Millisekunden. Dieser Wert sollte immer auf UTC basieren, ohne Zeitzonenanpassung.

Wenn Sie später den Zeitstempel ändern müssen, geben Sie die ursprüngliche Zeitzonen-ID an, damit Sie feststellen können, ob sich der Versatz möglicherweise von dem ursprünglichen Wert geändert hat.

Beim Planen zukünftiger Ereignisse wird normalerweise die lokale Zeit anstelle von UTC bevorzugt, da sich der Versatz normalerweise ändert. Siehe Antwort und Blogpost.

Denken Sie daran, dass Zeitzonen-Offsets nicht immer eine ganzzahlige Anzahl von Stunden sind (zum Beispiel ist die indische Standardzeit UTC + 05: 30 und Nepal verwendet UTC + 05: 45).

Wenn Sie Java verwenden, verwenden Sie Java.time für Java 8 oder Joda Time für Java 7 oder niedriger . Wenn Sie .NET verwenden, ziehen Sie die Verwendung von Noda Time in Betracht. Wenn Sie .NET ohne Noda Time verwenden, ist DateTimeOffset der Fall oft eine bessere Wahl als DateTime . Wenn Sie Perl verwenden, verwenden Sie DateTime . Wenn Sie Python verwenden, verwenden Sie pytz oder dateutil . Wenn Sie JavaScript verwenden, verwenden Sie moment.js mit der moment-timezone-Erweiterung . Wenn Sie PHP> 5.2 verwenden, verwenden Sie die von DateTime und DateTimeZone-Klassen bereitgestellten systemeigenen Zeitzonen-Konvertierungen. Seien Sie vorsichtig bei der Verwendung.

DateTimeZone :: listAbbreviations () - siehe Antwort. Installieren Sie regelmäßig das timezonedb-PECL-Paket, um PHP auf dem neuesten Stand Olson-Daten zu halten. siehe Antwort.

Wenn Sie C++ verwenden, stellen Sie sicher, dass Sie eine Bibliothek verwenden, die die IANA-Zeitzonen-Datenbank ordnungsgemäß implementiert. Dazu gehören cctz, ICU und Howard Hinnants "tz" -Bibliothek.

Verwenden Sie Boost nicht für Zeitzonen-Konvertierungen. Während die API behauptet, Standard-IANA-Kennungen (auch als "zoneinfo" bezeichnet) zu unterstützen, ordnet sie sie grob zu festen Offsets zu, ohne dabei die reichhaltigen Änderungshistorien zu berücksichtigen, die in jeder Zone vorgenommen wurden.

(Außerdem ist die Datei nicht mehr gewartet worden.)

Die meisten Geschäftsregeln verwenden die zivile Zeit anstelle von UTC oder GMT. Planen Sie daher die Konvertierung von UTC-Zeitmarken in eine lokale Zeitzone, bevor Sie die Anwendungslogik anwenden.

Denken Sie daran, dass Zeitzonen und Offsets nicht festgelegt sind und sich ändern können. In den USA und Großbritannien wurden zum Beispiel früher dieselben Daten verwendet, um nach vorne zu springen und zurückzufallen.

Im Jahr 2007 haben die USA jedoch das Datum geändert, an dem die Uhren geändert werden. Dies bedeutet nun, dass für 48 Wochen im Jahr der Unterschied zwischen der Londoner Zeit und der New Yorker Zeit 5 Stunden beträgt und für 4 Wochen (3 im Frühling, 1 im Herbst) 4 Stunden. Beachten Sie solche Elemente bei Berechnungen, die mehrere Zonen umfassen.

Berücksichtigen Sie die Art der Zeit (tatsächliche Ereigniszeit, Sendezeit, relative Zeit, historische Zeit, wiederkehrende Zeit), welche Elemente (Zeitstempel, Zeitzonenverschiebung und Name der Zeitzone) für den korrekten Abruf gespeichert werden müssen - siehe "Zeitarten" in Antworten.

Halten Sie Ihre Tzdata-Dateien für Betriebssystem, Datenbank und Anwendung zwischen sich und dem Rest der Welt synchron.

Stellen Sie auf Servern Hardware- und OS-Uhren auf UTC anstatt auf eine lokale Zeitzone ein.

Unabhängig vom vorherigen Aufzählungspunkt sollte serverseitiger Code, einschließlich Websites, niemals erwarten, dass die lokale Zeitzone des Servers etwas Besonderes ist. siehe Antwort.

Verwenden Sie NTP - Dienste auf allen Servern.

Denken Sie bei der Verwendung von FAT32 daran, dass Zeitstempel in Ortszeit und nicht in UTC gespeichert werden.

Denken Sie bei wiederkehrenden Ereignissen (z. B. wöchentliche TV-Sendungen) daran, dass sich die Zeit mit der Sommerzeit ändert und in den Zeitzonen unterschiedlich ist.

Abfragen von Datums-/Uhrzeitwerten immer als untergeordnete Angabe, einschließlich oberer Angabe (> =, <).

2
Charu

Lakonische Antwort (keine Änderung der Standardzeitzone erforderlich)

$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'
);

Geredete Antwort

Verwenden Sie die zweite Option von strtotime, die den Referenzrahmen der Funktion ändert. Übrigens möchte ich die Standardzeitzone des Skripts nicht aktualisieren:

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

int strtotime (Zeichenfolge $ time [ int $ now = time ())

Die Funktion erwartet eine Zeichenfolge, die ein englisches Datumsformat und .__ enthält. wird versuchen, dieses Format in einen Unix-Zeitstempel (die Anzahl von .__ Sekunden seit dem 1. Januar 1970 00:00:00 UTC) zu analysieren, relativ zum Zeitstempeljetzt angegeben oder die aktuelle Uhrzeit, wenn jetzt nicht angegeben.

Und ein Helfer

/**
 * 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')
    )
);

Vielleicht nicht der performanteste Ansatz, funktioniert aber gut, wenn Sie die Standardzeitzone und den Offset kennen. Wenn zum Beispiel die Standardzeitzone UTC ist und der Versatz -8 Stunden ist:

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