My web app caches the data it sends to the clients so that if another client asks for the same data while nothing's changed, I send them the same data and it's pretty fast. The problem there is that it's timed data, and that means that all the clients around the world have been seeing the data in Chicago-time. Not really what I want for a good user experience in New York and London.
So I needed to see if there was a way I could bring client localized time to the app without losing all the advantages of the cached datasets. If I passed in the location (region/TimeZone) of the client to the servlet, then I'd have a different cached response for each request in a region. Not ideal. Much better to be able to do it client-side. But that begs the question of how to do this?
One way would be to have the server generate GMT times for everything and then each client would have to deal with adjusting the data to the local time, and I almost went with that, but I decided to stick with the Chicago-based time and then add the GMT Offset in the package from the server.
If the client has the GMT Offset of the server, then it can see if it's GMT Offset is different from the server's, and if so, it can calculate the difference and apply it to all the times in the result set. Nice... for the Chicago users (the vast majority) there would be no change as the changes would be skipped, but for New York and London, I could update the data.
OK, how to do this?
Well... the first part is to generate the GMT Offset in the servlet. Since the offsets in Java and JavaScript have an opposite sign, the right thing to do is to standardize on one and then make the other 'fit' it. I chose to stick with the JavaScript version, so my Java servlet code looks like this:
public UserInfo() {
// don't forget to call the super's constructor - no matter what
super();
// start by getting the GMT offset in mins for this guy
GregorianCalendar now = new GregorianCalendar();
if (now != null) {
_gmtOffsetMins = (int)(-1)*(now.get(now.ZONE_OFFSET)
+ now.get(now.DST_OFFSET))/60000;
}
}
where my UserInfo is passed back to the client AJAX with some information about the validated user. Now it's got the GMT Offset in the same sign as JavaScript expects. Good. Now all I needed to do was convert the data that needed converting.
I created a JavaScript function:
function convertTimesToLocalTime() {
// get the time right now for the correct offset
var now = new Date();
var localOffset = now.getTimezoneOffset();
if (localOffset != userInfo.gmtOffsetMins) {
// get the soze of the table as we're going to need it
var rowCnt = graphData.getNumberOfRows();
// now let's run through the first column anc update the times
for (var r = 0; r < rowCnt; ++r) {
var obj = graphData.getValue(r, 0);
if (obj instanceof Date) {
// get the time from the server into UTC
var utc = obj.getTime() + userInfo.gmtOffsetMins * 60000;
// make this UTC time into a local time
graphData.setValue(r, 0, new Date(utc - localOffset * 60000));
}
}
}
}
With this, I don't do anything unless I need to, and when I have to, I get the time data in the local timezone - regardless of where that is! I'm really happy with this as it adds a little overhead to the client, but it allows my server to not mess with localizations and keeps the cache intact. Nice.