PHP Timestamp em DateTime

94

Você sabe como posso converter isso para um strtotime ou um tipo de valor semelhante para passar para o DateTime objeto ?

A data que tenho:

Mon, 12 Dec 2011 21:17:52 +0000

O que eu tentei:

$time = substr($item->pubDate, -14);
$date = substr($item->pubDate, 0, strlen($time));

$dtm = new DateTime(strtotime($time));
$dtm->setTimezone(new DateTimeZone(ADMIN_TIMEZONE));
$date = $dtm->format('D, M dS');
$time = $dtm->format('g:i a');

O acima não está correto. Se eu percorrer várias datas diferentes, todas serão a mesma data.

JREAM
fonte

Respostas:

164

Você não precisa transformar a string em um carimbo de data / hora para criar o DateTimeobjeto (na verdade, seu construtor nem permite que você faça isso, como você pode ver). Você pode simplesmente inserir sua string de data no DateTimeconstrutor no estado em que se encontra:

// Assuming $item->pubDate is "Mon, 12 Dec 2011 21:17:52 +0000"
$dt = new DateTime($item->pubDate);

Dito isso, se você tiver um carimbo de data / hora que deseja usar em vez de uma string, pode fazer isso usando DateTime::setTimestamp():

$timestamp = strtotime('Mon, 12 Dec 2011 21:17:52 +0000');
$dt = new DateTime();
$dt->setTimestamp($timestamp);

Editar (07/05/2014):

Na verdade, eu não estava ciente disso na época, mas o DateTimeconstrutor suporte à criação de instâncias diretamente de carimbos de data / hora. De acordo com esta documentação , tudo o que você precisa fazer é preceder o carimbo de data / hora com um @caractere:

$timestamp = strtotime('Mon, 12 Dec 2011 21:17:52 +0000');
$dt = new DateTime('@' . $timestamp);
FtDRbwLXw6
fonte
Isso funciona muito bem. Eu já havia tentado isso antes, mas não devo ter dado uma chance suficiente !!! obrigado :))
JREAM de
18
Observe isso new DateTime('@' . $timestamp) e $dt = new DateTime(); $dt->setTimestamp($timestamp)não trate os fusos horários da mesma maneira. Veja minha resposta @ stackoverflow.com/questions/12038558/… para mais detalhes.
John Slegers de
43

Embora @drrcknlsn esteja correto ao afirmar que há várias maneiras de converter uma string de hora em data e hora, é importante perceber que essas diferentes maneiras não lidam com fusos horários da mesma maneira.


Opção 1 : DateTime('@' . $timestamp)

Considere o seguinte código:

date_format(date_create('@'. strtotime('Mon, 12 Dec 2011 21:17:52 +0800')), 'c');

O strtotimebit elimina as informações de fuso horário e a date_createfunção assume GMT ( Europe/Brussels).

Como tal, o resultado será o seguinte, independentemente do servidor em que o executar:

2011-12-12T13:17:52+00:00

Opção 2 : date_create()->setTimestamp($timestamp)

Considere o seguinte código:

date_format(date_create()->setTimestamp(strtotime('Mon, 12 Dec 2011 21:17:52 +0800')), 'c');

Você pode esperar que isso produza a mesma saída. No entanto, se eu executar este código de um servidor belga, obtenho a seguinte saída:

2011-12-12T14:17:52+01:00

Ao contrário da date_createfunção, o setTimestampmétodo assume o fuso horário do servidor ( 'Europe/Brussels'no meu caso) em vez de GMT.


Definir explicitamente o seu fuso horário

Se você quiser ter certeza de que sua saída corresponde ao fuso horário de sua entrada, é melhor defini-la explicitamente.

Considere o seguinte código:

date_format(date_create('@'. strtotime('Mon, 12 Dec 2011 21:17:52 +0800'))->setTimezone(new DateTimeZone('Asia/Hong_Kong')), 'c')

Agora, considere também o seguinte código:

date_format(date_create()->setTimestamp(strtotime('Mon, 12 Dec 2011 21:17:52 +0800'))->setTimezone(new DateTimeZone('Asia/Hong_Kong')), 'c')

Como definimos explicitamente o fuso horário da saída para corresponder ao da entrada, ambos criarão a mesma saída (correta):

2011-12-12T21:17:52+08:00
John Slegers
fonte
27

Provavelmente, a solução mais simples é apenas:

DateTime::createFromFormat('U', $timeStamp);

Onde 'U' significa época Unix. Veja os documentos: http://php.net/manual/en/datetime.createfromformat.php

Forsberg
fonte
3
Este método também ignora o fuso horário
Bouke Versteegh
2
@BoukeVersteegh e qual não?
Forsberg
2
@BoukeVersteegh Este é um timestamp Unix !, ele libera você de problemas de fuso horário durante a criação do objeto . apenas use ->setTimezonepara definir o fuso horário preferencial antes de ligar->format()
Contador م
1
@BoukeVersteegh Verifique esta nota importante do manual do PHP "O parâmetro $ timezone e o fuso horário atual são ignorados quando o parâmetro $ time é um carimbo de data / hora UNIX (por exemplo, @ 946684800) ou especifica um fuso horário (por exemplo, 2010-01-28T15: 00: 00 + 02: 00). "
Contador م
1
Os timestamps Unix não têm fusos horários, eles são sempre UTC por definição
the_nuts
0

é a minha solução:

    function changeDateTimezone($date, $from='UTC', $to='Asia/Tehran', $targetFormat="Y-m-d H:i:s")
    {
        $date = new DateTime($date, new DateTimeZone($from));
        $date->setTimeZone(new DateTimeZone($to));
        return $date->format($targetFormat);
    }
engenhoso
fonte