This blog post will attempt to explain how to automatically detect your user’s time zone using JavaScript. If you’re in a hurry, you can skip directly to the demo or just grab the files
Previous attempts to solve this problem:
Server side:
Time is not included in an HTTP request. This means that there is no way to get your user’s time zone using a server side scripting language like PHP.
IP address geocoding:
Another method that people have used to address this problem is to geocode your visitors IP address. IP geocoding is what is used when you go to a website and are shown an ad to “meet other singles in Boulder”. Unfortunately, for simply detecting a timezone, IP geo-coding is an expensive way to go. Just check out the prices for Maxmind and ip2location. There’s no way I’m paying for that. I did find a free provider called hostip, but it is worthless as it couldn’t decide whether I live in CA or NC.
With JavaScript:
The common JavaScript that is used to detect a visitor’s timezone is:
document.write(myDate.getTimezoneOffset());
As I started reading up on the getTimezoneOffset code I realized it was too buggy to be used in any critical application. The function returned inconsistent results in different browsers and it never seemed to account for daylight savings time correctly. It quickly became clear that I was going to have to write my own script if I wanted this to work.
How I ended up doing it:
There are basically two things needed to figure out a visitors time zone. First, we need to determine the time offset from Greenwich Mean Time (GMT). This can easily be done by creating two dates (one local, and one in GMT) and comparing the time difference between them:
var jan1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
var temp = jan1.toGMTString();
var jan2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
var std_time_offset = (jan1 - jan2) / (1000 * 60 * 60);
The second thing that you need to know is whether the location observes daylight savings time (DST) or not. Since DST is always observed during the summer, we can compare the time offset between two dates in January, to the time offset between two dates in June. If the offsets are different, then we know that the location observes DST. If the offsets are the same, then we know that the location DOES NOT observe DST.
temp = june1.toGMTString();
var june2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
var daylight_time_offset = (june1 - june2) / (1000 * 60 * 60);
var dst;
if (std_time_offset == daylight_time_offset) {
dst = "0"; // daylight savings time is NOT observed
} else {
dst = "1"; // daylight savings time is observed
}
Once, I had this code written, the next step was to compile a list of the various time zones around the world along with their opinions on DST. I actually ended up using the list of time zones from Microsoft Windows. It was rather time consuming to compile this list, so I hope you can make use of my work to save yourself some time.
Please let me know if you have any comments, questions or problems with this code. As with anything that I post on this blog, feel free to use this code however you want. Just don’t blame me if it breaks.
Update (06/27/07):
My code wasn’t correctly detecting timezones in the lower hemisphere. I have added hemisphere detection for all our Aussie friends out there. I also fixed a bug in the convert() function that was leaving off the + sign at certain offsets. Thanks Val for pointing this out and helping me with the fix.
Update (10/24/08):
Fixed the bug that Rama and Will pointed out in the comments.


