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.
Related
I need to know what time zone is currently my users are in based on their IP or http header.
I got many answer regarding this issue, but i could not understood those answer. Some said use -new Date().getTimezoneOffset()/60 (from here). But what does it mean?
I have a date_default_timezone_set("Asia/Calcutta"); in the root of my (index.php) page. So for this I have to get the timezone dynamically and set it in place of Asia/Calcutta.
To summarize Matt Johnson's answer in terms of code:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js">
</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.4/jstz.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
var tz = jstz.determine(); // Determines the time zone of the browser client
var timezone = tz.name(); //For e.g.:"Asia/Kolkata" for the Indian Time.
$.post("url-to-function-that-handles-time-zone", {tz: timezone}, function(data) {
//Preocess the timezone in the controller function and get
//the confirmation value here. On success, refresh the page.
});
});
</script>
Time zone information of the browser is not part of the HTTP spec, so you can't just get it from a header.
If you have location coordinates (from a mobile device GPS, for example), then you can find the time zone using one of these methods. However, geolocation by IP address is not a great solution because often the IP is that of an ISP or proxy server which may be in another time zone.
There are some strategies you can use to try to detect the time zone, such as using jsTimeZoneDetect library, which is a great starting point, but imperfect enough that you can't just rely on that alone. If you're using moment.js, there's a built in function in moment-timezone called moment.tz.guess() that does the same thing.
The idea of using JavaScript's getTimezoneOffset() function is flawed in that you are not getting a time zone - just a single offset for a particular date. See the TimeZone tag wiki's section titled "TimeZone != Offset".
However you look at it, ultimately you have to decide on one of two approaches:
Ask the user to tell you their time zone, from some sort of drop-down list or map-based timezone picker control.
OR
Only send time to the browser in UTC, and use JavaScript on the browser to convert to whatever local time zone the user might have their computer set to.
I discuss this in more detail (from a c# perspective) in this answer.
Dependencies:
http://www.maxmind.com/download/geoip/api/php/php-latest.tar.gz
http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
//Get remote IP
$ip = $_SERVER['REMOTE_ADDR'];
//Open GeoIP database and query our IP
$gi = geoip_open("GeoLiteCity.dat", GEOIP_STANDARD);
$record = geoip_record_by_addr($gi, $ip);
//If we for some reason didnt find data about the IP, default to a preset location.
if(!isset($record)) {
$record = new geoiprecord();
$record->latitude = 59.2;
$record->longitude = 17.8167;
$record->country_code = 'SE';
$record->region = 26;
}
//Calculate the timezone and local time
try {
//Create timezone
$user_timezone = new DateTimeZone(get_time_zone($record->country_code, ($record->region!='') ? $record->region : 0));
//Create local time
$user_localtime = new DateTime("now", $user_timezone);
$user_timezone_offset = $user_localtime->getOffset();
}
//Timezone and/or local time detection failed
catch(Exception $e) {
$user_timezone_offset = 7200;
$user_localtime = new DateTime("now");
}
echo 'User local time: ' . $user_localtime->format('H:i:s') . '<br/>';
echo 'Timezone GMT offset: ' . $user_timezone_offset . '<br/>';
citation: SGet visitor local time, sunrise and sunset time by IP with MaxMind GeoIP and PHP by Stanislav Khromov
One solution is to ask them! Especially on members systems where you can capture/register a user - give them a choice at that point. Simple but accurate.
This works fine...
echo <<<EOE
<script type="text/javascript">
if (navigator.cookieEnabled)
document.cookie = "tzo="+ (- new Date().getTimezoneOffset());
</script>
EOE;
if (!isset($_COOKIE['tzo'])) {
echo <<<EOE
<script type="text/javascript">
if (navigator.cookieEnabled) document.reload();
else alert("Cookies must be enabled!");
</script>
EOE;
die();
}
$ts = new DateTime('now', new DateTimeZone('GMT'));
$ts->add(DateInterval::createFromDateString($_COOKIE['tzo'].' minutes'));
Timezone is not available in the HTTP header, but country (abbreviation) is in the ACCEPT_LANGUAGE header. It'll be something like "en-US" (US is the country code). This can be combined with the JavaScript information to get a good idea of the user's timezone.
This is what I'm using in JS:
function timezone() {
var now = new Date();
var jano = new Date(now.getFullYear(), 0, 1).getTimezoneOffset()/-60;
var julo = new Date(now.getFullYear(), 6, 1).getTimezoneOffset()/-60;
var tz = Math.min(jano, julo);
if (jano != julo) tz += ((jano < julo) ? 'S' : 'W') + Math.abs(jano - julo);
return tz;
}
This returns a string like "-6S1" for the central zone (standard time offset of -6 hours, DST active in the summer and adds 1 hour). I use a cookie to make this available to PHP. PHP searches the TZ database for zones that match this, and the country. For here (US, -6S1) there are 7 matching zones, the first is "America/Chicago".
BTW, there are 2 zones in the database where DST adds something other than 1 hour: Lord Howe Island (10.5W0.5) and Troll Station, Antarctica (0W2).
how to send browser time to MySQL server for save through php.
I search lot's of time on the internet, but I did not find a good answer.
suppose my browser time is 17-Sep-2018 3:10:55
So how can I store this in my database. I Use NOW(), DATE but nothing the write answer.thanx in advanced.
You will have to use Javascript; PHP is executed on the server - which is not the same as the user's browser or location.
For example:
(function() {
var url = '/some/file.php?date=' + new Date();
fetch(url, {
method: 'GET',
mode: 'no-cors'
})
.then(response() => console.log(response))
.catch(error => console.error('Could not complete request:', error));
})();
Then in the Server you can process the request:
<?php
// request date contains the date from our JS request
if( $_REQUEST['date'] )
{
// format it how you want it
$date = date('j M Y h:i:s a', $_REQUEST['date']);
// check and make sure variable exists
if( $date )
{
// connect to mysql (this is not recomended... better to use some sort of library)
$mysql = new mysqli('localhost', 'root', '', 'site');
// safely store it with prepared statements
$stmt = $mysql->prepare('INSERT INTO visits (visist_time) VALUES (?)');
if($stmt = $stmt->bind_param('d', $date))
{
// this will execute the query
$stmt->execute();
}
}
}
This is not a perfect answer; I am not sure why you want to get a timestamp for users who visit, but that will in theory be able to record timestamps every time the JS script is loaded.
Don't store the browser time - it could easily be incorrect, and will wreak havoc on users who travel between timezones as well. (If I go visit Australia, all my appointments in your database would suddenly be 14 hours off...)
Instead, you should store the server's time - which should always be correct using something like NTP - and in UTC. When you need to show a date to the user, you can use JavaScript to convert the timestamp into the correct time based on the browser's current GMT offset.
Another option is having the user provide their chosen timezone as a setting, and converting to that.
Im creating a UI where users get to choose their timezone. My backend is PHP and I know you can do it a few ways but I had questions about all of them and which way is the best:
http://ca2.php.net/date_default_timezone_set
//where America/Los_Angeles will be changed based on user
date_default_timezone_set('America/Los_Angeles');
Does this change the server timezone for ever user or just what is being exported? is there any performance issues with this?
What if it was a function like this...?
date_default_timezone_set('America/Los_Angeles'); -08:00 set in php.ini
$date = "2014-01-01 12:00:00";
$new_time_zone = "America/New_York" // -05:00 = +3 hours difference
function adjust_time_zone($string, $zone){
$datetime = new DateTime($string);
$new_zone = new DateTimeZone($zone);
$datetime->setTimezone($new_zone);
return ($datetime->format('Y-m-d H:i:s'));
}
adjust_time_zone($date, $new_time_zone);
Results(i tested this):
2014-01-01 15:00:00 //3 hours ahead.
in this format everything stamped in the system would be on LA time and exported would be the change...
I know there is allot of these Timezone threads but there seems to be allot of "i do it like this" and not any solid "this way blows my socks off="
Thanks for any help you can give!
I store everything in the db as a datetime and UTC timezone.
I store the user's timezone in the db ($timezone).
So when a time ($time) is taken from the db, I run it through the following function:
function changetimefromUTC($time, $timezone) {
$changetime = new DateTime($time, new DateTimeZone('UTC'));
$changetime->setTimezone(new DateTimeZone($timezone));
return $changetime->format('m/d/y h:i a');
}
This returns the time in the user's timezone, formatted.
edit: you can see the db table of timezones in this thread:
Generating a drop down list of timezones with PHP
Well it looks like what you have should work for you. This is an alternate method, although not necessarily better. You can just use PHP's mktime and pass the hour offset to it.
<?php
print "<br>Date: ".date("Y-m-d H:i:s");
// DEFINE AN OFFSET
$offset = -5; // TIMEZONE OFFSET: '-5' FOR NEW YORK
// ADD THE OFFSET TO THE CURRENT TIME
print "<br>Date Offset: ".$date_offset = date("Y-m-d H:i:s", mktime(date("H") + $offset, date("i"), date("s"), date("m"), date("d"), date("Y")));
I found a great solution to the problem - and to adapt the date and time settings on my page according to the users settings.
Ready build js code
Some developers that had the exact same problem build a javascript solution to the code. You don't need to know javascript as long as you follow these instructions.
Go to https://bitbucket.org/pellepim/jstimezonedetect/src/default/
Read through the readme file if you want to
Either download the script as an NPM package or download it manually by pressing "downloads" in the left menu.
If you pressed downloads to manually download the script press "Download repository" to get the files.
Create a js folder - named "js" in your project. (optional)
Unzip the jstimezonedetect files into the js folder. I chose to name the unziped file "jstimezonedetect".
To reach the files above my current directory is /js/jstimezonedetect/.
In your header code (important it is in header since the time-zone will affect the full code on the rest of your page unless you run a function.
Enter the following code to your php file:
echo '
<script src="js/jstimezonedetect/dist/jstz.min.js"></script>
<script>
document.cookie = "usertimezone="+jstz.determine().name();
</script>
';
$settimezone = $_COOKIE['usertimezone'];
date_default_timezone_set($settimezone);
The first line of script will import the jstz.min.js file from the importat jstimezonedetect project.
Second line will create a cookie (you can later delete the cookie if you want to).
In the third line I get the cookie into the php script and then I use PHP date_default_timezone_set();
(https://www.php.net/manual/en/function.date-default-timezone-set.php)
to set the timezone.
Worked perfectly for me. :) Ask if something is unclear.
I've asked a very similar question before but got no answers that helped.
I have a site that allows users to post notes. There will be a time stamp on those notes. The default timezone on my server is EST5EDT (despite me setting the date.timezone to something else, which is a different issue!).
As far as I can gather, it is best to set the timestamp with the server time and convert it for each user. For example:
User 1 (GMT) posts "Hello World" at (local time) 5:00 (server time) 0:00
User 2 (AEST, +10) sees that User 1 posted "Hello World" at (local time) 15:00
For the sake of argument, I am avoiding worrying about DST as I don't think it counts for this.
I understand I can use date_default_timezone_set() within my application but I am quite sure I should set the post time as the server time so no need to change the set timezone.
I only want to convert the time for the viewer
"Post as Server Time, Read as Local Time"
I do not believe I am the first person who has had their web app perform this so there must be an answer out there.
I will have to get the datetime the post was made, get the timezone of the user viewing the post (probably through javascript as php uses server side date and time) and convert the datetime using the user's timezone.
getTimezoneOffset() in javascript will work out the users time difference from UTC but not from my server time.
What you can do is save the UTC time when saving and when viewing show the UTC time + offset.
This can all be done using JS on client side.
JS method used when saving= UTC()
JS method used when displaying =
<html>
<head>
<script type="text/javascript">
function showDateInClientSideFormat(dValue)
{
var d = new Date()
var n = d.getTimezoneOffset();
var dateClientSide = new Date(dValue +n);
return dateClientSide;
}
</script>
</head>
<body>
<?php
echo '<script> showDateInClientSideFormat($dateSaved); </script>';
?>
</body>
</html>
PS: UTC time is the same as GMT time
You could use PHPs DateTime and DateTimeZone to convert the datetime into the users current timezone:
http://www.php.net/manual/de/class.datetime.php
http://www.php.net/manual/de/class.datetimezone.php
$date = new DateTime($dateTimeFromDB);
$date->setTimeZone( new DateTimeZone('User/Timezone') );
echo $date->format('d.m.Y H:i');
I would like to get their timezone with names like 'Asia/Calcutta' or 'Australia/Darwin'
I have php installed on myserver and its time set to 'UTC'
For detecting timezone offset you can use this function:
function get_time_zone_offset( ) {
var current_date = new Date();
return parseInt(-current_date.getTimezoneOffset() / 60);
}
Example you can see here
This is my first post here but hopefully I can help someone. I felt compelled because this site has helped me a lot. Thanks stackoverflow members!
http://www.pageloom.com/automatic-timezone-detection-with-javascript
From what I understand about this JavaScript code it is very accurate and will be able to return the offset from UST, the corresponding Olson Database timezone name, and handle the daylight savings time issue (ex. -5:00, America/New_york, true).
http://www.php.net/manual/en/timezones.america.php
The above link is just a list of the php supported timezone parameters, which as far as I can tell align with this JavaScript code (I am sure that is beneficial I just don't know why yet I am still writing my code and I am kinda new to php/mysql).
The only hurdle you will face after getting this code working on your html page will likely be getting these values to php and then to mysql if that is what you need. I achieved this by sending these values as a $.post using JQuery. I think this is the easiest way to do it (please someone correct me if I am wrong). I believe the other alternatives are using an AJAX command (more complicated) or cookies(I think?).
After I got the values from the Java-script code to the server (PHP) I stored them as session variables so they would change if the user on my site logged in from a different timezone then usual. However they could easily be saved to the database as well.
If you use the JQuery route this needs to be in the header of the html document where the $.post is being executed.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
The most updated timezonedetect script can be found linked on that first url I posted.
//replace this comment with the most updated timezonedetect code from that first link
var timezone = jstz.determine_timezone();
var tzoffset = timezone.offset();
var tzname = timezone.name();
var tzdst = timezone.dst();
$.post("scripts/tzdetect.php", { tzoffset: tzoffset, tzname: tzname, tzdst: tzdst } );
The receiving file in this case tzdetect.php should look like this if you want the data stored as session variables.
<?php
session_start();
$_SESSION['tzname'] = $_POST['tzname'];
$_SESSION['tzoffset'] = $_POST['tzoffset'];
$_SESSION['tzdst'] = $_POST['tzdst'];
?>
Your question is really about Javascript rather than PHP - because it depends on the client capabilities.
As I understand it, Javascript allows you to determine the current time zone offset (the difference between UTC and local time) but that does not allow you to unambiguously determine the time zone. Many time zones will share the same offset at any one particular point in time, but will differ at other times, in terms of whether they observe daylight saving and at what point they change into and out of daylight saving.
If you definitely need the time zone, you might want to work out a list of possible time zones, and present that to the user - also allowing them to override the narrowing decision, choosing any time zone.
Again, it really depends on what you're trying to achieve.
You do not need jQuery to do this. Try the following code:
var offset = (new Date()).getTimezoneOffset();
alert(offset);
It will alert current timezone offset from the browser (in minutes).
See this jsfiddle as a proof.
I think you will need to convert it to the timezone name on your own. If you want the names to be consistent, you should not depend on the user's browser.
You can use this code (see this jsfiddle):
var offset = (new Date()).getTimezoneOffset();
var timezones = {
'-12': 'Pacific/Kwajalein',
'-11': 'Pacific/Samoa',
'-10': 'Pacific/Honolulu',
'-9': 'America/Juneau',
'-8': 'America/Los_Angeles',
'-7': 'America/Denver',
'-6': 'America/Mexico_City',
'-5': 'America/New_York',
'-4': 'America/Caracas',
'-3.5': 'America/St_Johns',
'-3': 'America/Argentina/Buenos_Aires',
'-2': 'Atlantic/Azores',
'-1': 'Atlantic/Azores',
'0': 'Europe/London',
'1': 'Europe/Paris',
'2': 'Europe/Helsinki',
'3': 'Europe/Moscow',
'3.5': 'Asia/Tehran',
'4': 'Asia/Baku',
'4.5': 'Asia/Kabul',
'5': 'Asia/Karachi',
'5.5': 'Asia/Calcutta',
'6': 'Asia/Colombo',
'7': 'Asia/Bangkok',
'8': 'Asia/Singapore',
'9': 'Asia/Tokyo',
'9.5': 'Australia/Darwin',
'10': 'Pacific/Guam',
'11': 'Asia/Magadan',
'12': 'Asia/Kamchatka'
};
alert(timezones[-offset / 60]);
However I would not rely on this too much.
You can get the timezone offset. Which you can use to calculate the approximate timezone. You can keep an associative list of timezone offset and the names.
This method does not give any exact values, though.
<?
echo date("e");
?>
This will give the output:
Asia/Kolkata