Determining Time Zone Offset in a Salesforce sControl
I ran into an issue today and I've encountered it in the past but I couldn't find the code I originally wrote to resolve the problem. For this reason, I am going to post the code and the issue here so I can find it again in the future. Additionally, it might prove useful for some other developers and they should feel free to take it from this post.
The issue is pretty simple. I needed to write a sControl to display a summary of Cases on a page with a bunch of other summaries. One of my filters on the query I wrote for this code was the Case CreatedDate. As you know, the CreatedDate is a DateTime field and, as such, the filter must be of a specific format including a date portion, a time portion and an offset (ie 1999-01-01T23:01:01+01:00).
So I needed to determine the offset of the person accessing the sControl so that the filters for my query were accurate based on the individuals time zone setting. Now I could have simply hard coded the offset but that wouldn't be the correct solution and inevitably someone would eventually determine that they were seeing cases in the summary that didn't truly belong.
It would be great if salesforce.com actually created a time zone offset merge field but since that is not (currently) an option I decided to use the getUserInfo call in conjunction with the DescribeSObjects call. The getUserInfo call would provide me with the time zone setting for the running user and I could then take that value and compare it to the TimeZoneSidKey picklist from User via the DescribeSObjects call.
The AJAX toolkit provides the getUserInfo() call, which allows developers to quickly access an array of information about the running user (by running user I mean the person actually accessing the sControl and making run). The key field we need for the purposes of this write up is the time zone value. Please see the snippet of code below for how to access the Users time zone using this call.
var user = sforce.connection.getUserInfo(); //assign all of the getUserInfo information to a variable
user.userTimeZone; //specific value of time zone
Again, this getUserInfo call is very useful but the time zone value will only contain the country/region of the users time zone not the offset. If you were to alert the user.userTimeZone value from the snippet above it would look something like "America/Denver" or "Europe/Amsterdam." Now I think this is a bit misleading because if you go to any user record in your org and edit their time zone settings you'll see that the values contain more than just the country/region. Your selections would look something like "(GMT-07:00) Mountain Standard Time (America/Denver)" or "(GMT+01:00) Central European Time (Europe/Amsterdam)" if we were being consistent with my examples from earlier.
Anyway, based on the code above we now have the time zone text (for lack of a better way to describe the result of the getUserInfo call) but we still need to get the actual "+01:00" or "-07:00" offset for the user. To get the actual offset we will need to employ the DescribeSObjects call. Since we only care about a single value we will need to manipulate the call to return only the offset. That code is below:
//returns the offset for a passed timezone
function getOffset(usersTimeZone) {
var returnVal = ""; //variable for holding the offset after we find it
var oTable = sforce.connection.describeSObjects(["User"]); //connect to user table
var oFields = oTable[0].fields; //get all fields from that table
for (var a=0; a<oFields.length; a++) { //loop through all the fields
if (oFields[a].name=="TimeZoneSidKey") { //if the field is the time zone field
var oPicklistVals = oFields[a].picklistValues; //look at all the picklist values for field
for (var b=0; b<oPicklistVals.length; b++) { //loop through all picklist values
if (oPicklistVals[b].value == usersTimeZone) { //if the picklist value matches the time zone value passed to the function
returnVal = oPicklistVals[b].label.substring(oPicklistVals[b].label.indexOf("GMT")+3,oPicklistVals[b].label.indexOf(")")); //get the offset from the label
break; //kill the loop
}
}
}
}
return returnVal; //pass back the offset (it will look something like -05:00)
}
With these pieces of code you now have everything you need to get a users time zone offset for use in any sControl. I put the code together into a sample sControl so you could simply copy and paste the code into a new sControl inside your own org and see how it works. That code is below:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Time Zone Offset</title>
<link href="/sCSS/14.0/Theme2/common.css" type="text/css" media="handheld,print,projection,screen,tty,tv" rel="stylesheet">
<script src="/soap/ajax/14.0/connection.js" type="text/javascript"></script>
<script language="JavaScript" type="text/javascript">
function getOffsetValForPage() {
var user = sforce.connection.getUserInfo(); //assign all of the getUserInfo information to a variable
document.getElementById("name").innerHTML = user.userFullName; //display the name to the page
document.getElementById("timeZone").innerHTML = user.userTimeZone; //display the time zone to the page
var pHTML = getOffset(user.userTimeZone); //using only the time zone from the user get the offset
document.getElementById("timezoneOffset").innerHTML = pHTML; //display the offset to the page
}
//returns the offset for a passed timezone
function getOffset(usersTimeZone) {
var returnVal = ""; //variable for holding the offset after we find it
var oTable = sforce.connection.describeSObjects(["User"]); //connect to user table
var oFields = oTable[0].fields; //get all fields from that table
for (var a=0; a<oFields.length; a++) { //loop through all the fields
if (oFields[a].name=="TimeZoneSidKey") { //if the field is the time zone field
var oPicklistVals = oFields[a].picklistValues; //look at all the picklist values for field
for (var b=0; b<oPicklistVals.length; b++) { //loop through all picklist values
if (oPicklistVals[b].value == usersTimeZone) { //if the picklist value matches the time zone value passed to the function
returnVal = oPicklistVals[b].label.substring(oPicklistVals[b].label.indexOf("GMT")+3,oPicklistVals[b].label.indexOf(")")); //get the offset from the label
break; //kill the loop
}
}
}
}
return returnVal; //pass back the offset (it will look something like -05:00)
}
</script>
</head>
<body style="background-color:#F3F3EC;" onload="getOffsetValForPage()">
<table style="width: 100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td style="padding:2px 10px 2px 2px; text-align:right; font-size: 91%; font-weight: bold; color:#333; width: 17%;">Your Name</td>
<td style="padding:2px 2px 2px 10px; text-align:left; width:33%;" id="name"> </td>
</tr>
<tr>
<td style="padding:2px 10px 2px 2px; text-align:right; font-size: 91%; font-weight: bold; color:#333; width: 17%;">Your Time Zone</td>
<td style="padding:2px 2px 2px 10px; text-align:left; width:33%;" id="timeZone"> </td>
</tr>
<tr>
<td style="padding:2px 10px 2px 2px; text-align:right; font-size: 91%; font-weight: bold; color:#333; width: 17%;">Your Timezone Offset</td>
<td style="padding:2px 2px 2px 10px; text-align:left; width:33%;" id="timezoneOffset"> </td>
</tr>
</table>
</body>
</html>
As always, I appreciate that you've taken some time to read one of my posts. I hope you find the information useful and be sure to let me know if you have any questions.