I'm building an application that shows specific times on a given day. This application is meant to serve ppl worldwide.
I do all the calculation with a TZ in an hour format (-4 / 2 / 9.5 / -1 ETC). (don't worry. the hour tz is after DST calculations)
Now, I would like to show the user his local time. due to dev reasons, i can use only the hour tz for this calculation.
after a lot of tries, i maneged to write a piece of code that seems to work. (tested it for few timezones, negetive and positive)
I am wondering if my code is ok? could i do it in a more efficent way? do this code support infinite date range?
here is the code:
static function current_local_time_zmanim($tz)
/*
* This function will get the number of hours off set (the time zone that Full_Zmanim_calculation() is using to make the calcukation) and will return the current local time and date.
*/ {
$tz= ($tz * 3600);// calculatoin: (hour offset(tz. can be -4 or 4) * 3600). eg: (-4*3600) or (3*3600)// converting the hour tz to TIMESTAMP
$date_utc = new DateTime(null, new DateTimeZone("UTC")); // current time in UTC.
$utctime= $date_utc->getTimestamp(); // current time in UTC TIMESTAMP
$date_utc->setTimestamp($utctime + ($tz));// keep in mind that tz can be either positive or negetive
$localtime= $date_utc->format('H:i');
echo "<br> local time: $localtime <br> ";
return $localtime;
}
What do you think?
Thanks!
Related
I am using Laravel 4 and trying to calculate the difference of the Time on Server and the Time Save in Database in hours. Here is the code:
Time on Server=timeNowOnServer // 2016-02-03 19:05:43
Time saved in Database = setTime // 18:00:00
$timeNowOnServer = null;
$setTime = null;
$timeZone = $company->time_zone;
$company->save();
// My Time
$hour = substr($company->emp_auto_logout_time, 0, 2);
$setTime = Carbon::createFromTime($hour);
// Server Time Same as Mine
$timeNowOnServer = Carbon::now();
$timeNowOnServerSameAsMine = $timeNowOnServer->setTimezone($timeZone);
// Time Differnce Between SetTime and TimeOnServerSameAsMine
$timeDiff = $setTime->diffInHours($timeNowOnServerSameAsMine, $abs = false);
If Server Time is 14:00:00 for example and Set Time is 19:00:00. My time zone is GMT +5 Pakistan.
What I'm doing is, adding setting Server Time according to user time by giving time zone in the 3rd last line of the above given code.
When I use diffInHour it instead of giving me 0 it gives me -5 or 5. It means it's useing UTC (Server Time) and that's why give wrong difference in hours.
Can someone please let me know where I'm wrong?
You're trying to diff time in different time zones. A time difference (interval) is an absolute value, it doesn't depend on time zone. One second is always one second, be it UTC or Europe/Moscow.
Try without time zone (to be correct - using default server's time zone)
$timeDiff = $setTime->diffInHours($timeNowOnServer, $abs = false);
Always calc intervals using timestamps or the same time zone (doesn't matter exactly which one) for both DT values.
I've been searching alot and I can't seem to find a solution.
I have a PHP web page where I can schedule email alerts at specific times. I select the date and time of when the alert is to be sent. This is stored in MySQL table in UNIX format. I have a job that executes every 15 minutes and sends the emails if the date+time is in the past - this all works perfectly except I need to extend it for my USA colleagues. I am based in Ireland so I will need to manage the different timezones all across the US. I am planning on adding a select list of timezones that the user will have to select once they register...at least thats a start. Managing timezones is fine because I reckon all I need to do is minus the time different from the server time and then save the date time in unix format. DST is a different issue tho - does anyone have any ideas on how to overcome this?
I have read that using UTC as the base time but even if that is the case wont I still have the same issue?
Thanks a mil!
Your times are already in UNIX timestamp format so all you need is to calculate time difference (offset) of user. For example Ireland is in UTC/UTC+1 timezone. So all you need is to do the math like james_t mentioned in his comment. If you need user from Ireland to get an email in 9:00pm UTC+1 you have to send it in 8:00pm UTC. So what's an idea?
Allow users to select timezone which means they select offset from UTC. Keep it somewhere in database (your users table or some other table, doesn't matter).
Convert offset in seconds:
$delta_time = -1 * $offset * 3600
Then calculate your trigger-time:
$trigger_time = time() + $delta_time;
Now you have time when your email sender can fire in right moment depending on user's timezone settings.
For example:
$offset = 1; // summer in Ireland
$server_time = time(); // at the moment 1350509127
$delta_time = -1 * $offset * 3600; // -3600
$trigger_time = $server_time + $delta_time; // 1350505527
All you need is to compare $trigger_time with UNIX timestamp from your database and decide to send an email (or not).
Ofc, it's not bad idea to use PHP timezones instead of pure +/- offset and stay updated when DST changes apply on certain locations.
Make some test, this is not that hard.
This is just a general idea, not complete working solution.
Update:
To calculate time-difference in seconds between any two timezones you can use something like this:
function delta_offset()
function delta_offset($server_timezone, $user_timezone) {
$dt = new DateTime('now', new DateTimeZone($server_timezone));
$offset_server = $dt->getOffset();
$dt->setTimezone(new DateTimeZone($user_timezone));
$offset_user = $dt->getOffset();
return $offset_user - $offset_server;
}
To get an offset in seconds:
$server_tz = "Europe/London";
$user_tz = "America/New_York";
$offset = delta_offset($server_tz, $user_tz); // offset in sec.
Create some output:
$dt = new DateTime('now', new DateTimeZone('UTC'));
echo "<pre>UTC date/time: " . $dt->format('l, F jS, <b>H:i:s</b>') . "\n";
$dt = new DateTime('now', new DateTimeZone($server_tz));
echo "London date/time: " . $dt->format('l, F jS, <b>H:i:s</b>') . "\n";
$dt = new DateTime('now', new DateTimeZone($user_tz));
echo "New York date/time: " . $dt->format('l, F jS, <b>H:i:s</b>') . "\n\n";
echo "Time difference between London (UK) and New York (USA) is: <b>$offset_h</b> ($offset s)</pre>";
Output in browser (in moment of writing this post):
UTC date/time: Wednesday, October 17th, 22:32:27
London date/time: Wednesday, October 17th, 23:32:27
New York date/time: Wednesday, October 17th, 18:32:27
Time difference between London (UK) and New York (USA) is: -5:00 (-18000 s)
In this case offset is -5 hours (-18000 seconds) but it automatically changes if DST rules change for any of timezones given as function-arguments.
Delta-offset provides information how much earlier or later you have to send an email to user in different timezone and all you need now is to do simple +/- delta-offset with your email-sender's scheduler.
Hope this may help you to get right solution for your problem.
Update #2 - Example (theory)
Imagine this situation.
Your current server-time is X and its 7:00pm at the moment in Ireland. I live in Serbia and we have same DST rules but I’m one hour after (UTC+1/UTC+2). Difference between your and my time is +3600 seconds (1 hour).
Now you have to send an email to me in 10:00pm (it’s 9:00pm in Ireland).
Current time is X.
Delta-offset is -1 * +3600 = -3600 (delta-offset multiplied with -1).
Sending time on your location in 10:00 pm is X + 10800 (3 hours later).
Sending time on my location in 10 pm is X + 10800 + delta-offset = X + 7200 (2 hours later).
Formula to check if actual time is equal or greater than trigger-time (sending time) is:
current_timestamp >= trigger_timestamp + delta_offset
where delta-offset from delta_offset() function must be multiplied with -1 to use in formula.
Now you can send email when you want and be sure it will be sent using user's local time (ofc, if user timezone settings are correct).
Note: Difference from this example (Serbia - Ireland = +1 hour) is different during DST changes which means that 1 hour every year we're in same timezone (0 delta-offset), and one hour we have +2 hours delta-offset. This is possible because DST changes are applied 1 hour earlier in Serbia so when our time is changed +1 you have to wait 60 minutes before same change applies to Ireland-time *then we're +2) and same thing when we bring back clock to normal time (0 difference).
We have a battle system where people can pick a match time to challenge another player. To create a match the user needs to pick a date. Currently a user picks the day, hour, minute, and pm/am from a dropdown list. If the user selects 5/20/2012 # 1PM, the system adds the hours and minutes from the start of the day. Here's a quick sample to get a better understanding of what I'm talking about:
$time = strtotime('today', $inputdate);
$time = $time + $hours + $minutes;
the value of $hours changes if the users selects AM or PM. It's pretty basic:
Everything was working fine until people started have timezone issues. For example, if player A creates a match at 1:PM, then player B will see the match starts at 1:PM, but he/she will have different timezones!
The problem is that I don't know the problem :/
I don't know how to fix the timezone issue. I have been creating functions in the hopes that everything will fall together, but no luck.
What I have:
User profiles have a timezone options.
A function that gets the raw timestamp and returns the formatted time based on the user's timezone.
A function that gets a timestamp and converts it to another timestamp
based on the user's timezone.
I'm lost and I can't seem to fix the issue, I can code, but right now I'm not thinking logical. I took me one hour to write this and try to explain it how I could, since I myself don't know how to make it work. Some advice is appreciated.
I need a function to convert a timestamp to UTC-5:
function input_date($timestamp)
{
global $vbulletin;
$timestamp = (int)$timestamp;
if (strlen((string)$timestamp) == 10)
{
$hour = 3600.00;
$offset = $vbulletin->userinfo['timezoneoffset'];//sample -8
$ds = (int)$vbulletin->userinfo['dstonoff'];//DST
$fluff = $hour*($offset+5.00);
$timestamp = $timestamp+$fluff+($ds*$hour);
return $timestamp;//return timestamp in UTC-5 format..
}
else
{
return 0;
}
}
Essentially everything in the database should be stored using a single timezone, preferably one which is not affected by DST. The standard option here is UTC.
If you know the user's timezone by its name, you can use that to generate your time:
// Player A creates match at 1PM Europe/London
$timezone = 'Europe/London';
$localTime = '2012-03-01 13:00:00';
// work out UNIX timestamp using that timezone (making it timezone independent)
date_default_timezone_set($timezone);
$timestamp = strtotime($localTime);
// store $timestamp in the database
// Player B views the timestamp with timezone America/Los_Angeles
$timezone = 'America/Los_Angeles';
date_default_timezone_set($timezone);
var_dump(date('c', $timestamp)); // see manual for more output formats
If you have the timezones stored as their abbreviations (e.g. "CET", "GMT"), then use timezone_name_from_abbr to get the correct timezone name.
I need to compare two dates to show an edit link if it is within 5 mins after the post was made, in PHP. If more than 5 minutes have passed, don't show anything.
$answer_post_date = get_the_time("Y-m-d");
$current_date = date("Y-m-d");
$formated_current_date = strtotime($answer_post_date);
$formated_answer_post_date = strtotime($current_date);
At this point I have two values:
1274414400 ($formated_current_date)
1276056000 ($formated_answer_post_date)
I am not sure what to do next to check if the current date/time is > 5 mins from the answer post date.
Any suggestions would be great.
All I really need the answer to be is a Boolean (yes/no) and if yes, display the minuets left to show the link to edit.
You're only handling dates, how are you supposed to know if the difference is 5 minutes?
Anyway, I'd say the majority of the PHP code that uses the default PHP functions is at least somewhat broken. The problem is you, despite a unix timestamp storing the correct point in time something happens, it does not store timezone information. See here.
So, forget using only date and strtotime. Use the datetime extension.
Store in the database the Unix timestamp and the timezone (by timezone I mean e.g. Europe/Lisbon). Then:
$tz = new DateTimeZone($timezone);
$answer_post_date = new DateTime("$timestamp");
$answer_post_date->setTimeZone($tz);
$current_date = new DateTime("now", $tz);
$diff = $current_date->diff($answer_post_date);
if ($diff->format("a") > 0 ||
$diff->format("h") > 0 ||
$diff->format("m") >= 5) {
//more than 5 minutes have passed
}
Of course, for comparing dates, you can always compare the timestamps.
My understanding of what you need to do:
$delta = ($formated_current_date - $formated_answer_post_date) / 60; // in minutes
if ($delta < 5) {
// show $delta
}
EDIT: Like others pointed out, this alone will not fix all of the issues at hand. As I see it, the smallest change to your current code would be to use a date format with higher granularity - such as "Y-m-d H:i:s". This being enough, like others pointed out, is contingent on the post's date being in the same timezone as your system.
I don't see the need to do a round-trip to a string format and back, regardless of how efficient or reliable it is.
date() will default to calling time() which you can call directly and get the current time in seconds as a Unix epoch timestamp (which is what you're trying to end up with in $formated_answer_post_date). You need to look in the WordPress docs to find the equivalent based on the post's value.
Then you can do a simple comparison of seconds. 5 minutes is 300 seconds.
You will still need to check that the code can assume the timezones of both values will be the same.
I'm writing a PHP system and I need to get the system time. Not the GMT time or the time specific to a timezone, but the same system time that is used by the CRON system. I have a CRON job that runs every day at midnight and I want to show on a webpage how long will it take before it runs again.
For example:
Right now it is 6pm on my system clock. I run the code:
$timeLeftUntilMidnight = date("H:i", strtotime("tomorrow") - strtotime("now"));
The result, however, is "3:00" instead of "6:00". If I run
date("H:i", strtotime("tomorrow"));
It returns 0:00, which is correct. But if I run
date("H:i", strtotime("now"));
It returns 21:00, even though the correct should be 18:00.
Thanks.
There are many answers, however there is not even one correct at the time of writing.
PHP time() function doesn't return the system time, like most folks believe, but it return the PHP localtime, normally set with date.timezone in php.ini, or set with date_default_timezone_set() within a script.
For instance in one of my servers, PHP time was set to Europe/Romeand system time to UTC. I had a difference of one hour between system time and PHP time.
I'm going to give you a solution that works for Linux, I don't know for Windows. In Linux the system timezone is set in /etc/timezone. Now, this is normally outside my allowed open_basedir setting, but you can add :/etc/timezone to your list to be able to read the file.
Then, on top of the scripts, that want to get the system time, you can call a library function that sets the script timezone to the system timezone. I suppose that this function is part of a class, so I use static:
static function setSystemTz() {
$systemTz = trim(file_get_contents("/etc/timezone"));
if ($systemTz == 'Etc/UTC') $systemTz = 'UTC';
date_default_timezone_set($systemTz);
}
To make the matter worse in PHP 5.3.3 'Etc/UTC' is not recognized, while 'UTC' is, so I had to add an if to fix that.
Now you can happily call time() and it will really give you the system time. I've tested it, because I needed it for myself, that's why I found this question now.
php's time will return the system time. you can format it with date
if you just want to display the time in the local time of the visitor maybe you're better off using a little javascript
This is the easiest and most foolproof way to do it:
$sys_timestamp = strtotime(exec("date"));
Let's not try to spoof it with php, let's just get the real sys time ;)
(Will work on any unix based system)
time()
will give you the current system timestamp.
Manual
Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).
You can get the date/time of the server on which PHP is running using the time() function -- it'll return a timestamp, that corresponds to the current datetime.
It's the system time, on that server -- the same as used by cron.
If you want the GMT time you may want to use gmtstrftime(), which will give you the system time but as in GMT. There's more info at http://us2.php.net/gmstrftime.
If you are after a formatted date:
date ('d/m/y h:i:s');
will do the trick, there is no need to pass time() into date as it will default to the current system time if no second parameter is supplied.
for more formatting options see here: http://php.net/manual/en/function.date.php
Otherwise you can just use
time()
To get you the current unix timestamp as others have mentioned.
For getting the current time of your system you need to set the correct date.timezone in your php.ini file. For example if you are from India then you would write:
date.timezone = Asia/Calcutta
For Germany, it would be:
date.timezone = Europe/Berlin
After doing this, date("Y-m-d H:i:s") will give your current time. For getting your timezone see the list of timezones supported by PHP.
try this one:
$time=date("h:i:s A", strtotime("now"-14));
echo $time;
You can adjust the time by changing the number 14 above.
You can current local time via below Javascript and set it in any PHP variable than.
<script>
// For 24 hours
var ct = new Date();
var hr = ct.getHours();
var mt = ct.getMinutes();
if (mt < 10) {
mt = "0" + mt;
}
document.write("<b>" + hr + ":" + mt + " " + "</b>");
// For 12 hours (AM / PM)
var ct = new Date();
var hr = ct.getHours();
var mt = ct.getMinutes();
var ampm = "AM";
if (hr >= 12) {
ampm = "PM";
hr = hr - 12;
}
if (hr == 0) {
hr = 12;
}
if (mt < 10) {
mt = "0" + mt;
}
document.write("<b>" + hr + ":" + mt + " " + ampm + "</b>");
</script>