124

Do you know how I can convert this to a strtotime, or a similar type of value to pass into the DateTime object?

The date I have:

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

What I've tried:

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

The above is not correct. If I loop through a lot of different dates its all the same date.

John Slegers
  • 45,213
  • 22
  • 199
  • 169
JREAM
  • 5,741
  • 11
  • 46
  • 84

4 Answers4

216

You don't need to turn the string into a timestamp in order to create the DateTime object (in fact, its constructor doesn't even allow you to do this, as you can tell). You can simply feed your date string into the DateTime constructor as-is:

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

That being said, if you do have a timestamp that you wish to use instead of a string, you can do so using DateTime::setTimestamp():

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

Edit (2014-05-07):

I actually wasn't aware of this at the time, but the DateTime constructor does support creating instances directly from timestamps. According to this documentation, all you need to do is prepend the timestamp with an @ character:

$timestamp = strtotime('Mon, 12 Dec 2011 21:17:52 +0000');
$dt = new DateTime('@' . $timestamp);
FtDRbwLXw6
  • 27,774
  • 13
  • 70
  • 107
  • This works great. I had tried this previously but must have not given it enough of a chance!!! thanks :)) – JREAM Aug 20 '12 at 14:09
  • 23
    Note that `new DateTime('@' . $timestamp)` and `$dt = new DateTime(); $dt->setTimestamp($timestamp)` don't deal with timezones the same way. See my answer @ http://stackoverflow.com/questions/12038558/php-timestamp-into-datetime/35525866#35525866 for more details. – John Slegers Feb 20 '16 at 16:29
  • 1
    I think `new DateTime("@$timestamp")` may be more readable. – Manngo Oct 17 '21 at 05:41
  • 1
    A little shorter: `$date = (new DateTime)->setTimestamp($timestamp);` – Dion May 16 '22 at 14:25
64

While @drrcknlsn is correct to assert there are multiple ways to convert a time string to a datatime, it's important to realize that these different ways don't deal with timezones in the same way.


Option 1 : DateTime('@' . $timestamp)

Consider the following code :

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

The strtotime bit eliminates the time zone information, and the date_create function assumes GMT.

As such, the output will be the following, no matter which server I run it on :

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

Option 2 : date_create()->setTimestamp($timestamp)

Consider the following code :

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

You might expect this to produce the same output. However, if I execute this code from a Belgian server, I get the following output :

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

Unlike the date_create function, the setTimestamp method assumes the time zone of the server (CET in my case) rather than GMT.


Explicitly setting your time zone

If you want to make sure your output matches the time zone of your input, it's best to set it explicitly.

Consider the following code :

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

Now, also consider the following code :

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

Because we explicitly set the time zone of the output to match that of the input, both will create the same (correct) output :

2011-12-12T21:17:52+08:00
John Slegers
  • 45,213
  • 22
  • 199
  • 169
51

Probably the simplest solution is just:

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

Where 'U' means Unix epoch. See docs: http://php.net/manual/en/datetime.createfromformat.php

forsberg
  • 1,681
  • 1
  • 21
  • 27
  • 5
    This method also ignores timezone – Bouke Versteegh Nov 09 '17 at 14:23
  • 3
    @BoukeVersteegh and which one doesn't? – forsberg Nov 12 '17 at 07:12
  • 8
    @BoukeVersteegh This is a Unix timestamp!, **it frees you from timezones problems while creating the object**. just use `->setTimezone` to set the preferable timezone before calling `->format()` – Accountant م Sep 06 '19 at 07:49
  • 4
    @BoukeVersteegh Check this big note from the [PHP manual](https://www.php.net/manual/en/datetime.construct.php) **"The $timezone parameter and the current timezone are ignored when the $time parameter either is a UNIX timestamp (e.g. @946684800) or specifies a timezone (e.g. 2010-01-28T15:00:00+02:00). "** – Accountant م Sep 06 '19 at 07:54
  • 8
    Unix timestamps don't have timezones, they are always UTC by definition – the_nuts Sep 21 '20 at 05:43
0

This is my solution:

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);
}
John Slegers
  • 45,213
  • 22
  • 199
  • 169
ingenious
  • 764
  • 2
  • 8
  • 24