What I'm looking for is a way to detect the browser's timezone ID (as defined in the Olson tables) but I don't care for the exact ID, I just need the ID of a timezone that works the same as the user's one (for example "Europe/Rome" is fine if the user is in Paris).
I'm not interested in the current offset, I really need the timezone so that I can send it to the server to do computations for other dates (the server has the Olson tables too).
Theoretically, as I already use Moment.js timezone library and have included the Olson tables, I don't need anything else, but I don't find any API to do the detection. I don't know if it's hidden somewhere or if somebody has it already written. One of the problems is that the current timezone plugin seems to keep its data private.
I dont' want a solution based on the integration of yet another copy or extract of the Olson tables (which I would have to maintain), I know there are a few libraries duplicating them, I want to use the ones I already have in Moment.js.
moment now has the guess()
API as described here
I made a small script to do that detection. It starts by registering the ids of the available timezones, then, on a call to the matches
function tests all timezone ids for the current time and the times 4 and 8 months later (to filter out the timezones with different daylight rules) and five years before.
Here it is :
<script src="moment-with-langs.min.js"></script>
<script src="moment-timezone.min.js"></script>
<script src="moment-timezone-data.js"></script>
<script>
var tzdetect = {
names: moment.tz.names(),
matches: function(base){
var results = [], now = Date.now(), makekey = function(id){
return [0, 4, 8, -5*12, 4-5*12, 8-5*12, 4-2*12, 8-2*12].map(function(months){
var m = moment(now + months*30*24*60*60*1000);
if (id) m.tz(id);
return m.format("DDHHmm");
}).join(' ');
}, lockey = makekey(base);
tzdetect.names.forEach(function(id){
if (makekey(id)===lockey) results.push(id);
});
return results;
}
};
</script>
If you just want one timezone id, simply use
var tzid = tzdetect.matches()[0];
Demonstration
GitHub Repository : https://github.com/Canop/tzdetect.js
Update : The code here shown isn't compatible with the most recent versions of moment.js. Please refer to the GitHub repository for a maintained (free to use) code.
2017 Update: There's now an API in moment.js to guess the timezone. That's probably the best solution right now.
If you want to use the standard JavaScript API, you can use Intl.DateTimeFormat.resolvedOptions
where there is browser support:
Intl.DateTimeFormat().resolvedOptions().timeZone; // "America/Los_Angeles"
resolvedOptions
is currently (Jan 2016) available in all browsers except Safari on iOS and desktop: http://caniuse.com/#feat=internationalization
However, the timeZone
property is currently only available on Chrome.
There's a javascript tool that does just that :
https://github.com/entraigas/jstz
It seems to deal with timezones ambiguity also.
Combined with momentJS timezone, you can get the timezone and show formatted date :
var tzObj = jstz.determine();
var timezoneCode = tzObj.name();
console.log(moment.tz(timeZoneCode).format());