Server Time - driving me nuts :-) - php

Okay so I have a server in Denver with a user in New Zealand. I know everything about the user (timezone etc) and through the program they request something to happen in advance - let's say at 11:30am on August 5th 2013. I have a CRON job that runs every 15 minutes and asks the database if any requests are pending for the next 15 minute period, but how do I convert their stored time to the servers equivalent.
I set the default timezone for calculations: date_default_timezone_set('America/Denver')
I take the time now on the server and turn it into epoch: strtotime(date('Y-m-d H:i:s'))
I add the 15 minutes to create a range: $forward15 = strtotime('now +15 minutes')
I get the user chosen date from the database (and their timezone): 2013-08-05 11:30:00
Now what? If I convert that into epoch, it'll just be the servers version of that date.

NEW SOLUTION SEE BELOW!
If you know the timezone you can simply "add" it to your time.
For example:
server time: 01/01/01 00:00
the time the user wants: 01/01/01 01:00
the timezone of the user: GMT - 5
Just get the time (01/01/01 01:00) and add +5 => 01/01/01 06:00
So: your script needs to be executed at 01/01/01 06:00
(convert to timestamp where needed)
Added a little php to demonstrate
<?php
$servertime = time(); //timestamp of 01/01/01 00:00
$usertime = "01/01/01 06:00";//database
$userUTC = "-5";//database
strreplace($userUTC, "-", "+";
$replacetext = $userUTC . " days";
$usertime = strtotime($replacetext, $usertime);//now usertime is in your local timezone
$crontime = date("d/m/Y H:i");//the time you want the script to be executed
?>
I'm just assuming that the timezone is saved as "-5" for example and not Europe/Amsterdam Just tell me if i'm wrong.
edit 14:37
This could be a even better solution i think!
<?php
$usertime = "01/01/01 06:00";
$userUTC = "-5";
$userdate = $usertime . " " . $userUTC;
$usertimestamp = strtotime($userdate);//now you have the timestamp with correct timezone
$crontime = date("d/m/Y H:i", $usertimestamp);//formatted to the right date
echo $crontime;
?>
Edit: 25-07-2013 14:26
New solution to suit your database:
<?php
$usertime = "01/01/01 06:00";
$userUTC = "Pacific/Auckland";//get from database
$userdate = $usertime . " " . $userUTC;
$usertimestamp = strtotime($userdate);//now you have the timestamp with correct timezone
$crontime = date("d/m/Y H:i", $usertimestamp);//formatted to the right date
echo $crontime;
?>

the server is in which GMT time zone here is extremely easy way to get time and date for any time zone. This is done with time() and gmdate() function. gmdate() function normally give us GMT time but by doing a trick with time() function we can get GMT+N or GMT-N means we can get time for any GMT time zone.
For example you have to get time for GMT+5 we will do it like following
<?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 which is GMT-5 now we will just subtract the offset from the time() instead of adding into time like in following example we are getting time for GMT-4
<?php
$offset=4*60*60; //converting 5 hours to seconds.
$dateFormat="d-m-Y H:i";
$timeNdate=gmdate($dateFormat, time()-$offset);
?>

Related

need to store date as per user timezone in php

i have simple php script where i have this variable
$date = date('Y-m-d', time());
The Problem: The variable is storing date as per my server timezone.
What is want: I want to store date as per user time zone, take a look into
example below:
1- tom checkin from USA
2- jenne checkin from Asia
since there is 12 hrs. difference so the date will be different too sometime
here is found some example but it's not dynamic
Converting GMT time to local time using timezone offset in php
offset = '-0500';
$isDST = 1; // Daylight Saving 1 - on, 0 - off
$timezoneName = timezone_name_from_abbr('', intval($offset, 10) * 36, $isDST);
$timezone = new DateTimeZone($timezoneName);
Then you can use it in a DateTime constructor, e.g.
$datetime = new DateTime('2012-04-21 01:13:30', $timezone);
Now what exactly i am looking,
1- in case of TOM $date should be 18
11:38 PM
Tuesday, 18 April 2017 (GMT-5)
Time in Chicago, IL, USA
2- in case of jenne $date should be 19
9:40 AM
Wednesday, 19 April 2017 (GMT+5)
Time in Lahore
difficult writing code in the comments section so i posted a working answer for you here
<?php
// here $usertimezone should be set = to what you have in your database
$usertimezone="Asia/Shanghai";
date_default_timezone_set('"'.$usertimezone.'"');
//new date and time
$ndate= new datetime();
//split into date and time seperate
$nndate =$ndate->format("Y-m-d");
$nntime= $ndate->format("H:i:S");
//here you can test it
echo $nndate;
echo $nntime;
?>
Use this function date_default_timezone_set for setting timezone, From this function you can set the timezone according to user and then get the required format.
Examples
<?php
date_default_timezone_set("new/timezone");//set the name of timezone here example Asia/Kokata
echo $date= date("Y-m-d H:i:s");

PHP file modified time use GMT offset setting to report correct time

I'm currently reporting file modified time like so:
$this->newScanData[$key]["modified"] = filemtime($path."/".$file);
$modifiedtime = date($date_format." ".$time_format, $this->newScanData[$key]["modified"]);
To me I thought there was nothing wrong with that but a user of my code is reporting the time being 4 hours out. The only reason why I can think of this is because the server is in a different timezone to the user. Each user has a variable I can use $gmt_offset that stores the time zone that user is in. $gmt_offset is stored as a basic float offset.
The server could be in any timezone, not necessarily in GMT-0. The server might not be in the same timezone as the user.
How do I get $modifiedtime to have the correct time for the user in his timezone based on $gmt_offset?
filemtime() will return a unix timestamp based on the server's clock. Since you have user to gmt offset available, you must convert the unix timestamp to GMT and then into user's timszone as follows:
<?php
list($temp_hh, $temp_mm) = explode(':', date('P'));
$gmt_offset_server = $temp_hh + $temp_mm / 60;
$gmt_offset_user = -7.0;
$timestamp = filemtime(__FILE__);
echo sprintf('
Time based on server time.........: %s
Time converted to GMT.............: %s
Time converted to user timezone...: %s
Auto calculated server timezone...: %s
',
date('Y-m-d h:i:s A', $timestamp),
date('Y-m-d h:i:s A', $timestamp - $gmt_offset_server * 3600),
date('Y-m-d h:i:s A', $timestamp - $gmt_offset_server * 3600 + $gmt_offset_user * 3600),
$gmt_offset_server
);
// Output based on server timezone = PKT (+05:00 GMT) and user timezone = PDT (-07:00 GMT)
// Time based on server time.........: 2011-06-09 03:54:38 PM
// Time converted to GMT.............: 2011-06-09 10:54:38 AM
// Time converted to user timezone...: 2011-06-09 03:54:38 AM
// Auto calculated server timezone...: 5
What you need is the strtotime() function. Changed date to gmdate, converting your servers time to GMT
For example if you need the time format like 10:00:00
gmdate("H:i:s", strtotime($gmt_offset . " hours"));
More info here:
http://php.net/manual/en/function.strtotime.php
http://php.net/manual/en/function.gmdate.php
$modifiedtime = date($date_format." ".$time_format, $this->newScanData[$key]["modified"] + ($gmt_offset * 3600));
$gmt_offset should be of type float, not int -- some time zones can have fractional difference, like GMT +09:30 for Adelaide

How to convert datetime to GMT in php

Alright, so i'm not sure if im converting user input time to GMT properly. I will be having users across several timezones entering "events" and they will have to be able to see "how long untill" or "how long since" the current time();
This is how I was planning to convert the time they input. It will start as something like 07/21/2011 01:30 am Then,
echo gmdate('Y-m-d H:i:s',strtotime('07/21/2011 01:30 am'));
gives me 2011-07-21 08:30:00
So I was planning to take the value of gmdate('Y-m-d H:i:s',strtotime('07/21/2011 01:30 am')); then take time() and display "how long until this event" to users. But it seems like there is always 10 hours added onto the result, so if if i was scheduling an event 30 min from now it would say 10 hours 30 min from now. So, im thinking im not converting the local time correctly or something.
What am I missing? Maybe I just dont properly understand GMT. How can I make sure all the times involved are GMT so all times are universal to all the users on the website?
Other info if it helps:
The server timezone is America/Los_Angeles
EDIT:
After everyones suggestions i've tried setting this at the top of my php code:
date_default_timezone_set("GMT");
and I tried using date('Y-m-d H:i:s') to do the comparison to figure out the diff, but its saying "3 hours ago" rather than the 10 hours from now. So this definately changed things.
But still not correct.
I've confirmed date('Y-m-d H:i:s') is returning the correct and current GMT. So thats good.
But the user input date is off. How am I converting it incorrectly?
EDIT AGAIN(including some test results after Salman A's suggestions):
2:55am - my current local time EST
date('Y-m-d H:i:s') shows up as 2011-07-21 06:56:43 - which is correct
3:00am EST is the time in the future I submitted as 07/21/2011 03:00 am
Here's how I get the time "convert it" and submit it to my DB:
$time = $_POST['time'];
//there is where im assuming it turns my EST time to the GMT equivalent.
$the_date = strtotime($time . ' GMT');
$utctime = gmdate('Y-m-d H:i:s',$the_date);
I'm expecting my function to tell me the event is 5 minutes from now, but its hours off.
just to make sure the user submitted time was actually converted to GMT i display $utctime and it shows up as 2011-07-21 03:00:00 - which is not 08:00 or 07:00 (which i think one of those would be the GMT equivalent)
So how do I convert it?
So, what im seeing is strtotime($time . ' GMT'); doesn't seem to be applying the GMT to the local time I supply. On a side note: somone suggested I have date_default_timezone_set("GMT"); in my code, so i have it at the top. Should I remove it? but i noticed if i remove it the GMT is incorrect. So thats why I left it.
If you simply need to calculate the difference between two time values:
<?php
$time = '07/21/2011 11:30 am';
$timeleft = strtotime($time) - time();
// target time....: 2011-07-21 11:30:00
// current time...: 2011-07-21 11:13:45
// difference.....: 975 seconds (16 min, 15 seconds)
The above example assumes that $time has same timezone as that used by the time() function i.e. the server's timezone.
If the timezones differ, you must normalize them in order for subtraction to work as expected. So for example if you're storing GMT date/time in your database then the above example becomes:
<?php
$time = '07/21/2011 06:30 am';
$timeleft = strtotime($time . ' GMT') - time();
// target time............: 2011-07-21 06:30:00 GMT
// converted local time...: 2011-07-21 11:30:00 PKT
// current time...........: 2011-07-21 11:34:48 PKT
// difference.............: -288 seconds (minus 4 minutes, 48 seconds)
Edit 1
Regarding this code:
$time = $_POST['time'];
If your users are from various parts of the world, you should either:
ask them to enter the date/time in GMT
ask them to enter a timezone for the date entered
You can later convert the date on server side and store it in database:
<?php
$source_time = '2011-07-21 17:00';
$source_offset = '-0700'; // PDT
$local_timestamp = strtotime($source_time . ' ' . $source_offset); // 2011-07-22 05:00 PKT (SERVER TIME)
list(
$temp_hh,
$temp_mm
) = explode(':', date('P')); // returns difference between SERVER TIME and GMT
$local_offset = $temp_hh * 3600 + $temp_mm * 60;
$gmt_timestamp = $local_timestamp + $local_offset;
echo date("Y-m-d H:i:s", $gmt_timestamp); // 2011-07-21 10:00:00
// THIS is what you store in your database
// Same as 2011-07-21 17:00:00 minus 7 hours
Without the timezone information your calculations will be unreliable.
Edit #2
Actually... it is much simpler:
<?php
$source_time = '2011-07-21 17:00';
$source_offset = -7.0; // -0700
echo date("Y-m-d H:i:s", strtotime($source_time) + $source_offset * 3600);
// 2011-07-21 10:00:00
// THIS is what you store in your database
Edit #3
<input type="text" name="time" id="time" value="07/21/2011 17:00">
<input type="text" name="offset" id="offset">
<script type="text/javascript">
document.getElementById("time").onchange = function(){
var d = new Date(this.value);
alert('Date entered: ' + d + '\nDate to GMT: ' + d.toUTCString());
}
document.getElementById("offset").value = (new Date()).getTimezoneOffset() / 60;
</script>
Demo here
A good idea is to explicitly set the timezone for your scripts. For example:
date_default_timezone_set('Europe/London');
This will make all date functions returns dates in GMT, and I believe accounting for BST too.
Hello I am living in Poland and we have a CET time.
To convert CET to GMT I am using function:
function convertCETtoGMT($timeCET)
{
date_default_timezone_set('EUROPE/London');
$time = $timeCET." CET";
$timeGMT = date('Y-m-d H:i:s', strtotime($time));
date_default_timezone_set('EUROPE/Warsaw'); //set back to CET
return $timeGMT;
}

time() and date() problems after time change (DST - standard)

In PHP I would like to output an HTML option list containing dates for the next 14 days.
These appointments are always at 18 o'clock:
$today_day = date('d');
$today_month = date('m');
$today_year = date('Y');
$date_entry = mktime(18, 00, 00, $today_month, $today_day, $today_year);
$optionsStr = '<select name="date">';
for ($d = 1; $d < 14; $d++) {
$date_entry_temp = $date_entry+86400*$d;
$optionsStr .= '<option value="'.$date_entry_temp.'">'.date('d.m.Y', $date_entry_temp).'</option>';
}
$optionsStr .= '</select>';
echo $optionsStr;
The user can then choose from one of these dates and submit the form. The chosen timestamp is then inserted into the database.
So I have some entries in my database.
On another page there is a list of current appointments:
mysql_query("SELECT id, name FROM appointments WHERE date_time = ".time());
So at 18 o'clock there should be some output as there are entries in the database for that day. This works perfectly good until the time changes from DST to standard time or vice versa. Then, indeed, is wrong:
The appointments are shown one hour too late or too early respectively.
How can I solve this problem?
mktime() creates a unix timestamp. A unix time stamp is the number of seconds from January 1, 1970, 00:00:00 GMT +0000. (Greenwich time)
When you set your timezone to "Europe/Berlin", the timezone is either GMT+0100 (in winter) or GMT+0200 (in summer). This means that the Greenwich time of your appointments changes by one hour when you have DST. That means that the time between the first appointment before the change and the next appointment after the change is not 24 hours, but 23 or 25. However, you generate the appointments by adding 86400 seconds = 24 hours.
You can use the DateTime object and the add() method instead. It takes DST changes into account.
// create a new date object with todays date
$date = new DateTime();
// set the time to 18:00
$date->setTime(18,0,0);
$optionsStr = '<select name="date">';
for ($i = 0; $i < 14; $i++) {
// add 1 day
$date->add(new DateInterval('P1D'));
$optionsStr .= '<option value="'.$date->format('U').'">'.$date->format('d.m.Y').'</option>';
}
$optionsStr .= '</select>';
echo $optionsStr;
See http://www.php.net/manual/en/datetime.add.php for more information.
Your main issue is that you're not working on GMT dates. Here's a colorful post that highlights the resulting pitfalls:
http://derickrethans.nl/storing-date-time-in-database.html
What you should be doing is, store your appointments datetimes at time zone UTC, compare datetimes at time zone UTC, and display datetimes to users in your (ok) or their (ideal) preferred time zone.
Seems you have a problem with timezones: http://dev.mysql.com/doc/refman/5.0/en/timestamp.html
I would get the time selected, convert from your local time to UTC and then put it in the database. If you read it out, convert back from UTC to your localtime.
When relying on the time, please make sure that you always SET A TIMEZONE, either in your php.ini or in your code. And there's not a whole lot you can do about your database entries, if you sort them by time or date they will end up being interleaved due to the new date being before the date of your last entry prior to the timechange.

check time for time difference in 24hr

In php i get the variable $date_time in this format -- 11-01-2010 20:48:25 . This time is GMT time. I have a 2 hour flexibility and if it exceeds 2 hours then i have to reject it. I am set in EST, but i want to do the check based on GMT only so that there is no errors in the time difference. How can i set to GMT in my php code and how do i check for the 2 hours flexible time difference? like for this example it is acceptable for any time between 11-01-2010 18:48:25 and 11-01-2010 22:48:25. Also will it be an issue if $date_time is 11-01-2010 23:48:23?
Clarification
I am doing a $date_time=$_GET['date_time'];. Then i need to check if this new $date_time if within 2 hours range of the current GMT time. if it is in the range, then i will proceed to execute that code, else i will show an error or do something else. I wanted to know how i am going to check this 2 hours range for this $date_time variable.
Here is a way how to convert your time format into a UNIX timestamp:
$date = strptime($date_time, "%m-%d-%Y %T");
$ut = mktime($date['tm_hour'], $date['tm_min'], $date['tm_sec'], 1 + $date['tm_mon'], $date['tm_mday'], 1900 + $date['tm_year']);
$now = time();
if($ut >= $now && $ut <= ($now + 7200)) { // 7200 = 2 * 60 * 60 seconds
// allowed
}
Reference: strptime, mktime, time.
Note: time() always returns the UNIX timestamp in UTC (regardless of time settings). So this assumes that the $date_time timestamp is a GMT time.
Working example (of course you have to provide a valid GMT time for $date_time).
Note 2: If the input time is not in GMT, you can set the timezone with date_default_timezone_set (affects mktime but not time).
Working example (change time and timezone accordingly)
If PHP >= 5.3 (you've got a seriously weird format BTW):
date_default_timezone_set('EST');
$inputtime = DateTime::createFromFormat('m-d-Y H:i:s','11-01-2010 20:48:25',new DateTimeZone("GMT"));
$diff = $inputtime->getTimestamp() - time();
if(abs($diff) > 7200){
//more then 2 hours difference.
}
If you run on PHP > 5.3, you can use DateTime for this :
$my_date = "11-01-2010 20:48:25";
$date = DateTime::createFromFormat('m-d-Y H:i:s', $my_date);
$date_lower = DateTime::createFromFormat('m-d-Y H:i:s', $my_date);
$date_upper = DateTime::createFromFormat('m-d-Y H:i:s', $my_date);
$date_lower->sub(new DateInterval('PT2H'));
$date_upper->add(new DateInterval('PT2H'));
var_dump($date >= $date_lower && $date <= $date_upper); // bool(true)
I find it more readable.
You can also use another timezone if necessary, check the third argument of createFromFormat.
I suggest you to never pass times and dates with format string. Just convert it later. You just pass the timestamp as a get variable and then you format it in the script.
It's the best solution and also the cleanest.
Then use the following code:
$flexibility = X seconds;
if ($date_time < time() - $flexibility or $date_time > time() + $flexibility)
{ /*Error*/ }

Categories