I have a server which is set to EST, and all records in the database are set to EST. I would like to know how to set it to GMT. I want to offer a time zone option to my users.
6 Answers
I would strongly suggest avoiding messing with UNIX timestamps to make it look like a different time zone. This is a lesson I've learnt the hard way, way too many times.
A timestamp is the number of seconds since Midnight 1 January 1970, GMT. It doesn't matter where you are in the world, a given timestamp represents the exact same moment in time, regardless of time zones. Yes, the timestamp "0" means 10am 1/1/70 in Australia, Midnight 1/1/70 in London and 5pm 31/12/69 in LA, but this doesn't mean you can simply add or subtract values and guarantee accuracy.
The golden example which stuffed me up every year for way too long was when daylight savings would crop up. Daylight savings means that there are "clock times" which don't exist in certain parts of the world. For example, in most parts of the US, there was no such time as 2:01am on April 2, 2006.
Enough quasi-intelligible ranting though. My advice is to store your dates in the database as timestamps, and then...
- If you need the local time at the server, use
date()
- If you need to get GMT, then use
gmdate()
- If you need to get a different timezone, use
date_default_timezone_set()
and thendate()
For example,
$timestamp = time();
echo "BRISBANE: " . date('r', $timestamp) . "\n";
echo " UTC: " . gmdate('r', $timestamp) . "\n";
date_default_timezone_set('Africa/Johannesburg');
echo " JOBURG: " . date('r', $timestamp) . "\n";
// BRISBANE: Tue, 12 May 2009 18:28:20 +1000
// UTC: Tue, 12 May 2009 08:28:20 +0000
// JOBURG: Tue, 12 May 2009 10:28:20 +0200
This will keep your values clean (you don't have to be worrying about adding offsets, and then subtracting before saving), it will respect all Daylight Savings rules, and you also don't have to even look up the timezone of the place you want.

- 537,072
- 198
- 649
- 721
-
This is too screwy. And p01nd3xt3r's method is sound. If timezone X is, say, "7 hours ahead" of UTC, that is just another way of saying that the clocks in timezone X are now showing the same time that a UTC clock _will_ show 7 hours from now. So the question is "what is the current time in timezone X?" will always have the same answer as the question "what will the UTC time be in 7 hours?" -- at least until the timezone offset changes, whether due to Daylight Saving Time or whatever. – Robert L Sep 05 '09 at 03:35
-
4"at least until the timezone offset changes, whether due to Daylight Saving Time or whatever." ... and you're calling my solution screwy? – nickf Sep 06 '09 at 01:05
-
Yes, because you need a PHP library capable of this, and also what if the politicians change the rules, and what if you have other code which gets the local date, ... – Robert L Sep 15 '09 at 00:40
-
3"a PHP library capable of this" - it's built in. "what if the politicians change the rules" - good: you won't have to change any of your code - if PHP is kept updated, then it'll just work. "what if you have other code which gets the local date" - rinse and repeat. – nickf Sep 15 '09 at 01:21
-
5nickf is so right it hurts. You want to rely on a library or OS call, ANYTHING to avoid having to do time zone offset calculations yourself. Similar to nickf, I have also learnt this the hard way. – Mike Chamberlain Oct 20 '11 at 06:31
-
5Here here! Anyone dealing with this issue should use this solution. Both answers are good but this one is the better of the two. Just because it may confuse n3wbs does not make it an incorrect solution. Thanks nickf! Side note: nickf has 78k in rep, and p01nd3xt3r has 62. This says a lot about both users and what they bring to the table. – M.W. Felker Dec 06 '11 at 15:02
-
1@MaxFelker ...and it says something about how I spend my free time... :p – nickf Dec 07 '11 at 11:54
-
Once I had to do maintenance in an app where datetimes were stored as timestamps in the database. I remember bad moments having to decipher those "timestamp" numbers from the raw simple SQL query results into something understandable... Please, don't store your dates in the database as timestamps, if you can. – J. Bruni Jan 27 '12 at 06:31
-
2@J.Bruni what exactly was the problem? Almost every programming language (plus every SQL implementation that I know of) has built-in methods to convert a timestamp to a date and time. – nickf Jan 27 '12 at 22:28
-
@nickf The problem was that I always had to use one of these methods. :-) – J. Bruni Jan 29 '12 at 04:13
-
"but this doesn't mean you can simply add or subtract values and guarantee accuracy" - what if I do that, how can I loose the accuracy? – ihtus Aug 13 '13 at 18:35
-
2Because of changes to the timezone offset (eg: daylight savings). From the answer above: "For example, in most parts of the US, there was no such time as 2:01am on April 2, 2006." – nickf Aug 14 '13 at 03:59
-
nickf: thanks for your reply. Another question: I am recording an event time stamp with $timeGMT=time()-date("Z") and then display this $timeGMT: date("Y.m.d H:i",$timeGMT+$uTZ*3600), $uTZ is timezone offset and it's determined for each user and it reflects DTS (for ex for toronto $uTZ = -4 or -5). Based on your good experience with this issues: is this logic ok or I need to change something? – ihtus Aug 14 '13 at 13:12
-
1**If you're adding or subtracting something from the `time()`, then you're actually recording a different time.** With the offset, how does it reflect DST? When do you change it? How do you know when DST starts and ends for that particular region? If you use `date_default_timezone_set` then you don't have to worry about any of this. – nickf Aug 15 '13 at 07:36
-
nickf: the DST is reflected in the offset in a separate function. I just wanted to know if the logic described above outputs a good result, and hopefully I was not wrong. – ihtus Aug 15 '13 at 12:29
-
1you can still have problems around the edge, when adding dates which will cross the boundary (eg: April 2, 2006 1:30am + 1 hour = 3:30am). Please: Just use the functions that are designed for this purpose. – nickf Aug 15 '13 at 14:12
No matter in which GMT time zone the server is, here is an extremely easy way to get time and date for any time zone. This is done with the time()
and gmdate()
functions. The gmdate()
function normally gives us GMT time, but by doing a trick with the time()
function we can get GMT+N or GMT-N, meaning we can get the time for any GMT time zone.
For example, if you have to get the time for GMT+5, you can do it as follows
<?php
$offset=5*60*60; //converting 5 hours to seconds.
$dateFormat="d-m-Y H:i";
$timeNdate=gmdate($dateFormat, time()+$offset);
?>
Now if you have to get the time for GMT-5, you can just subtract the offset from the time()
instead of adding to it, like in the following example where we are getting the time for GMT-4
<?php
$offset=4*60*60; //converting 4 hours to seconds.
$dateFormat="d-m-Y H:i"; //set the date format
$timeNdate=gmdate($dateFormat, time()-$offset); //get GMT date - 4
?>