Hey this script really helped me .. thanks
Hi,
Excellent code, but one mistake exist I think.
For southern hemisphere summer and winter are different.
So if you swap daylight_time_offset and std_time_offset – it will work for southerners, but will not for northerners:-)
Probably checking the sign of difference for Jan and July will allow to detect hemisphere (if daylight savings exist at all).
Also not sure why Brisbane in HTML has no daylight savings?
Cheers,
Val.
Val,
Thanks for your comment. You are right that summer and winter take place at different times in each hemisphere. However, my code should work correctly in both hemispheres. Let me try and explain.
Take Antarctica for example. Their DST goes from Sept 30 – March 18. My code compares the time on Jan 1st (during DST) to the time on June 1st (not during DST). Since these times are different I know that DST is observed. I don’t care if it is observed during summer or winter. I only care that that the two times are different. The same formula works whether DST occurs from March to Sept or Sept to March.
I double checked Brisbane on timeanddate.com and it says that they are not observing daylight saving time in 2007. This of course could be wrong. I would appreciate it if you can send me more information about that.
Take care,
Josh
Josh,
I already tried and it did not work.
The proof: just set your comp timezone to Adelaide, open your test page
and your HTML will show the first item: (-12:00)Iternatioal Date Line West.
(Adelaide is +9:30,1 by the way according to your JS values).
If you check the HTML source, you will see, that none of the items in the combo are selected.
If you put an alerts in JS, you will see, that TZ detected is: ‘+10:30,1′. This value does not exist in HTML, so JS can not select the combo value.
If you change the JS script and swap the values of variables how I described before, it will work for Adelaide.
Cheers,
Val.
Hi! Good site respect! Visit welivetogether.com and addictinggames.com Thanks!
Thanks for putting up this script! It was really helpful and saved me a lot of time.
I’m looking for something similar for my comments section, so I can show the user the time something was posted in their own time reference. I should think just saving the time of post in UTC, then at the client side use the difference between local time and utc would give me the proper offset to use when I pull the comments from the db. No need to worry about dst or hemispheres that way. Sound correct?
Thomas,
No, you will still need to worry about both DST and hemispheres. Your offset from GMT would vary by 1 hour depending on whether or not you are in DST. You also need to worry about hemispheres since DST occurs during different times of year for each hemisphere. The good news is that my code should give you a nice head start on getting your times right on your comments.
I actually needed a way for people loading my page to see the times that comments were posted in their own time. My server is west coast and I’m east coast, so I noticed I would post and it was -3 hours off. I’ve written some ajax now that gets the cleints current time, finds the difference betwent that and the utc time, and loads the div that shows comments to my page and uses that to offset to show the time a post was made. The offset is hardcoded to -240 right now, but I’m working on the difference between utc and current client time right now. I think that should make all neccessary corrections, though I may be missing something. If utc is X and my current time is Y, I think I should be able to use that difference to offset the time a post was saved (in utc) in order to show the time that post was saved in the clients time frame. Please correct me if I’m mistaken.
Thomas,
I think you’re still missing the issue here.
It is the offset between the client time and UTC/GMT that changes with DST. The hemisphere determines when that change will occur. (DST is always observed in the summer, but Christmas is in the summer in the lower hemisphere).
A good case to think about is Arizona. Arizona is in the same timezone as I am (-07:00 GMT), but they don’t observe DST. That means as I am writing this comment at 6:30pm it is 5:30pm in Arizona. Basically, you need to consider more than just the raw offset from GMT. You can’t just ignore DST if you want your script to work consistently no matter where you are.
Change the clock on your computer to test various timezones. If you can get your script to work correctly with Arizona, California and Australia, you’re probably okay.
Great script. Works like a champ! I’m trying to get it to write out the actual timezoneName when you submit it to a formMailer. It only submits the value for the array. Any suggestions?
Thanks!
Swobo,
The form is currently submitting the offset from GMT and a 0 or 1 for whether it supports DST or not. So Denver, CO is “-07:00,1″. (-7 for the offset, 1 for DST boolean)
You have a couple options:
– Include the name of the timezone in the dropdown. For example:
OR (probably a better solution)
– Map each of the select options back to their names on the server side. For this, you would need to create an array for each possible selection and map it back to its respective name. In PHP you would do something like:
$timezones['-07:00,1'] = “Mountain Time (US & Canada)”;
etc…
I hope that helps.
Hey Josh. Heck of a script. Thanks for sharing. What’s the licensing? Can I use this as part of a commercial site? Also, I’m trying to map these back to abbreviations, but I’m having a heck of a time finding the correct abbreviations for these. Do you happen to have any mapping like that?
Bob,
Feel free to use this script however you like. There are no limits on it. Just don’t blame me if it breaks.
I wish I could help you with the mapping. That would definitely be a good thing to have. Unfortunately, I’ve not seen anything like that around. If you manage to find it, let me know and I’ll update the post to help some other people out.
First of all thanks for your script.
One thing for -10:00 ,-11:00 ,-12:00 the convert function is returning +-10:00,
+-11:00,+-12:00
to rectify that one i added one line of code in the convert function as below:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(hours > 0) {
display_hours = (hours 0) ? “+0″+hours : “+”+hours; // positive
}
————————————————————————————————————
Thanks Josh Fraser once again for you script.
It really cool! thanks!
I do have a question which is – does it detect the summer time for EU / Asian countries as well?
Jason,
Yes, as long as the time is set correctly on the local computer.
Hi, I have a question:
Because javascript is a client side script, this timezone detection actually occurs after the first request and response from the server, when the browser loads this script and executes it. My problem is I want to send the first request with timezone info, guess there’s no way to do that, huh?
Richard,
A couple tricks to be able to automatically use their timezone on the server side:
– get the timezone on a page that is visited earlier and save it into a session cookie
– save the timezone and force a refresh on a page
– save the data to the server via AJAX
What are you trying to do exactly? I may be able to suggest a better fitting solution to your problem.
Thanks bunches!
Have you or anyone found a mapping to the abbreviations? I am having a hard time getting it from the internet.
Raj,
The best resource I know of is:
http://www.twinsun.com/tz/tz-link.htm
There’s also a lot of useful information at:
http://us.php.net/manual/en/function.timezone-identifiers-list.php
Hope that helps!
“As I started reading up on the getTimezoneOffset code I realized it was too buggy to be used in any critical application. The function returned inconsistent results in different browsers and it never seemed to account for daylight savings time correctly. It quickly became clear that I was going to have to write my own script if I wanted this to work.”
Sorry but I think you are re-inventig the wheel. I tested this code in IE and FIREFOX they seem to return the same result for where I live 420, that’s PDT. what browsers did you use?
Tas, change the clock on your computer to Arizona time and see if you still feel that way.
Did change the clock to Arizona time and it’s still consistent results. 420 offsets in both IE 7 and FIREFOX Mozilla 5.0. win xp.
considering vancouver, bc is on PDT, it should match the time in Arizona. that’s why I get 420 offset each way which is correct.
are you suggesting Javascript has a bug that is not documented?
Tas,
So PDT and Arizona are both 420 minutes (7hrs) from GMT? I think we both know that’s not true. The reason you got the same value for 2 very different timezones is that the most browsers (older versions of IE don’t) go ahead and factor DST into the offset. This also means that you get different results depending on the time of year. My goal with writing this function was to make something that works in all browsers and returns consistent results regardless of the time of year. It also separates timezone offset and DST into separate variables — something that isn’t possible using only gettimezoneoffset().
Arizona time: (Arizona Time)
http://www.google.ca/search?hl=en&q=arizona+time&meta=
Vancouver time: (PDT)
http://www.google.ca/search?hl=en&q=vancouver+time&meta=
Vancouver and Phoenix are the same time. at the time I wrote this entry, it was 3:12pm. this will however change when we switch back to PST.
I don’t think it’s up to the browser, it’s up to the windows system to switch the DST settings, and the browser will pick up from the OS.
However I understand you will have issues if you are trying to get the TimeZone using getTimezoneOffset(), because as the function will only gives you the offset of where the computer is currently located compared to GMT as documentation states. You would however get different results in another time of the year if you are trying to guess the timezoe of the computer, but the function is not intended for that.
downloaded the index.html & detect_timezone.js today (06/01/2008)
==
bug?…
In the calculate_time_zone function…
“if (hemisphere >= 0) ” ….missing the IF’s starting {
and then also added } before the function end to properly end the prior ELSE
also needed to set DST with an “else”…
==
if (hemisphere >= 0) {
std_time_offset = daylight_time_offset;
dst = “1″; // daylight savings time is observed
}
else {
dst = “0″; // daylight savings time is not observed
}
}
var i;
===
looks like my above entries…screwed up other stuff…
dealing with the DST calcs…backed them out.
Why tie Hemisphere to whether the system is currently on DST?
and if not curently on DST my -6 CST-US would report as -6 CST-Central Am ???
===
my system (WIN-XP) has 5: (GMT -6:00 CST) entries
Central America
Central Time (US & Canada)
Central Time Guadalajara, Mexico city, Monterrey – New
Central Time Guadalajara, Mexico city, Monterrey – Old
Central Time Saskatchewan
===
If change my system to any – all go to CST US
===
also have bunches of other TZ’s in list, that are not in the OPTION list.
So this has not been updated, since all of the TZ changes from MS in 2007?
Mike,
No, that’s not a bug. It’s just an if-statement without braces.
You do bring up a good point that people should understand. This script works under the presumption that you are only wanting to store the GMT offset and the DST boolean.
This script condenses multiple timezones in order to have only 1 primary key on GMT offset/DST. While this usually works in practice, you do loose some accuracy in knowing an exact TZ.
I’m using the time zones from http://www.php.net/manual/en/function.timezone-abbreviations-list.php so I have a way of mapping the offset and DST to the zone (though I will not get the correct value for multiple time zones with the same offset and DST).
Currently, I won’t bother to extend your JS so that it determines which time zone to select via Ajax, but if I ever do, I’ll post back. If someone else does, I’m watching these comments and I’d like to see your results!
Ruben
Josh,
Great script. Is there anyway to modify the script to only use US timezones? I have the following timezones in my database, and I want to match the client to one of these timezones. The exceptions, Indiana and Arizona do not have their own timezone in my database, they simply fall into a standard zone. Thanks.
AKST ALASKAN STANDARD TIME -9
AST ATLANTIC STANDARD TIME -4
CST CENTRAL STANDARD TIME -6
EST EASTERN STANDARD TIME -5
HST HAWAII-ALEUTIAN STANDARD TIME -10
MST MOUNTAIN STANDARD TIME -7
PST PACIFIC STANDARD TIME -8
AKDT ALASKAN DAYLIGHT SAVING TIME -8
ADT ATLANTIC DAYLIGHT SAVING TIME -3
CDT CENTRAL DAYLIGHT SAVING TIME -5
EDT EASTERN DAYLIGHT SAVING TIME -4
PDT PACIFIC DAYLIGHT SAVING TIME -7
MDT MOUNTAIN DAYLIGHT SAVING TIME -6
[...] out a time zone by a single time zone offset. I only found a few implementations like discussed here, which try to guess the browser time zone in correctly. The Problem with this approach is, that you [...]
Hi Josh,
Thanks for the script! I got bit by the same problem as Rama (see post above), but this was an easy fix. Perhaps that patch could be rolled into the official code.
Thanks again,
–Will
Good call, Will. I’ve updated the code.
Excellent , I just read your blog post about when does daylight savings end it seems a very good recopilation from internet articles as wikipedia as other related when does daylight savings end books. Congrats on your blog, I dugged and stumble today Wednesday due to the great post about when does daylight savings end . Cheers Andy Colleman.
That’s good work!
Worked nicely! Thanks so much. I haven’t been looking forward to this bit, but it seems to have worked out.
John
Dude, sweet script!
Up and running in under 2 minutes and WAY BETTER than any other timezone dropdown I have found (and I have looked, A LOT).
Thank you, thank you, thank you!
Looks like you’ve said it’s ok, but I just want to confirm I can get permission to adapt your code for use with the PHP.JS equivalents library (see http://kevin.vanzonneveld.net/techblog/article/phpjs_namespaced/ ). I want to use it for the JavaScript equivalent of PHP’s localtime(). So, is it all right for us to use it under his MIT-style license? Thanks!
@Brett I’d be honored. Go for it! A comment with a link back to this blog would be appreciated.
Thanks! Will do. I’ve submitted the function with credits to Kevin, the site owner. He’s been busy setting up a new site, but he’s good about following up… take care, Brett
Awesome! Glad you found it useful. Be sure to subscribe. I've got some more good stuff coming.
hey sorry but im a total newb and learning this stuff currently in the select box you have ex.
-12:00,0
and others maybe havea ,1
what are those for?
You should read the comments, sli, you would have found the answer.
Josh himself said:
"The form is currently submitting the offset from GMT and a 0 or 1 for whether it supports DST or not. So Denver, CO is "-07:00,1". (-7 for the offset, 1 for DST boolean)."
On another topic, I found a little mistake: it's not "Nonosibirsk", it's "Novosibirsk".
[...] I required didn’t work. After much hunting through google I stumbled upon Josh Fraser’s Timezone Autodetection which addressed what I was after brilliantly except that it was a little too hard coded for my [...]
Awesome Josh, finally something worth using! I've amended this a little so that it can be used for function callbacks. Turning the html into an array. Full credit to yourself both in the source and the blog post -> http://www.julian-young.com/2009/06/21/javascript...
Thanks!
Nice job. Thanks for building on it and sharing your work.
Hi Josh,
I have this issue:
I am using Windows XP and Firefox. And I have set the timezone as GMT+2. Now the computer time is 9.54AM and your script outputs 'std_time_offset' as 2 which is correct.
Then when I click on the check box "Automatically adjust daylight saving changes" check box in Adjust Date/Time window in XP, the computer's time gets changed as 10:54AM. But your script still outputs 2. I think it should output 3.
Is there any way I can solve this?
Thanks.
No. It's outputting the correct values. The GMT offset is always the same. What you want to look at is the value for DST. If the DST flag is set, you should add 1to the GMT offset if you are in the summer months. If you do that, you'll get the 3 that you are expecting & still have access to the true offset later on. Make sense?
thanks, THANKS, THANKS!!!!
And one question. Is there somewhere a list of the timezones and the possible countries that fit that timezone? Sorry if i ask for too much.
Like this or something more technical? http://en.wikipedia.org/wiki/List_of_time_zones
I'm in the process of developing a database of timezones to tie PHP and Javascript timezones together nicely.
I'm really having trouble following this. The code looks awesome and you can get then get the timezone to the server-side… but what do you do with it? On Rails we have TZInfo, which has much more specific zones than the ones you're working with. Plus, some of the zones are already wrong (like Buenos Aires, which does again have DST). I'm really not following how you use this. The client-side code looks perfect, and the user has a timezone and everything. But how would then convert a time for the user's timezone? Wouldn't you have to know not whether they celebrate (hehe) DST ever, but instead whether they celebrate it right now?
Thanks for this code.
You're right — it's tough to do much with the values once you have them. This really deserves a follow-up post… I'll see what I can do.
Cool, looking forward to that. Thanks Josh!
Thanks lot. Nice script.
Thanks… awesome script.. saved a lot of my time
Awesome. Glad to hear it.
I don't understand why you need to create two dates and subtract them – wouldn't the internal Date engine just use the timezoneOffset to figure out the difference? In other words, what you are doing is the equivalent of taking jan1.getTimezoneOffset() and jun1.getTimezoneOffset(), no? can you give an example where the results of those two function calls is different from your code?
I found that you are actually using the date of July 1st to compare with January 1st, instead of using June 1st as you claimed. Although this has no impact on the end result, I would just like to point it out so that you may update your blog to correct it.
Here is the javascript code of yours:
var june1 = new Date(rightNow.getFullYear(), 6, 1, 0, 0, 0, 0); // june 1st
"6" actually means July here, because the parameter for the month starts with 0 for January and ends with 11 for December.
Zhibin
How do you go about solving the issue where you have multiple time zones with same offset and dst. I want to be able to uniquely identify the timezones.
I have also verified that the script does break if you set your computer timezone to Newfoundaland.
Hey Josh,
this looks like a very useable piece of js.
Since you posted it here, your intention probably is to share this and let others make use of this, right?
As you put just your name over it, gerenal copyright applies and one wouldn't legaly be able to use or redistribute it.
Most probably something like the BSD license would be appropriate for this work?
http://opensource.org/licenses/bsd-license.php
Notice the comment I put at the bottom "As with anything that I post on this blog, feel free to use this code however you want. Just don’t blame me if it breaks."
Since then I have started releases everything under the Apache 2.0 license.
Hi Josh,
really great work! I found 2 little bugs: in the convert function you have to take the absolute value of minutes to find the correct index. Then you will get the correct timezone for Newfoundland. And I think the entry for Tehran must be set to dst, right?
Hi excelent code,
I have some doubts in DST and timezones.
as per my requirment I have to check the server time and client time and they both should be in sync.
as of now I am going like this
checking the DST is enable or not in client machine and converting the server time and client time to GMT format and checking it.
Kindly let me know if my logic is wrong or any where I am missing anything.
is there way of chnaging time zone
Surely Sydney and Vladivostok are not the same time zone?!?!
You're right. They just both have the same GMT offset and both support DST — BUT at opposite times of the year. There really needs to be a follow up post to this because this method has so many flaws in it. It's ideal for getting a true GMT offset and the DST flag, but that's about it.
Thanks for the code, it was very useful!
wow, that is so amazing! Thank You!
For those looking for a php map to the select form here you go:
$timezones = array (
'-12:00,0' => 'Etc/GMT-12',
'-11:00,0' => 'Etc/GMT-11',
'-10:00,0' => 'US/Hawaii',
'-09:00,1' => 'US/Alaska',
'-08:00,1' => 'US/Pacific',
'-07:00,0' => 'US/Arizona',
'-07:00,1' => 'US/Mountain',
'-06:00,0' => 'Canada/Saskatchewan',
'-06:00,1' => 'US/Central',
'-05:00,0' => 'US/Indiana-Starke',
'-05:00,1' => 'US/Eastern',
'-04:00,1' => 'Canada/Atlantic',
'-04:00,0' => 'America/Caracas',
'-03:30,1' => 'Canada/Newfoundland',
'-03:00,1' => 'America/Godthab',
'-03:00,0' => 'America/Argentina/Buenos_Aires',
'-02:00,1' => 'Atlantic/South_Georgia',
'-01:00,1' => 'Atlantic/Azores',
'-01:00,0' => 'Atlantic/Cape_Verde',
'00:00,0' => 'Africa/Casablanca',
'00:00,1' => 'Europe/Dublin',
'+01:00,1' => 'Europe/Berlin',
'+01:00,0' => 'Africa/Algiers',
'+02:00,1' => 'Europe/Athens',
'+02:00,0' => 'Africa/Harare',
'+03:00,1' => 'Europe/Moscow',
'+03:00,0' => 'Asia/Kuwait',
'+03:30,0' => 'Asia/Tehran',
'+04:00,0' => 'Asia/Muscat',
'+04:00,1' => 'Asia/Baku',
'+04:30,0' => 'Asia/Kabul',
'+05:00,1' => 'Asia/Yekaterinburg',
'+05:00,0' => 'Asia/Karachi',
'+05:30,0' => 'Asia/Kolkata',
'+05:45,0' => 'Asia/Katmandu',
'+06:00,0' => 'Asia/Dhaka',
'+06:00,1' => 'Asia/Almaty',
'+06:30,0' => 'Asia/Rangoon',
'+07:00,1' => 'Asia/Krasnoyarsk',
'+07:00,0' => 'Asia/Bangkok',
'+08:00,0' => 'Asia/Hong_Kong',
'+08:00,1' => 'Australia/Perth',
'+09:00,1' => 'Asia/Yakutsk',
'+09:00,0' => 'Asia/Seoul',
'+09:30,0' => 'Australia/Darwin',
'+09:30,1' => 'Australia/Adelaide',
'+10:00,0' => 'Australia/Brisbane',
'+10:00,1' => 'Australia/Melbourne',
'+11:00,0' => 'Asia/Magadan',
'+12:00,1' => 'Pacific/Auckland'
'+12:00,0' => 'Pacific/Fiji',
'+13:00,0' => 'Pacific/Tongatapu');
Chris
how i can grab the value from combobox option and put in a php session?
you need to submit the form and store it server side or pass it through with an AJAX request