Unless I'm missing something it seems that there is no way to get the current time zone?? I know there are third party libs to get the olson name.. I just thought this would be included.
moment.tz().zoneName()
moment.tz(new Date()).zoneName()
moment.tz(new Date()).zone()
See #55 as well.
This is planned, but I haven't had time to implement it yet.
Hi, I'd like this feature as well. A couple of questions:
zoneName() and zoneNames()?Yeah, I think the api would be something like moment.tz.localZones() to return a list of possible matches and moment.tz.localZone() to return the first item from that list.
Fortunately, this can be a one-time calculation, as the user's timezone won't change without a refresh.
var cachedLocalZones;
function localZones () {
if (!cachedLocalZones) {
cachedLocalZones = calculateLocalZones()
}
return cachedLocalZones.slice(); // always return a copy
}
function localZone () {
return localZones().pop();
}
As far as the actual logic for calculating the local timezone, I was thinking something along these lines.
First Pass
Create Date objects for Jan 1 and Jul 1 of the current year.
var currYear = new Date().getFullYear();
var jan = new Date(currYear, 0, 1);
var jul = new Date(currYear, 6, 1);
Get the offsets for those dates using getTimezoneOffset.
var janOffset = jan.getTimezoneOffset();
var julOffset = jul.getTimezoneOffset();
Filter out zones which do not match the Jan and Jul offsets. See http://momentjs.com/timezone/docs/#/zone-object/offset/
zone.offset(jan) === janOffset && zone.offset(jul) === julOffset
That should filter down the list pretty significantly.
Second Pass
This pass is where things can get a bit more hairy, @mj1856, you should weigh in on this as I think you have more knowledge here. I don't know if we can check any more than just the current year in this step as browser timezone rules are unreliable for previous years.
For each zone that made it through the first pass, check the offset right before and after the untils for that year.
for (var i = 0; i < zone._untils.length; i++) {
if (
isCurrentYear(zone._untils[i])) {
(new Date(zone._untils[i] - 1000).getTimezoneOffset() === zone._offsets[i]) &&
(new Date(zone._untils[i] + 1000).getTimezoneOffset() === zone._offsets[i + 1])
) {
// zone makes it through pass
}
}
I think that should get most of the way there. This doesn't provide a way to prefer one zone alias over another, so we may have to add support for adding a list of preferred names to get America/Los_Angeles instead of US/Pacific for example.
As far as testing this functionality, I think we should mock Date.prototype.getTimezoneOffset to output the offsets that we want.
var getTimezoneOffset = Date.prototype.getTimezoneOffset;
exports.localZones = {
tearDown : function () {
Date.prototype.getTimezoneOffset = getTimezoneOffset;
},
someTest : function () {
Date.prototype.getTimezoneOffset = function () {
return this > someTimestamp ? 420 : 480;
};
}
};
I found this, also see the first comment to that answer...
I wonder, wouldn't it work if we just retrieved the standard timezone offset (without DST if it's in effect) and returned all zones with the same timezone offset? To borrow from the example in the link above:
We are trying to get the smallest array possible with localZones, so we should try to eliminate as many zones as we can. The southern hemisphere has DST during the northern hemisphere's winter, so checking both Jan and Jul will help eliminate those.
moment.tz([2014, 0, 1], 'Africa/Windhoek').format('MMM Z'); // Jan +02:00
moment.tz([2014, 6, 1], 'Africa/Windhoek').format('MMM Z'); // Jul +01:00
moment.tz([2014, 0, 1], 'Europe/Berlin').format('MMM Z'); // Jan +01:00
moment.tz([2014, 6, 1], 'Europe/Berlin').format('MMM Z'); // Jul +02:00
Alright. I'll go ahead an proceed with an initial implementation in a couple of days unless @mj1856 (or someone else) gets there first. :)
Another pass we could add is to check if the Jan and Jul Date objects contain the timezone abbreviation in their toString value.
new Date().toString(); //Wed Nov 05 2014 09:25:33 GMT-0800 (PST)
Date.prototype.toString does not always contain a timezone abbreviation, so we'll have to ignore this pass if it doesn't yield any results.
@elad - Go for it. I'm swamped at the moment. :)
Hi Guys! You can check how jstimezonedetect doest it!
@franleplant - Yes, we're well aware of jstimezonedetect. There's also an effort at https://github.com/Canop/tzdetect.js to take the same approach within the moment-timezone data.
The bigger problem is that as time goes on, the detection tests have to be updated. Due to the ECMAScript issue, tests around historical dates don't always work. So jstz, and anything else, has to rely on _current_ tz rules. (see https://github.com/moment/moment/issues/831 and http://codeofmatt.com/2013/06/07/javascript-date-type-is-horribly-broken/).
Some browsers that support the ECMAScript Internationalization API (ECMA-402) can easily get the time zone from the host directly. (I say _some_ because Internet Explorer supports that API, but doesn't support the provision for reporting IANA time zones.)
Intl.DateTimeFormat().resolvedOptions().timeZone
Thanks for all the information @mj1856
Im currently working on a private app that needs to support Different timezones, and timezone selection, and let me tell you that it is no trivial task.
Thanks to moment.js and moment-timezone its easier though!
Fran
Would love to see this get put in place! I just went through some troubles trying to figure this out today. I ended up using jstz with moment-timezone as follows
var someTimeFromUTC = moment('2014-11-19T08:00:00Z');
var tzName = jstz.determine().name(); // America/Los_Angeles
var localTime = moment(someTimeFromUTC).tz(tzName)
var formatedTime = localTime.format('llll z'); // Tue, Nov 19, 2014 8:00AM PST
All I really wanted to do was to be able to format my time with the abbreviated time zone. I saw that was depreciated in moment.js in lieu of creating moment-timezone however the functionality doesn't seem to exist anymore.
@elad Did you get a chance to wire up a working protoype for this feature.. I can give it a shot, if you haven't done a lot of progress on it already. Thanks!
@kashifshamaz21 please do! Unfortunately I haven't had a chance to get to it yet. :(
Hello,
This feature would be awsome!
+1000
Check this code
http://stackoverflow.com/questions/19420582/detect-the-id-of-the-current-user-timezone-using-moment-js
https://github.com/Canop/tzdetect.js
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;
}
};
If you just want one timezone id, simply use
var tzid = tzdetect.matches()[0];
I love the idea of having a function that can be used directly against the moment-timezone data, rather than jsTimeZoneDetect, which has it's own data. However, I'm not convinced that the Canop/tzdetect solution is complete enough to be useful.
Running it on my computer, which is Windows 8.1, Chrome latest, in US Pacific time, I get:
["America/Dawson", "America/Ensenada", "America/Los_Angeles", "America/Tijuana",
"America/Vancouver", "America/Whitehorse", "Canada/Pacific", "Canada/Yukon",
"Mexico/BajaNorte", "PST8PDT", "US/Pacific", "US/Pacific-New"]
jsTimeZoneDetect gives the correct result of America/Los_Angeles.
I'd love to be proven wrong, but I'm fairly certain that any solution other than the Ecma Intl API (in supported browsers) will have problems. The mere fact that ECMAScript 5.1 hides all non-current DST transitions makes it near impossible to properly interrogate the Date object for time zone information.
Until this gets fixed you can use Intl.DateTimeFormat().resolvedOptions().timeZone on latest Chrome & FF
@emorikawa - Chrome, yes. FF - no. I also believe it works in Opera, but not IE. Not sure about Safari.
+1 ! with todays SaaS apps displaying analytics everywhere it's a must-have feature. Thank you if you cant make it !
Gonna try and jump in and implement this. I have a lot of docs to read to orient myself though. @elad @timrwood if you have any updates other than what you have specified above let me know!
I opened a PR for this at #220.
@mj1856 good call on Intl.DateTimeFormat().resolvedOptions().timeZone!
@timrwood I'm using moment-timezone 0.3.0. Is the capability of getting client/browser timezone implemented? I'm currently using jstz-detect to detect the timezone (Country/City) and using that with moment.tz.* functions.
@gnansu - no, it is not yet implemented in the release. You can try the code in PR #220, but we've still got some things to work out before we are ready to merge and release it.
@mj1856 Thanks Matt for the information. Looking forward to the new additions.
Fortunately, this can be a one-time calculation, as the user's timezone won't change without a refresh.
@timrwood that's not true all the time: try on Chrome (OSX), it will update the timezone dynamically without refresh.
@avetisk, that's a bummer, we'll have to add some cache checks to make sure we aren't getting stale data.
Closing in favor of https://github.com/moment/moment-timezone/pull/220
the great white hope:
Intl.DateTimeFormat().resolvedOptions().timeZone
Unfortunately I tried it with my 4 browsers. Safari (today's) has no Intl, FF41 and IE11 have it but returns undefined (which is documented as 'the current timezone' thanx a lot). Chrome has it but use 'resolved' in place of 'resolvedOptions()'. So the only one that works, is the improperly implemented one. :-(
Why is this so hard? It would be easy to implement once you've done the rest of Intl. EZ.
Have implemented this feature,i noted that is issue have been posted more than one year,but i can find any info about this in moment-timezone's documents.
@argb is right, it looks like it's done.
@timrwood @mj1856 this was closed in favor of #220. #220 is now closed because it was moved to #256 which is merged, but only to guess-timezone. I just saw there's progress (#274), but there's no open tracking issue for this as a feature, or is there?
This has been released in [email protected] as moment.tz.guess().
@timrwood I tried using moment.tz.guess() it works however it doesn't detect it automatically the page has to reload first. is there a way to get the timezone immediately without having to reload the page?
@Ihs88999 - There's nothing special about that function in terms of loading. Perhaps you just aren't loading moment and moment-timezone correctly? We don't know anything about your code or environment, so it's hard to say.
@timrwood Suggestions for how to use this outside the browser?
@kevinSuttle process.env.TZ
@bcherny is there a trick to get TZ on OSX?
$ node
> process.env.TZ
undefined
I'm using OS X 10.11.6
$ node --version
v5.4.1
Looks like OSX doesn't define it. I just published node-timezone, which I tested on OSX and Ubuntu.
This works for me inside of Webpack: https://github.com/moment/moment-timezone/issues/138#issuecomment-77792958
Most helpful comment
This has been released in
[email protected]asmoment.tz.guess().