Auto detect a time zone with JavaScript
June 8th, 2007 by Josh FraserThis 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:
var myDate = new Date(); 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 rightNow = new Date();
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.
var june1 = new Date(rightNow.getFullYear(),
6, 1, 0, 0, 0, 0);
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.


June 20th, 2007 at 3:34 am
Hey this script really helped me .. thanks
June 26th, 2007 at 8:38 pm
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.
June 26th, 2007 at 10:59 pm
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
June 27th, 2007 at 12:37 am
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.
July 8th, 2007 at 3:50 am
Hi! Good site respect! Visit welivetogether.com and addictinggames.com Thanks!
August 16th, 2007 at 8:49 am
Thanks for putting up this script! It was really helpful and saved me a lot of time.
September 15th, 2007 at 1:21 pm
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?
September 15th, 2007 at 1:32 pm
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.
September 15th, 2007 at 5:15 pm
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.
September 15th, 2007 at 5:43 pm
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.
December 5th, 2007 at 5:26 pm
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!
December 5th, 2007 at 8:23 pm
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.
January 8th, 2008 at 2:31 pm
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?
January 8th, 2008 at 3:14 pm
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.
February 1st, 2008 at 5:05 am
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.
February 23rd, 2008 at 7:38 pm
It really cool! thanks!
I do have a question which is - does it detect the summer time for EU / Asian countries as well?
February 23rd, 2008 at 8:14 pm
Jason,
Yes, as long as the time is set correctly on the local computer.
March 25th, 2008 at 8:30 pm
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?
March 26th, 2008 at 8:37 am
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.
April 15th, 2008 at 6:36 pm
Thanks bunches!
Have you or anyone found a mapping to the abbreviations? I am having a hard time getting it from the internet.
April 16th, 2008 at 9:56 pm
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!
May 9th, 2008 at 6:33 pm
“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?
May 12th, 2008 at 8:48 am
Tas, change the clock on your computer to Arizona time and see if you still feel that way.
May 12th, 2008 at 1:41 pm
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?
May 12th, 2008 at 2:09 pm
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().
June 1st, 2008 at 1:18 pm
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
June 1st, 2008 at 3:47 pm
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?
June 2nd, 2008 at 9:37 am
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.
July 15th, 2008 at 9:27 pm
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