Status QUERY_OVER_LIMIT received as response from google maps API v3 - google-maps

I am using your api in my application for several functionalities namely,
-- Get directions to a destination
-- Get distances to several locations
-- Receive location addresses by locating with markers on the map
Application summary (Local-Deals-Now)
The application is a free application to allow local businesses located in Australia, to publish offers/deals related to their business. A user can create a business account (free of charge) and give the location of their business (using google maps api) and add offers/deals to the system by dates and times. Public users/consumers can then view these offers (Or search by distance, location, date, keywords etc:-.... The distance to the offers from the current user location is calculated using distancematrix api).
The application stated above is currently in its development stages and can be accessed via http://www.chuli.fclhosting.com/ . The problem faced was when using the distance matrix APIs to calculate distances to the business from the current logged in user location. I am using the API on the server side as follows
$curl = curl_init();
$uri = "http://maps.googleapis.com/maps/api/distancematrix/json?origins=".$originString."&destinations=".$destinationsString."&mode=driving&language&sensor=false";
die($uri);
$options = array(
CURLOPT_URL => $uri,
CURLOPT_HTTPHEADER => array(),
CURLOPT_COOKIE => '',
CURLOPT_RETURNTRANSFER => true
);
curl_setopt_array($curl, $options);
$responseBody = curl_exec($curl);
$responseHeaders = curl_getinfo($curl);
$data = $responseBody;
$responseContentType = $responseHeaders['content_type'];
if ((strpos($responseContentType, 'json') !== false) || (substr(html_entity_decode(trim($data)), 0, 1) == "{")) {
$jsonData = json_decode($data, true);
if (!is_null($jsonData)) {
$data =$jsonData;
}
}
for ($i = 0; $i < count($data['origin_addresses']); $i++) {
for ($j = 0; $j < count($data['destination_addresses']); $j++) {
$from = $data['origin_addresses'][$i];
$to = $data['destination_addresses'][$j];
if($data['rows'][$i]['elements'][$j]['status']=="OK" && $data['rows'][$i]['elements'][$j]['distance']['value']<= ($distance*1000)) {
$businessDistanceArray[$businesses[$j]->getId()] = $data['rows'][$i]['elements'][$j]['distance']['text'];
} else {
$businessDistanceArray[$businesses[$j]->getId()] = sfConfig::get('app_offer_not_applicable');
}
}
}
Since recently i have started receiving a warning/error stating OVER_QUERY_LIMIT. After googling on the problem (reference : https://developers.google.com/maps/documentation/javascript/usage) i have grasped that , the above problem occurs either if
--the request limit per day exceeds 25 000 map loads
OR
--by sending too many requests per second
The application as to my knowledge doe not fulfill either one of the above requirements but, still received the warning. Please let me know what i could do regarding this problem in order to overcome this error
Do i have to purchase a business license
OR
Since currently the application is a non profitable one should i apply for a Google Earth Outeach Grant
OR
Just continue without any changes
Here is a sample request sent:
http://maps.google.com/maps/api/distancematrix/json?origins=-25.198526444487587,133.20029780312507&destinations=-33.767636351789754,147.41606950000005|-33.905755787445024,151.15402221679688|-32.02195365825273,115.90862329062497|-37.79805567326585,145.01495173583987|-36.8839206402564,144.20859858437507|-31.362071510290537,117.42054612812501|-23.609959,143.72078599999998|-37.819317,145.12404889999993|-37.8186394,145.12360620000004|-37.816506,145.11867699999993|-37.815524,145.12131499999998|-30.708111,134.56642599999998&mode=driving&language&sensor=false
Please look into the info given above. Your feedback would thoroughly appreciated by us
Thanks in advance

There are two different limits like Dr.Molle says. You exceeded the daily limit which allows 2500 elements to be queried in a 24 hour period of time. When this happens you'll get continuous OVER_QUERY_LIMIT errors until that 24 hour time window expires and your quota refreshes.
The other limit to be on the lookout for is the short term limit of 100 elements every 10 seconds. When you exceed this limit you'll experience the OVER_QUERY_LIMIT error for a few seconds (i.e. until the 10 second window is up) and then you'll be able to use the service again.
If this is a user-facing application that loads the Google Maps JavaScript API and performs these distance matrix queries as a result of some user action the JavaScript Distance Matrix Service is definitely worth exploring. Limits from the JavaScript application are distributed among your website users, not the back-end server.

The Limit for the DistanceMatrix-Service is different:
100 elements per query.
100 elements per 10 seconds.
2 500 elements per 24 hour period.
So please check first, how many origins/destinations you request. When origins*destinations is more than 100, you should have reached the limit for a query and 10 seconds.
In this case(assuming you have only 1 origin), how many "businesses" do you request?
Edit:
As the request did not exceed the limit for queries/10 seconds, it may be that you repeatedly pass the daily-limit. Your request returns 12 elements, so you will exceed the limit with around 200 requests in 24hours, could this happen?

You might be flagged as passing one or other limit if you are sharing hosting with others who are also using the service. Sharing a server may well mean sharing the limits on the service.

Related

Messages between agents in Anylogic GIS environment

In the Anylogic GIS environment, I want to send a message to the agents that are close to the agent that sends the message.
Is it possible to send a message to more than one agent within a certain distance in a GIS environment?
Thanks,
I used send("msg", this.getNearestAgent(agents)); but it only sends the message to the one nearest agent and not the nearest ones.
You will need to create your own function for this. I created the following one with the agent type called MyAgent so replace MyAgent with whatever Agent Type you are using:
for( MyAgent m : myAgents ) {
if( agent.distanceTo(m) < 1000000 && agent != m ) {
send("msg", m);
}
}
Note that distanceTo returns a distance in meters. I also the second condition in the if statement to make sure the agent doesn't send a message to itself. Finally, make sure to add an argument to your function as shown below.

How can i use Zabbix Monitoring tool API to fetch all alerts for last 15 mins

I am using zabbix for infrastructure monitoring. I want to export alerts real time to a centralized platform like splunk, ELK?
Can i pull all active alerts for last 15 mins using Zabbix API
ALso, is the api mature enough to implement auto close functionality?
Thanks in Advance !!!!
You should use the problem.get api:
This method is for retrieving unresolved problems. It is also
possible, if specified, to additionally retrieve recently resolved
problems.
A small python sample:
from zabbix.api import ZabbixAPI
zabbixServer = 'http://yourserver/zabbix/'
zabbixUser = 'someuser'
zabbixPass = 'somepass'
zapi = ZabbixAPI(url=zabbixServer, user=zabbixUser, password=zabbixPass)
problems = zapi.problem.get()
for problem in problems:
trigger = zapi.trigger.get (triggerids=problem['objectid'], selectHosts='extend')
interface = zapi.hostinterface.get(hostids=trigger[0]['hosts'][0]['hostid'])
group = zapi.hostgroup.get(hostids=trigger[0]['hosts'][0]['hostid'])
enabled = "Enabled"
if (trigger[0]['hosts'][0]['status'] == "1"):
enabled = "Disabled"
print "Group:{}; Host:{}; IP:{}; Problem:{}; {}".format(group[1]['name'],
trigger[0]['hosts'][0]['host'],
interface[0]['ip'],
trigger[0]['description'],
enabled )

Pagination yields no results in Google Fit

I am using the REST API of Google Fit. I want to list sessions with the fitness.users.sessions.list method. This gives me a few dozen of results.
Now I would like to get more results and for this I set the pageToken to the value I got from the previous response. But the new results does not contain any data points, just yet another pageToken:
{
"session": [
],
"deletedSession": [
],
"nextPageToken": "1541027616563"
}
The same happens when I use the pagination function of the Google Python API Client: I iterate on results but never get any new data.
request = self.service.users().sessions().list(userId='me')
while request is not None:
response = request.execute()
for ds in response['session']:
yield ds
request = self.service.users().sessions().list_next(request, response)
I am sure there is much(!) more session data in Google Fit for my account. Am I missing something regarding pagination?
Thanks
I think that the description of the pageToken parameter is actually rather confusing in the documentation (this answer was written prior to the documentation being updated).
The continuation token, which is used to page through large result sets. To get the next page of results, set this parameter to the value of nextPageToken from the previous response.
This is conflating two concepts: continuation, and paging. There isn't actually any paging in the implementation of Users.sessions.
Sessions are indexed by their modification timestamp. There are two (or three, depending on how you count) ways to interact with the API:
Pass a start and/or end time. Omitted start and end times are taken to be the start and end of time respectively. In this case, you will get back all sessions falling between those times.
Pass neither start nor end times. In this case, you will receive all sessions between some time in the past and now. That time is:
pageToken, if provided
Otherwise, it's 7 days ago (this doesn't actually appear in the documentation, but it is the behavior)
In any of these cases, you receive a nextPageToken back which is just after the most recent session in the results. As such, nextPageToken is really a continuation token, because what it is saying is that you have been told about all sessions modified up to now: pass that token back to be told about anything modified between nextPageToken and "current time" to get updates.
As such, if you issue a request that fetches all sessions for the last 7 days (no start/end time, no page token) and get a nextPageToken, you will only get something back in a request using that nextPageToken if any sessions have been modified in between the first and second requests.
So, if you're making these requests in quick succession, it is expected that you won't see anything in the second response.
In terms of the validity of the startTime you were passing in your comment, that's a bug. RFC3339 defines that fractional seconds should be optional.
I'll see about getting that fixed; but in the interim, just make sure you pass a fractional number of seconds (even if it is just .0, e.g. 2018-10-18T00:00:00.0+00:00).
It may be because the format of the URL you're using is different from the example in the documentation.
You are using:
startTime=2018-10-18T00:00:00+00:00
Wherein the one in the documentation has it as:
startTime=2014-04-01T00:00:00.00Z
The documentation also stated that both startTime and endTime query parameters are required.