- 317,000
- 35
- 244
- 286

- 821
- 1
- 9
- 19
-
This is a good example... but how do i know the time that must be subtracted or added to the gmdate time ? – shasi kanth Oct 10 '12 at 06:02
-
2This answer is wrong i guess, because the time() function will get server local time. It won't get UTC so if you don't know what is the server time then you won't get expected time zone time. – rram Oct 21 '14 at 07:02
-
2
-
This requires you to hard-code the GMT offset in the `$offset=5*60*60` code. Not ideal, especially if you need to account for daylight savings or server clusters that span timezones. – Mark Aug 24 '16 at 16:02
Here is a list of the time zones with different from GMT, hope this is helpful!
echo '<pre>';
$zones_array = array();
$timestamp = time();
# to maintain the original timezone, store before
$default_timezone = date_default_timezone_get();
foreach (timezone_identifiers_list() as $key => $zone) {
date_default_timezone_set($zone);
$zones_array[$key]['zone'] = $zone;
$zones_array[$key]['diff_from_GMT'] = date('P', $timestamp);
}
# to maintain the original timezone, re-set after
date_default_timezone_set($default_timezone);
print_r($zones_array);
Thanks!

- 1,062
- 13
- 17

- 115
- 2
- 7
-
Do people ever reject edits or are people just spamming approve? I would have said... "This edit is incorrect or an attempt to reply to or comment on the existing post." – ficuscr Feb 28 '14 at 18:42
-
-
Ow I see. I was searching for some understanding and ended seeing this, and thought it was best to correct it. That if you're saying I was just wanting attention. If was for the solution... Well could you explain? I would be happy to learn... – Vitor Tyburski Feb 28 '14 at 20:39
It is important to note that if you are using date('Z') to convert a date that is stored in a database that you give the date the timestamp as the second argument, otherwise your result will not be accurate.
e.g.
In the UK, sometimes date('Z') will give 3600, sometimes it will give 0.
echo date('Z', strtotime('2012-01-01'));
Gives 0
echo date('Z', strtotime('2012-07-01'));
Gives 3600
So purely using strtotime($dbDateValue) - date('Z') can be wrong
Instead use:
$dbDateTimestamp = strtotime($dbDateValue); // where $dbDateValue something like 2012-01-01 22:34:00
$utcTimestamp = strtotime($dbDateTimestamp) - date('Z', $dbDateTimestamp);
This of course relies on PHP and the database both being set to the same timezone.

