Determine a user's timezone
Asked Answered
W

27

720

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?

Wether answered 1/8, 2008 at 0:42 Comment(10)
Well, lucky for you that answer can be found on our very own stackoverflow website: https://mcmap.net/q/21175/-how-to-get-the-country-according-to-a-certain-ip-duplicate spoiler: hostip.info/use.htmlHepato
Ask the user. If you get the time zone from the user's computer, and it is set wrong, then what?Vanitavanity
Then the user probably doesn't care?Carbine
Do you mean https://mcmap.net/q/21145/-getting-the-client-39-s-time-zone-and-offset-in-javascript/218196 ?Timon
No. Doesn't help my current cause, though looks useful for other things. What I need to do is take the getTimezoneOffset() minutes, and pass them to something from which will give me America/Los_Angeles for example. Or pass something to a function that will give me that or equivlent. Im not looking to display times based on the users set timezone more so than I am based on the place something took place..Keturahkeung
I don't think there is a built-in API that gives the timezone name. You have to resort to some external service or library for that.Timon
Unfortunately, the answers to this question also allow for user profiling and geofencing.Interrogatory
Why do you need to know the user timezone?Locale
I don't think it is possible unless the user sends the information to the server. This should be handled client-side.Galvanotropism
codeproject.com/Questions/107174/…Sortie
C
351
-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.

Coughlin answered 27/11, 2009 at 17:52 Comment(19)
this is what makes the most sense to me. is there any reason this shouldn't be used or is everyone above just making the problem more difficult than they need to.Whiffet
@jordanstephens I am not an expert so I do not know if there are circumstances where this would not work, but it worked fine for me.Coughlin
What about users who use cell phones that have browsers without javascript support? I like the question, the user asks about HTTP headers, user agent... is there a way to make this work server side, as accurate as possible?Icefall
That's strange. For me this returns -4 but I'm in GET which ought to be +4 - what am I missing? I've checked that my OS is set to the correct timezone.Bio
getTimezoneOffset() returns number of minutes when you subtract your current time from GMT time. So if you live in California, that's PST, which is GMT-8, so you're 8 hours behind. Subtract that from GMT using getTimezoneOffset(), and it will return 480 minutes. If you want to find your offset, multiply that by -1 and divide by 60.Amoral
This doesn't account for Daylight Saving Time / Summer Time, but the link posted by Joseph Lust does: https://mcmap.net/q/21164/-determine-a-user-39-s-timezoneGutsy
This doesn't always work for DST. Get timezone offset does exactly what it says. It get's the offset. A time ZONE is actually a geographical area. This won't work for daylight savings since you don't know which hemisphere the user lives in, or if their country even has daylight savings. Why not use this instead: >>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"Sideways
I beg to differ with Keyo. The definition of getTimezoneOffset() (according to the ECMA standard ecma-international.org/ecma-262/5.1/#sec-15.9.5.26) is "Returns the difference between local time and UTC time in minutes." - in other words, it should take daylight savings into account. Mozilla's documentation says "Daylight saving time prevents this value from being a constant even for a given locale."Creight
@xgretsch: It gets the user's current offset from GMT. That's fine if you're presenting another time that occurs on the same day (unless the current date is a changeover date, where it could be wrong). However, there are many timezones which have the same offset from GMT, and they may have different changeover dates or not use daylight savings.Quiff
@Keyo: toTimeString's output is implementation-defined: ecma-international.org/ecma-262/5.1/#sec-15.9.5.4. There is no guarantee that it will include a time zone name. There is also no guarantee that if it does include a time zone name, that it maps to anything the server knows about. It may work in some browsers some of the time, but I wouldn't like to rely on it.Quiff
@Mike Dimmick: While true, the question itself asks if there is a way to get the time zone offset, not the actual time zone itself, so this should be correct.Grocer
@Mike Dimmick: Ah, I see your point. I guess there isn't a simple answer to "what's the user's time zone offset" - you need to ask "what's the user's time zone offset at a particular point in time". I'm beginning to think that the only robust way of doing this is one of those horrible solutions where you set the time zone, print out the time in local time, and compare what you got!Creight
One thing to note here; some places (such as Newfoundland in Canada) have timezones that are off by half an hour, so after dividing by 60 your answer may not be an integer.Geyserite
To solve the above, why not get the browser's current time (ie. actual time, not offset) then, server-side, determine GMT offset by comparing browser's current time with server's current time (assuming you know the server's own GMT offset). This seems the least problematic solution to me. You can determine the time zone from there. In .NET, for example, you can use TimeZoneInfo to cycle through current times in each zone, until a match is found for the browser's reported time (or query an online time service).Shadow
The user's computer clock could be wrong, in which case this would fail. For example, if I'm serving a report to teachers that lists student responses to questions with their times, and my database stores times in UTC, then I would need to know a time-zone offset, and the user's current computer time would be irrelevant. The only way to reliably obtain such an offset would be to either ask the user (i.e. ensure the time zone is included with report request, or add a drop down for time-zone above the report and do the conversion client-side), or determine the user's physical location via GPS.Almaraz
The question asks how to determine it on the server side. This is code for the client.Mathre
w3scool says The returned value is not a constant, because of the practice of using Daylight Saving Time. as a Note.Surcingle
This doesn't even BEGIN to answer the question.Bronchopneumonia
Some timezones are offset by 30 or 45 minutes, not 60, so best to leave as minutes: timeanddate.com/time/time-zones-interesting.htmlGunnel
C
218

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.