CakePHP - How to paging with json data?

I'm training with CakePHP. Currently I have a problem.
I don't know how to paging with json data.
My application will call to API and receive JSON data.
The format look like
{"success":1,"films":[{"film_id":"384","title":"GROSSE WONDERFUL","description":"A Epic Drama of a Cat And a Explorer who must Redeem a Moose in Australia","release_year":"2006","language_id":"1","original_language_id":null,"rental_duration":"5","rental_rate":"4.99","length":"49","replacement_cost":"19.99","rating":"R","special_features":"Behind the Scenes","last_update":"2006-02-15 05:03:42"},{"film_id":"984","title":"WONDERFUL DROP","description":"A Boring Panorama of a Woman And a Madman who must Overcome a Butler in A U-Boat","release_year":"2006","language_id":"1","original_language_id":null,"rental_duration":"3","rental_rate":"2.99","length":"126","replacement_cost":"20.99","rating":"NC-17","special_features":"Commentaries","last_update":"2006-02-15 05:03:42"}]}
This is php code
$data = array('filmId' => $search_data['filmId'], 'filmTitle' => $search_data['filmTitle'], 'releaseYear' => $search_data['releaseYear'], 'rating' => $search_data['rating']);
$HttpSocket = new HttpSocket();
$records = $HttpSocket->post($apiFilmsByConditions, $data);
$records = json_decode($records, true);
I try to use paginate of CakePHP but it seems that this will get data from database, not from API.
This is API link http://oxuhandmade.com/api/get_all_films.php
Can you help me on this case?
Doesn't the API query the database? An API is an "Application programming interface", meaning that it allows you to operate on the database from the "outside", based on a simple interface, triggered by some requests. So there is no point in wanting to limit the results via API, but not via database.
To limit the results an API returns, you need to pass a parameter together with your request, process it in the backend, query the database with the desired limit, and return the results to whoever made the request. Or simply hardcode the desired limit on the API, if it doesn't need to be dynamic.
The Paginator from CakePHP makes this work a whole lot easier, you only have to feed it some conditions and parameters for paginating the results, and it does the magic for you.