- 41
- 2
I was inspired by this question to write an alternative function to convert a timestamp to a needed timezone.
So, CORRECT procedure steps to record, display (convert) time:
1) record timestamp with time()
2) If you need to get a different timezone, use:
2.1) Class based:
2.1.1) DateTime class + setTimezone
or
2.1.2) date_default_timezone_set() and then date()
2.1.1) is better and more flexible than 2.1.2)
Function:
function getLTime_class($ts, $uTZ, $format_str="Y.m.d H:i", $sTZ="America/Toronto"){
// $ts - timestamp recorded with time(); if have date => convert to timestamp: strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
// $uTZ - TZ string (ex: 'America/Toronto'); convert timestamp to this TimeZone
// $sTZ - TZ string (ex: 'America/Toronto'); convert timestamp from this TimeZone
$TimeZone_server=new DateTimeZone($sTZ);
$date_obj=new DateTime("@$ts", $TimeZone_server);
$TimeZone_local=new DateTimeZone($uTZ);
$date_obj->setTimeZone($TimeZone_local);
return $date_obj->format($format_str);
}
Usage:
$date_input=$_POST['date_input']; //read from POST
$ts=strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
$userTZ='America/Toronto'; //read from user params
$result=getLTime_class($ts, $userTZ, 'Y-m-d H:i:s');
2.2) Non-Class based:
Function:
//this function replaces the function with DateTime class. It's faster. $uTZoffset is integer.
function getLTime_nonclass($ts, $uTZoffset, $format_str="Y.m.d H:i"){
// $ts - timestamp recorded with time(); if have date => convert to timestamp: strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
// $uTZoffset - TZ offset (integer) $uTZoffset must consider DTS (for ex: in summer $uTZoffset=-4; in winter $uTZoffset=-5)
$ts_offset=date('Z',$ts);
if ($uTZoffset) $add_offset=$ts_offset-date('Z'); //when not UTC
else $add_offset=0; //when UTC
return date($format_str,$ts-$ts_offset+$uTZoffset*3600+$add_offset);
}
Usage:
$date_input=$_POST['date_input']; //read from POST
$ts=strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
$uTZoffset=-4; //read from user params. $uTZoffset - TZ offset (integer) $uTZoffset must consider DTS (for ex: in summer $uTZoffset=-4; in winter $uTZoffset=-5)
$result=getLTime_nonclass($ts, $uTZoffset, 'Y-m-d H:i:s');
Results:
$date_input = 2012-08-17 12:00:00
Server date: summer (2013-08-26)
getLTime_class => $userTZ='America/Toronto' => 2012-08-17 12:00:00
getLTime_nonclass => $uTZoffset=-4 => 2012-08-17 12:00:00
getLTime_class => $userTZ='UTC' => 2012-08-17 16:00:00
getLTime_nonclass => $uTZoffset=0 => 2012-08-17 16:00:00
Server date: winter (2013-02-26)
getLTime_class => $userTZ='America/Toronto' => 2012-08-17 12:00:00
getLTime_nonclass => $uTZoffset=-5 => 2012-08-17 12:00:00
getLTime_class => $userTZ='UTC' => 2012-08-17 16:00:00
getLTime_nonclass => $uTZoffset=0 => 2012-08-17 16:00:00
$date_input = 2012-02-17 12:00:00
Server date: summer (2013-08-26)
getLTime_class => $userTZ='America/Toronto' => 2012-02-17 12:00:00
getLTime_nonclass => $uTZoffset=-4 => 2012-02-17 12:00:00
getLTime_class => $userTZ='UTC' => 2012-02-17 17:00:00
getLTime_nonclass => $uTZoffset=0 => 2012-02-17 17:00:00
Server date: winter (2013-02-26)
getLTime_class => $userTZ='America/Toronto' => 2012-02-17 12:00:00
getLTime_nonclass => $uTZoffset=-5 => 2012-02-17 12:00:00
getLTime_class => $userTZ='UTC' => 2012-02-17 17:00:00
getLTime_nonclass => $uTZoffset=0 => 2012-02-17 17:00:00
I decided to getLTime_nonclass hoping to make the conversion faster than using classes. All I ask is to confirm that getLTime_nonclass is a valid replacement for getLTime_class.
A lot of time there is task when necessary record time in DB in GMT+0, but function time() will return time of the server. Its possible resolve by next function:
/**
* Converts a local Unix timestamp to GMT
*
* @param int Unix timestamp
* @return int
*/
function local_to_gmt($time = '')
{
if ($time === '')
{
$time = time();
}
return mktime(
gmdate('G', $time),
gmdate('i', $time),
gmdate('s', $time),
gmdate('n', $time),
gmdate('j', $time),
gmdate('Y', $time)
);
}

- 2,050
- 1
- 24
- 22