Cyanogen answered 3/8, 2008 at 19:30 Comment(7)
What about when a user is downloading an .ics file that should have a start time specific to their location (e.g. 9-11am across the country)? They shouldn't HAVE to say what their time zone is imo.Siobhan
Why not accept this as the correct answer? The answer given by Unkwntech even not work for non-IE browsers.Underbody
@Ishmaeel: but users do travel internationally and they shouldnt need to tell their timezone each time they login from some non-native timezoneTradesman
This doesn't answer the question, which clearly implies he's looking for a technological solution.Metallography
@gWiz OP is asking for a standard solution. This is pretty standard.Plutonium
The best solution would probably be a combination of asking the user (e.g. providing a time-zone drop down at the top of a report), while defaulting the drop down selection to a GPS-determined time-zone when the user is on a mobile device that provides location information, and otherwise default to UTC.Almaraz
@user01 You can not make such a general statement and think it is correct for all situations. There are enough applications with user profile where the user is not travelling each day. Thus a dropdown with timezones to choose from is fine for "most" user requirements.Extinguish
M
217

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.

Matheson answered 1/8, 2008 at 12:19 Comment(5)
Strangely, this is the only correct answer to the question, which asks how to do it server side. I suspect the reason there are other answers with more votes is because once you realize you need to do it client side you end up using the other answers. But IMHO anyone upvoting another answer should be upvoting this one too.Ramonaramonda
I believe the best method is to use geo-ip location to sort the possible time zones and by default pick the first one that is (close) match to user agent time offset (JavaScript required). Even after that, you have to provide a way to fix the timezone after even this method will select the incorrect one.Darill
@MikkoRantalainen careful when using proxies through, as they don't always advertise themselves in the headers.Scend
@Scend there exists a better answer nowadays: https://mcmap.net/q/21164/-determine-a-user-39-s-timezoneDarill
This is literally the only answer that actually addressed the question posed.Bronchopneumonia
L
110

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:

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. They're also listed in the MDN browser compatibility table of Intl.DateTimeFormat.prototype.resolvedOptions in the row labeled "computed timeZone"

  • 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.

Lowpressure answered 25/3, 2014 at 3:47 Comment(6)
Using the user's geographic location (i.e. their locale) to deduce the timezone is also flawed. Users may wish to use a specific timezone on their device that is not the local timezone, even thought it might display the same time (or not). E.g. travellers frequently leave their devices with the timezone set to their usual locality and do not expect to see dates and times use a different offset without being advised. I might be talking from personal experience here… ;-)Becnel
Can't tell if you're trolling me Rob. ;) But none of these approaches use their locale, but rather the setting on the device, so aligns with your point. (Only the alternate approach mentioned in the last paragraph would use current location.)Lowpressure
Chiming in with a terminology note: "locale" is emphatically not the user's geographic location. "Locale" is a group of settings such as language, number format, calendar, etc. For example, the de_DE locale specifies German as default language, the euro as default currency, commas as decimal separator, periods as the thousands separator, and Gregorian as the calendar. See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Jerrodjerrol
Just want to say jsTimeZoneDetect came back wrong for me, but moment didn't! +1Effieeffigy
'in the Intl compatibility table' link does not work anymoreGunwale
@Gunwale - Thank you. I've updated the link to its new location, and also added a link to similar information now found in MDN.Lowpressure
C
56

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.

