1

I need to reliably determine user's timezone in JavaScript. Majority of the userbase will be on low bandwidth & old browsers so I have to maintain backwards compatibility and keep data transfer to minimum. Ideally I would like to fetch user's timezone only at start of session (I use CAS for login so there is no login page), then send it back to server where I'll be able to store it in database. I have looked in jsTimezoneDetect library as well as various geolocation APIs (to retrieve location/timezone by user's IP) but each has its drawbacks:

  1. jsTimezoneDetect is not big, but I'd rather not include 5K of extra JS code on all my pages (there is no single login page!)
  2. Geolocation APIs (such as IPInfoDB) introduce dependency on external services, can be slow, and does not always guarantee me results

What is the simplest way to reliably and efficiently determine user's timezone, and send it back to my JSF app while using minimum bandwidth and browser's resources?

Onur Yıldırım
  • 32,327
  • 12
  • 84
  • 98
rootkit
  • 2,165
  • 2
  • 29
  • 43
  • 2
    Re 1: Note that it will be cached, so there is no network overhead for either the client or the server for including it in every page, only JS overhead for the client. – P Varga Feb 19 '13 at 17:34
  • 4
    I don't see how you're going to do better than jsTimezoneDetect without sacrificing accuracy. – Pointy Feb 19 '13 at 17:34
  • This is not a JSF issue. This is just a JS issue. JSF is in the context of this question "just" a HTML/CSS/JS code generator. You'd still have had exactly the same problem when using a different server side language or framework generating the same kind of HTML/CSS/JS, like Spring MVC, PHP, ASP.NET-MVC, etc.. – BalusC Feb 19 '13 at 17:42
  • 1
    Have you take a look at this [answer](http://stackoverflow.com/a/1809974/564005) to detetermine timezone ? – Nicolas Labrot Feb 19 '13 at 18:00
  • 2
    `var timezoneOffset = (new Date()).getTimezoneOffset();` returns the time difference between UTC time and local time, in minutes. – Onur Yıldırım Feb 19 '13 at 18:40
  • I really like jsTimeZoneDetect. Also a very good suggestion on getting the time zone offset from Date object! – rootkit Feb 19 '13 at 18:49
  • BalusC, while I agree that determining timezone is purely JS issue, communicating it back to the server is not - it is JSF specific. – rootkit Feb 19 '13 at 18:50
  • Sending a JS variable to JSF is in no way related to determining the timezone in JS. You'd still have had exactly the same problem for any other kind of JS variable value. In essence, you've 2 completely independent problems which should be asked in separate questions: 1) How to determine timezone in JS. 2) How to set a JS variable as JSF model value. – BalusC Feb 19 '13 at 19:49

1 Answers1

0

After reading the comments I ended up with the following code:

<h:panelGroup layout="block" rendered="#{!applicationBean.timeZoneSet}">
    <h:outputScript name="timezone.js" library="js"></h:outputScript>
    <h:form style="display:none;">
        <p:inputText value="#{applicationBean.currentTimeZone}" widgetVar="wTZ" style="display:none;"></p:inputText>
        <p:remoteCommand autoRun="true" name="setTZ" onstart="var tzone=jstz.determine();wTZ.getJQ().val(tzone.name())" process="@form"></p:remoteCommand>
    </h:form>
</h:panelGroup>  

Backing bean:

public boolean isTimeZoneSet() {
    return getELValue(EL_TIMEZONE_FLAG, Boolean.class);
}

public void setTimeZoneSet(boolean val) {
    setELValue(EL_TIMEZONE_FLAG, val);
}

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void setCurrentTimeZone(String val) {
    User _user = getCurrentUser();
    _user.setTimeZone(val);
    _usersDAO.merge(_user);
    setTimeZoneSet(true);
}

@Transactional(propagation=Propagation.REQUIRES_NEW)
public String getCurrentTimeZone() {
 User _user = getCurrentUser();
     return _user.getTimeZone();
    }

where EL_TIMEZONE_FLAG is a session-scoped EL expression. The approach above ensures that I have a timezone set on User, only does it once per session, and loads any additional JS code only once per session as well

rootkit
  • 2,165
  • 2
  • 29
  • 43