Determine a user's timezone

Is there a standard way for a web server to be able to determine a user's timezone within a web page?
Perhaps from an HTTP header or part of the user-agent string?
-new Date().getTimezoneOffset()/60;
The method getTimezoneOffset() will subtract your time from GMT and return the number of minutes. So if you live in GMT-8, it will return 480.
To put this into hours, divide by 60. Also, notice that the sign is the opposite of what you need - it's calculating GMT's offset from your time zone, not your time zone's offset from GMT. To fix this, simply multiply by -1.
Also note that w3school says:
The returned value is not a constant, because of the practice of using
Daylight Saving Time.
The most popular (==standard?) way of determining the time zone I've seen around is simply asking the users themselves. If your website requires subscription, this could be saved in the users' profile data. For anon users, the dates could be displayed as UTC or GMT or some such.
I'm not trying to be a smart aleck. It's just that sometimes some problems have finer solutions outside of any programming context.
There are no HTTP headers that will report the clients timezone so far although it has been suggested to include it in the HTTP specification.
If it was me, I would probably try to fetch the timezone using clientside JavaScript and then submit it to the server using Ajax or something.
First, understand that time zone detection in JavaScript is imperfect. You can get the local time zone offset for a particular date and time using getTimezoneOffset on an instance of the Date object, but that's not quite the same as a full IANA time zone like America/Los_Angeles.
There are some options that can work though:
Most modern browsers support IANA time zones in their implementation of the ECMAScript Internationalization API, so you can do this:
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tzid);
The result is a string containing the IANA time zone setting of the computer where the code is running.
Supported environments are listed in the Intl compatibility table. Expand the DateTimeFormat section, and look at the feature named resolvedOptions().timeZone defaults to the host environment.
Some libraries, such as Luxon use this API to determine the time zone through functions like luxon.Settings.defaultZoneName.
If you need to support an wider set of environments, such as older web browsers, you can use a library to make an educated guess at the time zone. They work by first trying the Intl API if it's available, and when it's not available, they interrogate the getTimezoneOffset function of the Date object, for several different points in time, using the results to choose an appropriate time zone from an internal data set.
Both jsTimezoneDetect and moment-timezone have this functionality.
// using jsTimeZoneDetect
var tzid = jstz.determine().name();
// using moment-timezone
var tzid = moment.tz.guess();
In both cases, the result can only be thought of as a guess. The guess may be correct in many cases, but not all of them.
Additionally, these libraries have to be periodically updated to counteract the fact that many older JavaScript implementations are only aware of the current daylight saving time rule for their local time zone. More details on that here.
Ultimately, a better approach is to actually ask your user for their time zone. Provide a setting that they can change. You can use one of the above options to choose a default setting, but don't make it impossible to deviate from that in your app.
There's also the entirely different approach of not relying on the time zone setting of the user's computer at all. Instead, if you can gather latitude and longitude coordinates, you can resolve those to a time zone using one of these methods. This works well on mobile devices.
JavaScript is the easiest way to get the client's local time. I would suggest using an XMLHttpRequest to send back the local time, and if that fails, fall back to the timezone detected based on their IP address.
As far as geolocation, I've used MaxMind GeoIP on several projects and it works well, though I'm not sure if they provide timezone data. It's a service you pay for and they provide monthly updates to your database. They provide wrappers in several web languages.
Here is a robust JavaScript solution to determine the time zone the browser is in.
>>> var timezone = jstz.determine();
>>> timezone.name();
"Europe/London"
https://github.com/pellepim/jstimezonedetect
Here is a more complete way.
Get the timezone offset for the user
Test some days on daylight saving boundaries to determine if they are in a zone that uses daylight saving.
An excerpt is below:
function TimezoneDetect(){
var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear());
var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt
var intMonth;
var intHoursUtc;
var intHours;
var intDaysMultiplyBy;
// Go through each month to find the lowest offset to account for DST
for (intMonth=0;intMonth < 12;intMonth++){
//go to the next month
dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);
// To ignore daylight saving time look for the lowest offset.
// Since, during DST, the clock moves forward, it'll be a bigger number.
if (intOffset > (dtDate.getTimezoneOffset() * (-1))){
intOffset = (dtDate.getTimezoneOffset() * (-1));
}
}
return intOffset;
}
Getting TZ and DST from JS (via Way Back Machine)
Using Unkwntech's approach, I wrote a function using jQuery and PHP. This is tested and does work!
On the PHP page where you want to have the timezone as a variable, have this snippet of code somewhere near the top of the page:
<?php
session_start();
$timezone = $_SESSION['time'];
?>
This will read the session variable "time", which we are now about to create.
On the same page, in the <head>, you need to first of all include jQuery:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
Also in the <head>, below the jQuery, paste this:
<script type="text/javascript">
$(document).ready(function() {
if("<?php echo $timezone; ?>".length==0){
var visitortime = new Date();
var visitortimezone = "GMT " + -visitortime.getTimezoneOffset()/60;
$.ajax({
type: "GET",
url: "http://example.org/timezone.php",
data: 'time='+ visitortimezone,
success: function(){
location.reload();
}
});
}
});
</script>
You may or may not have noticed, but you need to change the URL to your actual domain.
One last thing. You are probably wondering what the heck timezone.php is. Well, it is simply this:
(create a new file called timezone.php and point to it with the above URL)
<?php
session_start();
$_SESSION['time'] = $_GET['time'];
?>
If this works correctly, it will first load the page, execute the JavaScript, and reload the page. You will then be able to read the $timezone variable and use it to your pleasure! It returns the current UTC/GMT time zone offset (GMT -7) or whatever timezone you are in.
To submit the timezone offset as an HTTP header on AJAX requests with jQuery
$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60);
}
});
You can also do something similar to get the actual time zone name by using moment.tz.guess(); from http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/
I still have not seen a detailed answer here that gets the time zone. You shouldn't need to geocode by IP address or use PHP (lol) or incorrectly guess from an offset.
Firstly a time zone is not just an offset from GMT. It is an area of land in which the time rules are set by local standards. Some countries have daylight savings, and will switch on DST at differing times. It's usually important to get the actual zone, not just the current offset.
If you intend to store this timezone, for instance in user preferences you want the zone and not just the offset. For realtime conversions it won't matter much.
Now, to get the time zone with javascript you can use this:
>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.
However I found it easier to simply use this robust plugin which returns the Olsen formatted timezone:
https://github.com/scottwater/jquery.detect_timezone
With the PHP date function you will get the date time of server on which the site is located. The only way to get the user time is to use JavaScript.
But I suggest you to, if your site has registration required then the best way is to ask the user while to have registration as a compulsory field. You can list various time zones in the register page and save that in the database. After this, if the user logs in to the site then you can set the default time zone for that session as per the users’ selected time zone.
You can set any specific time zone using the PHP function date_default_timezone_set. This sets the specified time zone for users.
Basically the users’ time zone is goes to the client side, so we must use JavaScript for this.
Below is the script to get users’ time zone using PHP and JavaScript.
<?php
#http://www.php.net/manual/en/timezones.php List of Time Zones
function showclienttime()
{
if(!isset($_COOKIE['GMT_bias']))
{
?>
<script type="text/javascript">
var Cookies = {};
Cookies.create = function (name, value, days) {
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toGMTString();
}
else {
var expires = "";
}
document.cookie = name + "=" + value + expires + "; path=/";
this[name] = value;
}
var now = new Date();
Cookies.create("GMT_bias",now.getTimezoneOffset(),1);
window.location = "<?php echo $_SERVER['PHP_SELF'];?>";
</script>
<?php
}
else {
$fct_clientbias = $_COOKIE['GMT_bias'];
}
$fct_servertimedata = gettimeofday();
$fct_servertime = $fct_servertimedata['sec'];
$fct_serverbias = $fct_servertimedata['minuteswest'];
$fct_totalbias = $fct_serverbias – $fct_clientbias;
$fct_totalbias = $fct_totalbias * 60;
$fct_clienttimestamp = $fct_servertime + $fct_totalbias;
$fct_time = time();
$fct_year = strftime("%Y", $fct_clienttimestamp);
$fct_month = strftime("%B", $fct_clienttimestamp);
$fct_day = strftime("%d", $fct_clienttimestamp);
$fct_hour = strftime("%I", $fct_clienttimestamp);
$fct_minute = strftime("%M", $fct_clienttimestamp);
$fct_second = strftime("%S", $fct_clienttimestamp);
$fct_am_pm = strftime("%p", $fct_clienttimestamp);
echo $fct_day.", ".$fct_month." ".$fct_year." ( ".$fct_hour.":".$fct_minute.":".$fct_second." ".$fct_am_pm." )";
}
showclienttime();
?>
But as per my point of view, it’s better to ask to the users if registration is mandatory in your project.
Don't use the IP address to definitively determine location (and hence timezone)-- that's because with NAT, proxies (increasingly popular), and VPNs, IP addresses do not necessarily realistically reflect the user's actual location, but the location at which the servers implementing those protocols reside.
Similar to how US area codes are no longer useful for locating a telephone user, given the popularity of number portability.
IP address and other techniques shown above are useful for suggesting a default that the user can adjust/correct.
JavaScript:
function maketimus(timestampz)
{
var linktime = new Date(timestampz * 1000);
var linkday = linktime.getDate();
var freakingmonths = new Array();
freakingmonths[0] = "jan";
freakingmonths[1] = "feb";
freakingmonths[2] = "mar";
freakingmonths[3] = "apr";
freakingmonths[4] = "may";
freakingmonths[5] = "jun";
freakingmonths[6] = "jul";
freakingmonths[7] = "aug";
freakingmonths[8] = "sep";
freakingmonths[9] = "oct";
freakingmonths[10] = "nov";
freakingmonths[11] = "dec";
var linkmonthnum = linktime.getMonth();
var linkmonth = freakingmonths[linkmonthnum];
var linkyear = linktime.getFullYear();
var linkhour = linktime.getHours();
var linkminute = linktime.getMinutes();
if (linkminute < 10)
{
linkminute = "0" + linkminute;
}
var fomratedtime = linkday + linkmonth + linkyear + " " +
linkhour + ":" + linkminute + "h";
return fomratedtime;
}
Simply provide your times in Unix timestamp format to this function; JavaScript already knows the timezone of the user.
Like this:
PHP:
echo '<script type="text/javascript">
var eltimio = maketimus('.$unix_timestamp_ofshiz.');
document.write(eltimio);
</script><noscript>pls enable javascript</noscript>';
This will always show the times correctly based on the timezone the person has set on his/her computer clock. There is no need to ask anything to anyone and save it into places, thank god!
Easy, just use the JavaScript getTimezoneOffset function like so:
-new Date().getTimezoneOffset()/60;
All the magic seems to be in
visitortime.getTimezoneOffset()
That's cool, I didn't know about that. Does it work in Internet Explorer etc? From there you should be able to use JavaScript to Ajax, set cookies whatever. I'd probably go the cookie route myself.
You'll need to allow the user to change it though. We tried to use geo-location (via maxmind) to do this a while ago, and it was wrong enough to make it not worth doing. So we just let the user set it in their profile, and show a notice to users who haven't set theirs yet.
If you happen to be using OpenID for authentication, Simple Registration Extension would solve the problem for authenticated users (You'll need to convert from tz to numeric).
Another option would be to infer the time zone from the user agent's country preference. This is a somewhat crude method (won't work for en-US), but makes a good approximation.
Here is an article (with source code) that explains how to determine and use localized time in an ASP.NET (VB.NET, C#) application:
It's About Time
In short, the described approach relies on the JavaScript getTimezoneOffset function, which returns the value that is saved in the session cookie and used by code-behind to adjust time values between GMT and local time. The nice thing is that the user does not need to specify the time zone (the code does it automatically). There is more involved (this is why I link to the article), but provided code makes it really easy to use. I suspect that you can convert the logic to PHP and other languages (as long as you understand ASP.NET).
It is simple with JavaScript and PHP:
Even though the user can mess with his/her internal clock and/or timezone, the best way I found so far, to get the offset, remains new Date().getTimezoneOffset();. It's non-invasive, doesn't give head-aches and eliminates the need to rely on third parties.
Say I have a table, users, that contains a field date_created int(13), for storing Unix timestamps;
Assuming a client creates a new account, data is received by post, and I need to insert/update the date_created column with the client's Unix timestamp, not the server's.
Since the timezoneOffset is needed at the time of insert/update, it is passed as an extra $_POST element when the client submits the form, thus eliminating the need to store it in sessions and/or cookies, and no additional server hits either.
var off = (-new Date().getTimezoneOffset()/60).toString();//note the '-' in front which makes it return positive for negative offsets and negative for positive offsets
var tzo = off == '0' ? 'GMT' : off.indexOf('-') > -1 ? 'GMT'+off : 'GMT+'+off;
Say the server receives tzo as $_POST['tzo'];
$ts = new DateTime('now', new DateTimeZone($_POST['tzo']);
$user_time = $ts->format("F j, Y, g:i a");//will return the users current time in readable format, regardless of whether date_default_timezone() is set or not.
$user_timestamp = strtotime($user_time);
Insert/update date_created=$user_timestamp.
When retrieving the date_created, you can convert the timestamp like so:
$date_created = // Get from the database
$created = date("F j, Y, g:i a",$date_created); // Return it to the user or whatever
Now, this example may fit one's needs, when it comes to inserting a first timestamp... When it comes to an additional timestamp, or table, you may want to consider inserting the tzo value into the users table for future reference, or setting it as session or as a cookie.
P.S. BUT what if the user travels and switches timezones. Logs in at GMT+4, travels fast to GMT-1 and logs in again. Last login would be in the future.
I think... we think too much.
You could do it on the client with moment-timezone and send the value to server; sample usage:
> moment.tz.guess()
"America/Asuncion"
Getting a valid TZ Database timezone name in PHP is a two-step process:
With JavaScript, get timezone offset in minutes through getTimezoneOffset. This offset will be positive if the local timezone is behind UTC and negative if it is ahead. So you must add an opposite sign to the offset.
var timezone_offset_minutes = new Date().getTimezoneOffset();
timezone_offset_minutes = timezone_offset_minutes == 0 ? 0 : -timezone_offset_minutes;
Pass this offset to PHP.
In PHP convert this offset into a valid timezone name with timezone_name_from_abbr function.
// Just an example.
$timezone_offset_minutes = -360; // $_GET['timezone_offset_minutes']
// Convert minutes to seconds
$timezone_name = timezone_name_from_abbr("", $timezone_offset_minutes*60, false);
// America/Chicago
echo $timezone_name;</code></pre>
I've written a blog post on it: How to Detect User Timezone in PHP. It also contains a demo.
Try this PHP code:
<?php
$ip = $_SERVER['REMOTE_ADDR'];
$json = file_get_contents("http://api.easyjquery.com/ips/?ip=" . $ip . "&full=true");
$json = json_decode($json,true);
$timezone = $json['LocalTimeZone'];
?>
A simple way to do it is by using:
new Date().getTimezoneOffset();
Here's how I do it. This will set the PHP default timezone to the user's local timezone. Just paste the following on the top of all your pages:
<?php
session_start();
if(!isset($_SESSION['timezone']))
{
if(!isset($_REQUEST['offset']))
{
?>
<script>
var d = new Date()
var offset= -d.getTimezoneOffset()/60;
location.href = "<?php echo $_SERVER['PHP_SELF']; ?>?offset="+offset;
</script>
<?php
}
else
{
$zonelist = array('Kwajalein' => -12.00, 'Pacific/Midway' => -11.00, 'Pacific/Honolulu' => -10.00, 'America/Anchorage' => -9.00, 'America/Los_Angeles' => -8.00, 'America/Denver' => -7.00, 'America/Tegucigalpa' => -6.00, 'America/New_York' => -5.00, 'America/Caracas' => -4.30, 'America/Halifax' => -4.00, 'America/St_Johns' => -3.30, 'America/Argentina/Buenos_Aires' => -3.00, 'America/Sao_Paulo' => -3.00, 'Atlantic/South_Georgia' => -2.00, 'Atlantic/Azores' => -1.00, 'Europe/Dublin' => 0, 'Europe/Belgrade' => 1.00, 'Europe/Minsk' => 2.00, 'Asia/Kuwait' => 3.00, 'Asia/Tehran' => 3.30, 'Asia/Muscat' => 4.00, 'Asia/Yekaterinburg' => 5.00, 'Asia/Kolkata' => 5.30, 'Asia/Katmandu' => 5.45, 'Asia/Dhaka' => 6.00, 'Asia/Rangoon' => 6.30, 'Asia/Krasnoyarsk' => 7.00, 'Asia/Brunei' => 8.00, 'Asia/Seoul' => 9.00, 'Australia/Darwin' => 9.30, 'Australia/Canberra' => 10.00, 'Asia/Magadan' => 11.00, 'Pacific/Fiji' => 12.00, 'Pacific/Tongatapu' => 13.00);
$index = array_keys($zonelist, $_REQUEST['offset']);
$_SESSION['timezone'] = $index[0];
}
}
date_default_timezone_set($_SESSION['timezone']);
//rest of your code goes here
?>
One possible option is to use the Date header field, which is defined in RFC 7231 and is supposed to include the timezone. Of course, it is not guaranteed that the value is really the client's timezone, but it can be a convenient starting point.
There can be a few ways to determine the timezone in the browser. If there is a standard function that is available and supported by your browser, that is what you should use. Below are three ways to get the same information in different formats. Avoid using non-standard solutions that make any guesses based on certain assumptions or hard coded lists of zones though they may be helpful if nothing else can be done.
Once you have this info, you can pass this as a non-standard request header to server and use it there. If you also need the timezone offset, you can also pass it to server in headers or in request payload which can be retrieved with dateObj.getTimezoneOffset().
Use Intl API to get the Olson format (Standard and recommended way): Note that this is not supported by all browsers. Refer this link for details on browser support for this.
This API let's you get the timezone in Olson format i.e., something like Asia/Kolkata, America/New_York etc.
Intl.DateTimeFormat().resolvedOptions().timeZone
Use Date object to get the long format such as India Standard Time, Eastern Standard Time etc: This is supported by all browsers.
let dateObj = new Date(2021, 11, 25, 09, 30, 00);
//then
dateObj.toString()
//yields
Sat Dec 25 2021 09:30:00 GMT+0530 (India Standard Time) //I am located in India (IST)
Notice the string contains timezone info in long and short formats. You can now use regex to get this info out:
let longZoneRegex = /\((.+)\)/;
dateObj.toString().match(longZoneRegex);
//yields
['(India Standard Time)', 'India Standard Time', index: 34, input: 'Sat Dec 25 2021 09:30:00 GMT+0530 (India Standard Time)', groups: undefined]
//Note that output is an array so use output[1] to get the timezone name.
Use Date object to get the short format such as GMT+0530, GMT-0500 etc: This is supported by all browsers.
Similarly, you can get the short format out too:
let shortZoneRegex = /GMT[+-]\d{1,4}/;
dateObj.toString().match(shortZoneRegex);
//yields
['GMT+0530', index: 25, input: 'Sat Dec 25 2021 09:30:00 GMT+0530 (India Standard Time)', groups: undefined]
//Note that output is an array so use output[0] to get the timezone name.
There's no such way to figure the timezone in the actual HTML code or any user-agent string, but what you can do is make a basic function getting it using JavaScript.
I don't know how to code with JavaScript yet so my function might take time to make.
However, you can try to get the actual timezone also using JavaScript with the getTzimezoneOffset() function in the Date section or simply new Date().getTimezoneOffset();.
I think that #Matt Johnson-Pints is by far the best and a CanIuse search reveals that now it is widely adopted:
https://caniuse.com/?search=Intl.DateTimeFormat().resolvedOptions().timeZone
One of the challenges though is to consider why you want to know the Timezone. Because I think one of the things most people have missed is that they can change! If a user travels with his laptop from Europe to America if you had previously stored it in a database their timezone is now incorrect (even if the user never actually updates their devices timezone). This is also the problem with #Mads Kristiansen answer as well because users travel - you cannot rely on it as a given.
For example, my Linux laptop has "automatic timezone" turned off. Whilst the time might update my timezone doesn't.
So I believe the answer is - what do you need it for? Client side certainly seems to give an easier way to ascertain it, but both client and server side code will depend on either the user updating their timezone or it updating automatically. I might of course be wrong.