- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-19-2018 11:26 AM
Hi,
We want to set the Timezone on the user table to the location the user is currently at. If they are on a business trip, and their computer is displaying the time in that location, we want the experience to be the same within ServiceNow.
My best thought is to include the moment-timezone library, guess their timezone, map it to the Timezones in ServiceNow, and then update the sys_user table. The Ideally this would be executed on login.
1. How do I call the moment-timezone library from a UI Script?
2. How do I execute a UI Script only after login?
3. Is there a different method to do this?
Thanks!
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-19-2018 04:41 PM
I've figured out how to reference the moment-timezone.js UI Script. I had to add moment.js UI Script separately since I don't believe it exists. Here is the code I've written to identify their timezone.
//TODO: Probably should provide a way for the user to block this
//TODO: Should we add a confirmation if we're gonna change their Timezone?
function sameTimezone(tz1, tz2){
var zone1 = moment.tz.zone(tz1),
zone2 = moment.tz.zone(tz2),
abbrs1 = zone1 ? zone1.abbrs : null,
abbrs2 = zone2 ? zone2.abbrs : null;
return tz1 === tz2 //the same string
||
(abbrs1 && abbrs1.indexOf(tz2) !== -1) //tz2 is an abbr and in tz1's abbrs
||
(abbrs2 && abbrs2.indexOf(tz1) !== -1) //tz1 is an abbr and in tz2's abbrs
||
(abbrs1 && abbrs2 && abbrs1 === abbrs2); //tz1 and tz2 are not null and both are the same abbrs
}
addLoadEvent( function() {
if(window.frameElement && window.location.pathname === '/login_redirect.do'){
ScriptLoader.getScripts(['moment.js.jsdbx','moment-timezone.js.jsdbx'], function(){
var timezones = [];
var guess = moment.tz.guess(true); //Guess the user's timezone
var snGuess;
//Get all the timezones from the form
var formTimezones = new GlideRecord('sys_choice');
formTimezones.addQuery('name', 'sys_user');
formTimezones.addQuery('element', 'time_zone');
formTimezones.addQuery('inactive', 'false');
formTimezones.query();
while(formTimezones.next()){
timezones.push(formTimezones.value);
}
//If the guess is a timezone choice, use it.
if(timezones.indexOf(guess) !== -1){
snGuess = timezones[timezones.indexOf(guess)];
}else{
//Loop through the timezones and find one that is the same as our guess
for(var i=0; i<timezones.length; i++){
if(sameTimezone(guess, timezones[i])){
snGuess = timezones[i];
}
}
}
//If we've made a guess, lets grab the user's current timezone
if(snGuess){
var user = new GlideRecord('sys_user');
user.addQuery('sys_id', g_user.userID);
user.query();
if(user.next()){
//If their timezone currently and our guess are different, update it
//Note: If our guess is America/Los_Angeles, and their timezone is US/Pacific,
// it will not be changed since they are the same timezone.
if(!sameTimezone(snGuess, user.time_zone)){
user.time_zone = snGuess;
user.update();
}
}
}
});
}
});
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-19-2018 04:41 PM
I've figured out how to reference the moment-timezone.js UI Script. I had to add moment.js UI Script separately since I don't believe it exists. Here is the code I've written to identify their timezone.
//TODO: Probably should provide a way for the user to block this
//TODO: Should we add a confirmation if we're gonna change their Timezone?
function sameTimezone(tz1, tz2){
var zone1 = moment.tz.zone(tz1),
zone2 = moment.tz.zone(tz2),
abbrs1 = zone1 ? zone1.abbrs : null,
abbrs2 = zone2 ? zone2.abbrs : null;
return tz1 === tz2 //the same string
||
(abbrs1 && abbrs1.indexOf(tz2) !== -1) //tz2 is an abbr and in tz1's abbrs
||
(abbrs2 && abbrs2.indexOf(tz1) !== -1) //tz1 is an abbr and in tz2's abbrs
||
(abbrs1 && abbrs2 && abbrs1 === abbrs2); //tz1 and tz2 are not null and both are the same abbrs
}
addLoadEvent( function() {
if(window.frameElement && window.location.pathname === '/login_redirect.do'){
ScriptLoader.getScripts(['moment.js.jsdbx','moment-timezone.js.jsdbx'], function(){
var timezones = [];
var guess = moment.tz.guess(true); //Guess the user's timezone
var snGuess;
//Get all the timezones from the form
var formTimezones = new GlideRecord('sys_choice');
formTimezones.addQuery('name', 'sys_user');
formTimezones.addQuery('element', 'time_zone');
formTimezones.addQuery('inactive', 'false');
formTimezones.query();
while(formTimezones.next()){
timezones.push(formTimezones.value);
}
//If the guess is a timezone choice, use it.
if(timezones.indexOf(guess) !== -1){
snGuess = timezones[timezones.indexOf(guess)];
}else{
//Loop through the timezones and find one that is the same as our guess
for(var i=0; i<timezones.length; i++){
if(sameTimezone(guess, timezones[i])){
snGuess = timezones[i];
}
}
}
//If we've made a guess, lets grab the user's current timezone
if(snGuess){
var user = new GlideRecord('sys_user');
user.addQuery('sys_id', g_user.userID);
user.query();
if(user.next()){
//If their timezone currently and our guess are different, update it
//Note: If our guess is America/Los_Angeles, and their timezone is US/Pacific,
// it will not be changed since they are the same timezone.
if(!sameTimezone(snGuess, user.time_zone)){
user.time_zone = snGuess;
user.update();
}
}
}
});
}
});
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-20-2018 02:43 PM
Some notes on this. Login check didn't work with SSO. I can't figure out how to catch the login event, so instead I just use a flag on window.top (window.top._sn_check_time_zone) which is good enough but a bit hacky.
I also had to use a more up to date moment-timezone library than the one included in ServiceNow to support more browsers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎05-24-2023 01:52 PM
Hey Mathieu,
Thank you for providing the solution. I'm working on implementing this now but I'm not able to get the script to run on login. Where did you end up setting the flag on window.top?
Thanks,
Justin
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎05-24-2023 02:18 PM
Hi Justin,
I didn't really get it to work on login, but instead it checks on a new window. This isn't ideal, but since we don't use a login page, it was the best I could come up with. This also specifically is targeted towards users on the backend, something similar would need to be done if this was also wanted to be done for users on portals by hiding the check somewhere like in a header or footer.
I've also attached an image to see the other configs I have on the sys_ui_script, such as Global=True and UI Type = Desktop.
//TODO: Probably should provide a way for the user to block this
//TODO: Should we add a confirmation if we're gonna change their Timezone?
function sameTimezone(tz1, tz2){
var zone1 = moment.tz.zone(tz1),
zone2 = moment.tz.zone(tz2),
abbrs1 = zone1 ? zone1.abbrs : null,
abbrs2 = zone2 ? zone2.abbrs : null;
return tz1 === tz2 //the same string
||
(abbrs1 && abbrs1.indexOf(tz2) !== -1) //tz2 is an abbr and in tz1's abbrs
||
(abbrs2 && abbrs2.indexOf(tz1) !== -1) //tz1 is an abbr and in tz2's abbrs
||
(abbrs1 && abbrs2 && abbrs1 === abbrs2); //tz1 and tz2 are not null and both are the same abbrs
}
addLoadEvent( function() {
if(!('_sn_checked_time_zone' in window.top)){
ScriptLoader.getScripts(['moment.js.jsdbx','moment-timezone-0.5.17.js.jsdbx'], function(){
var timezones = [];
var guess = moment.tz.guess(true); //Guess the user's timezone
var snGuess;
//Get all the timezones from the form
var formTimezones = new GlideRecord('sys_choice');
formTimezones.addQuery('name', 'sys_user');
formTimezones.addQuery('element', 'time_zone');
formTimezones.addQuery('inactive', 'false');
formTimezones.query();
while(formTimezones.next()){
timezones.push(formTimezones.value);
}
//If the guess is a timezone choice, use it.
if(timezones.indexOf(guess) !== -1){
snGuess = timezones[timezones.indexOf(guess)];
}else{
//Loop through the timezones and find one that is the same as our guess
for(var i=0; i<timezones.length; i++){
if(sameTimezone(guess, timezones[i])){
snGuess = timezones[i];
}
}
}
//If we've made a guess, lets grab the user's current timezone
if(snGuess){
var user = new GlideRecord('sys_user');
user.addQuery('sys_id', g_user.userID);
user.query();
if(user.next()){
//If their timezone currently and our guess are different, update it
//Note: If our guess is America/Los_Angeles, and their timezone is US/Pacific,
// it will not be changed since they are the same timezone.
if(!sameTimezone(snGuess, user.time_zone)){
user.time_zone = snGuess;
user.update();
}
}
}
window.top._sn_checked_time_zone = true;
});
}
});