Cocotte answered 1/8, 2008 at 15:11 Comment(3)
I have voted this answer up because the latitude and longitude obtained from databases like GeoIP (which has a free version available as of now) can be combined with databases that convert such a coordinate to a time zone. I think GeoNames has a latter such database.Changchun
The current versions (both free and paid-for) of the MaxMind GeoIP databases/ APIs, do indeed supply timezone information (it returns "Europe/London" for my timezone.) I can't remember whether the old version of their GeoIP system did the same, but it works very well now! The MaxMind fields are named "time_zone", "time_zone_name".Aphoristic
I'm sure this works great till you are using a VPN.Misti
G
55

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

General answered 6/8, 2012 at 21:22 Comment(4)
Link only answers are discouraged, because if the link disappears, the answer ceases to be useful; and because without following the link, readers don't know whether it gives a good answer. In this case, you could clarify that this is a 3rd-party library which takes a database-based approach to identification, and maybe explain some of the principles of its operation.Reamonn
This! This is the way to go. Simple library, handles DST properly. Other answers are full of WTF and many don't do DST.Jhelum
This library is very clever. It works by querying current offset to UTC, then adjusting JavaScript Date object time by adding or substracting seconds until offset to UTC changes. Using this method this library figures out many enough DST changes to uniquely identify the timezone. I think the library could have even better performance if it did binary search instead of linear search. The return value is an IANA zone info key (aka the Olson time zone database).Darill
This library is no longer needed. Modern browsers support the Intl API, which returns the IANA timezone string. See this answer.Sheriesherif
G
47

Here is a more complete way.

  1. Get the timezone offset for the user
  2. 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)

Goncourt answered 30/3, 2011 at 20:48 Comment(2)
This worked for me! Read the comments under the blog post for a couple updates to the code.Gutsy
This will still only return the standard offset for the time zone, such as +02:00. It will not give you enough information to determine the time zone of the user, such as Africa/Johannesburg or Europe/Istanbul. See the timezone tag wiki.Lowpressure
M
34

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.

Mordacious answered 9/4, 2011 at 19:16 Comment(3)
i do like this, but i might have something that checks the current $_SESSION['time'] and only get the javascript to reload if its differentRashida
It's probably easier to use a Cookie than a Session to transport this, since locking and unserializing the PHP session may cause slowdowns in your app. For maximum efficiency, you could copy the value into the session and delete the cookie so that it's not sent in subsequent requests.Reamonn
Do not do this. The code that captures timezone then forces the entire page to reload could strike at any time, while the user is filling out a form, who knows. If for any reason the code fails, for example their timezone is not set or your code fails to roundtrip it, this will create an infinite loop where the user's page constantly reloads once the JS fires, forever. Don't do this to them!Putrescent
S
28

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/

Streamliner answered 13/9, 2012 at 2:5 Comment(2)
This only returns the current time zone offset - not the time zone. See the timezone tag wiki.Lowpressure
Edited to include info about doing the same for the time zone name.Streamliner
W
25

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.

Wommera answered 16/9, 2010 at 5:59 Comment(0)
S
25

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

Sideways answered 30/8, 2012 at 5:8 Comment(0)
D
25

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.

Deathly answered 2/1, 2013 at 18:5 Comment(0)
C
24

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!

Creese answered 27/8, 2011 at 23:0 Comment(1)
$unix_timestamp_ofshiz ? Something is missing here and doesn't quite work ,even though this seems like it could be a good answer.Moldboard
P
22

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.

Pansophy answered 3/8, 2008 at 20:40 Comment(0)
D
22

Easy, just use the JavaScript getTimezoneOffset function like so:

