52

What's the easiest way to get the UTC offset in PHP, relative to the current (system) timezone?

Adam Ernst
  • 52,440
  • 18
  • 59
  • 71

8 Answers8

97
  date('Z');

returns the UTC offset in seconds.

Czimi
  • 2,494
  • 17
  • 14
  • 4
    Thanks. Unfortunately, PHP requires that you call date_default_timezone_set(). If you set that to GMT, your dates from a database will still be in local time, but date('Z') will return zero. If you set it to the server's timezone, you might as well just hard-code the server's offset from GMT in an include file. It's incredible that there's no straightforward way to do this. EDIT: I discovered that you can do date_default_timezone_set(date_default_timezone_get()). How asinine! – Oscar Jul 31 '12 at 21:25
  • date('Z') returns the GMT offset in seconds – Dahomz May 02 '17 at 12:29
  • That returns 0. – Adry Feb 21 '18 at 17:14
  • 2
    Adry, looks like you are in UTC (-; – jg6 Aug 26 '19 at 20:02
52
// will output something like +02:00 or -04:00
echo date('P');
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Tuhin Bepari
  • 725
  • 5
  • 11
22

timezone_offset_get()

$this_tz_str = date_default_timezone_get();
$this_tz = new DateTimeZone($this_tz_str);
$now = new DateTime("now", $this_tz);
$offset = $this_tz->getOffset($now);

Untested, but should work

John Millikin
  • 197,344
  • 39
  • 212
  • 226
20

I did a slightly modified version of what Oscar did.

date_default_timezone_set('America/New_York');
$utc_offset =  date('Z') / 3600;

This gave me the offset from my timezone, EST, to UTC, in hours.

The value of $utc_offset was -4.

Kenny
  • 2,150
  • 2
  • 22
  • 30
8

Simply you can do this:

//Object oriented style
function getUTCOffset_OOP($timezone)
{
    $current   = timezone_open($timezone);
    $utcTime  = new \DateTime('now', new \DateTimeZone('UTC'));
    $offsetInSecs =  $current->getOffset($utcTime);
    $hoursAndSec = gmdate('H:i', abs($offsetInSecs));
    return stripos($offsetInSecs, '-') === false ? "+{$hoursAndSec}" : "-{$hoursAndSec}";
}

//Procedural style
function getUTCOffset($timezone)
{
    $current   = timezone_open($timezone);
    $utcTime  = new \DateTime('now', new \DateTimeZone('UTC'));
    $offsetInSecs =  timezone_offset_get( $current, $utcTime);
    $hoursAndSec = gmdate('H:i', abs($offsetInSecs));
    return stripos($offsetInSecs, '-') === false ? "+{$hoursAndSec}" : "-{$hoursAndSec}";
}


$timezone = 'America/Mexico_City';

echo "Procedural style<br>";
echo getUTCOffset($timezone); //-06:00
echo "<br>";
echo "(UTC " . getUTCOffset($timezone) . ") " . $timezone; // (UTC -06:00) America/Mexico_City
echo "<br>--------------<br>";
echo "Object oriented style<br>";
echo getUTCOffset_OOP($timezone); //-06:00
echo "<br>";
echo "(UTC " . getUTCOffset_OOP($timezone) . ") " . $timezone; // (UTC -06:00) America/Mexico_City
HMagdy
  • 3,029
  • 33
  • 54
6

This is same JavaScript date.getTimezoneOffset() function:

<?php
echo date('Z')/-60;
?>
Sos.
  • 914
  • 10
  • 14
  • [`date('Z')`](http://php.net/manual/en/function.date.php) is the *«Timezone offset in seconds.»* The minus sign should stay... Divide by `60`. Not by `-60` Then, this will output the server's time zone offset. OP wanted (in 2008) to compare the local user's offset with this value you talk about. – Louys Patrice Bessette May 29 '17 at 21:55
  • @LouysPatriceBessette `getTimezoneOffset()` function in javascript gives like this value exactly (-180). – Sos. May 29 '17 at 22:00
  • That is true for [JavaScript getTimezoneOffset()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset)... And it is in minutes instead of seconds. PHP date doesn't do this absolute value inversion. – Louys Patrice Bessette May 29 '17 at 22:03
  • @LouysPatriceBessette I have tested this function and I compared it with javascript function and it is same in my location, gives value -180, so it is the correct answer for the question. Sorry for my English. – Sos. May 29 '17 at 22:07
  • PHP documentation states: *«The offset for timezones west of UTC is always negative»*... So there is no minus sign to revert. UTC-5 would give `-18000`, which is correct. – Louys Patrice Bessette May 29 '17 at 22:10
  • In fact, to have it in hours... It has to be divided by 3600... lol I just noticed it – Louys Patrice Bessette May 29 '17 at 22:11
  • @LouysPatriceBessette I don't know what PHP does. But this function is exactly like javascript `getTimezoneOffset()` and I have tested it now. – Sos. May 29 '17 at 22:13
  • Ok I got what you mean now... Your answer is correct if you compare `date('Z')/-60` with `date().getTimezoneOffset()`... Comparison is made in minutes and the minus sign is correct. Just add this explanation to you answer and I'll upvote you. ;) – Louys Patrice Bessette May 29 '17 at 22:15
  • @LouysPatriceBessette read my answer I wrote `same JavaScript getTimezoneOffset()` – Sos. May 29 '17 at 22:17
  • No it's not the same... What I said about the difference between the two is true. Plus, you'd have to round the PHP date since the division can create a floating value with too much decimals. – Louys Patrice Bessette May 29 '17 at 22:19
  • @LouysPatriceBessette OK Thank you for the note. – Sos. May 29 '17 at 22:23
  • 1
    I would say `round( date('Z')/-60 , 2);` (decimal precision) for time zones offsets like UTC+8:45 like Australia's Cetral Western. ;) I upvoted... But more explanations would be great... It's your answer. – Louys Patrice Bessette May 29 '17 at 22:24
  • @LouysPatriceBessette Thank you. – Sos. May 29 '17 at 22:26
  • 1
    Just for you to know... I've had your answer on the "Late answer" review queue. Questions and answers are strongly reviewed here ;) The more complete and relevant is your answer, the more rep. you will gain. ;) – Louys Patrice Bessette May 29 '17 at 22:29
  • @LouysPatriceBessette Thank you Louys. Actually I do not care about this. I wrote this answer just to help someone may need it. Thank you. – Sos. May 29 '17 at 22:38
  • Well a fully explained solution help better, don't you think? In this actual case, future reader *maybe* will read this conversation, but maybe not. ;) – Louys Patrice Bessette May 29 '17 at 22:40
  • @LouysPatriceBessette Sorry for my English I didn't understand you well before now :) Huh. You can explain the answer because I'm poor in English. – Sos. May 29 '17 at 22:44
  • Nope. I can edit other's post to improve English and code formating. But I should not (even if I can) improve the content of others with some content addition. What I can do is to post an answer as I would have done it, you could see what a great answer looks like. – Louys Patrice Bessette May 29 '17 at 22:54
  • @LouysPatriceBessette I don't know what to add for explain this answer, and I see it very clear . I have wrote it is same javascript `getTimezoneOffset()` function, so i think there is no need for more explain. – Sos. May 29 '17 at 22:59
3

This will output something formatted as: +0200 or -0400:

echo date('O');

This may be useful for a proper RSS RFC822 format

<pubDate>Sat, 07 Sep 2002 00:00:01 -0500</pubDate>

GMT offsets (like this) shouldn't use a colon (+02:00 from date('P');).

And, although it is acceptable for RSS RFC833, we don't want output like PDT and CST because these are arbitraty and "CST" can mean many things:

Jesse
  • 750
  • 1
  • 9
  • 25
-2

date("Z") will return the UTC offset relative to the server timezone not the user's machine timezone. To get the user's machine timezone you could use the javascript getTimezoneOffset() function which returns the time difference between UTC time and local time, in minutes.

<script type="text/javascript">
    d = new Date();
    window.location.href = "page.php?offset=" + d.getTimezoneOffset();
</script>

And in page.php which holds your php code, you can do whatever you want with that offset value. Or instead of redirecting to another page, you can send the offset value to your php script through Ajax, according to your needs.

Amr
  • 4,809
  • 6
  • 46
  • 60