2016-09-28 10 views
5

Mam trudności z używaniem PHP DateTime do konwersji daty odebranej ze strefy czasowej GMT-8 (PST) do formatu czytelnego dla człowieka z strefa czasowa GMT -7 (PDT).Używanie PHP DateTime do parsowania i konwersji strefy czasowej PST na PDT (GMT -8 na GMT -7)

Oto przykład:

$tz = new DateTimeZone('America/Los_Angeles'); 
$saleEndDate = new DateTime("2016-11-07T17:30:00-08:00"); 
$saleEndDate->setTimezone($tz); 
echo $saleEndDate->format('Y-m-d H:i:s'); 

Wyjście powyższego kodu jest: 07.11.2016 17:30:00. Jednak powinien on wyświetlać 2016-11-07 18:30:00, ponieważ America/Los_Angeles jest teraz w świetle dziennym (GMT -7, PDT).

Z tego co czytałem w DateTime docs, komenda new DateTime powinien być w stanie zinterpretować, że ciąg 2016-11-07T17:30:00-08:00 ma GMT -8 Strefa czasowa:

The czasowej parametru i aktualnej strefy czasowej są ignorowane gdy parametr czas zawiera znacznik czasu UNIX (np. 946684800) lub określa strefę czasową (np. 2010-01-28T15: 00: 00 + 02: 00).

Mimo to nie sądzę DateTime rozpoznaje GMT -8 poprawnie.

Czy ktoś wie, jakie podejście jest konieczne, aby poprawnie przekonwertować między strefami czasowymi?

Aktualizacja:

Ja również próbowałem przechodzącą w DateTimeZone jako drugi parametr do konstruktora DateTime, ale również bez skutku:

$tz = new DateTimeZone('America/Los_Angeles'); 
$saleEndDate = new DateTime("2016-11-07T17:30:00-08:00", new DateTimeZone("America/Los_Angeles")); 
$saleEndDate->setTimezone($tz); 
echo $saleEndDate->format('Y-m-d H:i:s'); 

także nie działa:

$tz = new DateTimeZone('America/Los_Angeles'); 
$saleEndDate = new DateTime("2016-11-07T17:30:00", new DateTimeZone("PST")); 
$saleEndDate->setTimezone($tz); 
echo $saleEndDate->format('Y-m-d H:i:s'); 

Również nie działa:

$tz = new DateTimeZone("PDT"); 
$saleEndDate = new DateTime("2016-11-07T17:30:00", new DateTimeZone("PST")); 
$saleEndDate->setTimezone($tz); 
echo $saleEndDate->format('Y-m-d H:i:s'); 
+0

Nie spadłem, wznowiłem ... ale może nie rozumiem tutaj czegoś ... dlaczego myślisz, że powinien on zostać zamieniony na 18:30 tylko dlatego, że teraz oszczędzasz na świetle dziennym? -8 to w zasadzie Los Angeles, więc może nie ma co tu konwertować. –

+1

http://stackoverflow.com/questions/17694894/different-timezone-types-on-datetime-object "Tylko obiekty DateTime z dołączonymi strefami czasowymi typu 3 będą poprawnie zezwalać na czas letni." Twoja '$ saleEndDate' jest tworzona jako typ 1. – ceejayoz

+0

@PawelDubiel powinien się przekonwertować, ponieważ podany czas to' -8', ale zestaw stref czasowych to '-7' – zerkms

Odpowiedz

2

nie najlepsza, ale to jedyny sposób mogę myśleć to zrobić

$tz = new DateTimeZone('America/Los_Angeles'); 
$saleEndDate = new DateTime("2016-11-07T17:30:00-08:00"); 
$saleEndDate->setTimezone($tz); 
$stamp = $saleEndDate->format('U'); 
$zone = $tz->getTransitions($stamp, $stamp); 
if(!$zone[0]['isdst']) $saleEndDate->modify('+1 hour'); 
echo $saleEndDate->format('Y-m-d H:i:s'); 

Co ja robię tu za pomocą DateTimeZone::getTransitions function celu określenia, czy data podałeś jest strefa czasowa, czy nie. Jeśli nie, dodamy jedną godzinę. Zauważ, że to nie zmienia strefę czasową, to po prostu koryguje DST przesunąć

You can see it in action here

1

DateTime funkcjonuje tak jak powinno. Jeśli nie znajdujesz się w obszarze, w którym zaobserwowano różne czasy letnie do większego obszaru, 6 listopada (w 2016 r.) Opuścił DST (PDT-> PST), America/Los_Angeles.

https://www.timeanddate.com/news/time/usa-canada-end-dst-2016.html

Z timezeonedb można skontrolować datami wykorzystywanymi przez przeszukanie tablicy dla danego Date/Time (który zrobił Machavity) i dostał się fakt, że nie jest w DST, a następnie udał się do zmodyfikuj ręcznie. Co nie jest odpowiedzią, ponieważ ostatecznie zakończy się niepowodzeniem, chyba że ręcznie dodasz czas wyłączenia, aby przerwać ręczną korekcję.

Sprawdzanie daty przejścia wokół daty ujawnia:

date_default_timezone_set('America/Los_Angeles'); 
$theDate = new DateTime("2016-11-07T17:30:00",new DateTimeZone("America/Los_Angeles")); 
$theDateBefore = new DateTime("2016-03-01"); 
$theDateAfter = new DateTime("2017-03-15"); 
echo "<pre>"; 
print_r($theDate->getTimezone()->getTransitions(
    $theDateBefore->getTimestamp(),$theDateAfter->getTimestamp())); 
echo "</pre>"; 

Powstały w tablicy 4:

Array 
(
    [0] => Array 
     (
      [ts] => 1456819200 
      [time] => 2016-03-01T08:00:00+0000 
      [offset] => -28800 
      [isdst] => 
      [abbr] => PST 
     ) 

    [1] => Array 
     (
      [ts] => 1457863200 
      [time] => 2016-03-13T10:00:00+0000 
      [offset] => -25200 
      [isdst] => 1 
      [abbr] => PDT 
     ) 

    [2] => Array 
     (
      [ts] => 1478422800 
      [time] => 2016-11-06T09:00:00+0000 
      [offset] => -28800 
      [isdst] => 
      [abbr] => PST 
     ) 

    [3] => Array 
     (
      [ts] => 1489312800 
      [time] => 2017-03-12T10:00:00+0000 
      [offset] => -25200 
      [isdst] => 1 
      [abbr] => PDT 
     ) 

) 

Array [0] to strefa czasowa, w efekcie na theDateBefore i można zobaczyć zmiany dat obowiązują dla twojego timezeone.

Data sprzedaży przypada po zmianie z PDT na PST.

Aby kod zwrócił skorygowaną datę/godzinę, należy ręcznie ją zmienić. Zrobienie tego w sposób, który został zaakceptowany, przyniesie fałszywe wyniki. Jak już wspomniałem, trzeba to otoczyć datami, w których ma być wymuszona niestandardowa strefa czasowa.

Powiązane problemy