-new Date().getTimezoneOffset()/60;
Daubery answered 27/5, 2012 at 17:25 Comment(2)
Also, it only returns the current time zone offset - not the time zone. See the timezone tag wiki.Lowpressure
This is a just a copy of the accepted answer, why you even voting on it.Thersathersites
C
16

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.

Coriolanus answered 30/8, 2008 at 9:29 Comment(0)
A
16

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).

Arise answered 25/5, 2010 at 0:11 Comment(4)
The link is dead. I think this is the alternative link: devproconnections.com/article/aspnet2/it-s-about-time-122778Soakage
The article is available as PDF form here too: app.box.com/shared/bfvvmidtygAdenaadenauer
The method of converting UTC server time to local client time described in this article is wrong. Using the current client offset to adjust UTC times on the server will result in incorrect "local" times for half the year for client locales that observe daylight savings time. Consider this scenario: a client in the UK on 14 Jan 2013 (GMT+0000 Standard Time) sets a date and time of 21 Aug 2015 14:00 (GMT+0100 Daylight Time). This gets normalised on the server to 21 Aug 2015 13:00 UTC. On the day this occurs the client offset is 0 so the time sent back to the client will be 21 Aug 2015 13:00.Renin
Valid point, but I didn't claim this to be a bullet-proof solution. If you need to implement a really time-sensitive solution, say a train ticket booking application, then you need to find a more comprehensive (and complex solution). However, for many apps this would not be an issue. Because in many cases we want to localize GMT values for current session. Now, if you have an application that needs to save a time stamp for some even in the future and it cannot tolerate DTS, then a proper way would be to present an option to save time directly in GMT. If you know a better option, please share.Arise
K
16

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.

Kedgeree answered 15/9, 2014 at 1:19 Comment(0)
C
16

You could do it on the client with moment-timezone and send the value to server; sample usage:

> moment.tz.guess()
"America/Asuncion"
Catlett answered 13/9, 2016 at 6:19 Comment(1)
Nowadays, moment.js i no longer recommended. There are far smaller alternatives currently (dayjs, date-fns). Moment is huge.Sheriesherif
A
14

Getting a valid TZ Database timezone name in PHP is a two-step process:

  1. 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.

  2. 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.

Anthony answered 10/1, 2017 at 11:56 Comment(1)
I think a simpler process is to call Intl.DateTimeFormat().resolvedOptions().timeZone and send it to web server. Ref: stackoverflow.com/questions/9772955/…Galvanotropism
L
13

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'];
?>
Luo answered 30/7, 2012 at 8:8 Comment(0)
B
11

A simple way to do it is by using:

new Date().getTimezoneOffset();
Burrussburry answered 1/12, 2011 at 11:8 Comment(2)
Why did you repost an identical answer (by John Isaacks) from 2 years ago: https://mcmap.net/q/21164/-determine-a-user-39-s-timezone ?Anse
Also, it only returns the current time zone offset - not the time zone. See the timezone tag wiki.Lowpressure
T
10

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
?>
Trafficator answered 28/1, 2012 at 8:21 Comment(1)
This doesn't account for "daylight saving" adjustments - a user in Dublin would match your 'Europe/Dublin' in winter, but 'Europe/Belgrade' in summer. If you're going to use the current offset, all you can reasonably assume is that offset, not a geographical identifier.Reamonn
C
9

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.

Clerical answered 8/9, 2014 at 23:25 Comment(1)
Unfortunately, that header seems to be mainly designed for responses, not requests: "A user agent MAY send a Date header field in a request, though generally will not do so unless it is believed to convey useful information to the server." I just checked, and Firefox does not send it.Reamonn
P
5

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().

  1. 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
  1. 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.
  1. 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.
Porker answered 27/12, 2021 at 11:50 Comment(1)
Great answer!, thank youBoroughenglish
B
2

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();.

Babyblueeyes answered 13/10, 2020 at 6:43 Comment(0)
T
1

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.

Thermic answered 13/4, 2021 at 9:46 Comment(1)
FYI, I store the Time Zone in the user profile so that I can later use it for adjusting times sent via email. The user CAN put their own time zone in their profile, but most don't. This way, the email times are most likely correct as I update the time zone on every login unless they have selected one manually.Crosspollinate

© 2022 - 2024 — McMap. All rights reserved.