I looked into this a bit and one problem is that there isn't a default TimeZone
set, which seems like an oversight; RequestContextUtils.getTimeZone(request)
should return the server's time zone if nothing else is available.
That's easy enough to fix; add a dependency injection in BootStrap.groovy
for the "localeResolver" bean and some code to set the default time zone in the resolver:
class BootStrap {
def localeResolver
def init = {
if (!localeResolver.defaultTimeZone) {
localeResolver.defaultTimeZone = TimeZone.getDefault()
// or hard-code to a known instance, e.g. TimeZone.getTimeZone('America/New_York')
}
}
}
There's not much documented about working with TimeZone
s in the Spring reference docs; there's actually a lot more information in the comments of the original feature request from 2005.
Grails overrides the default LocaleResolver
implementation of AcceptHeaderLocaleResolver
(which has no support for TimeZone
) and configures a SessionLocaleResolver
instead. This looks for a locale first in the session, then for a default value set on the resolver (by default null - it's not initialized by Grails), and finally it calls request.getLocale()
, which checks the Accept-Language
header. This is commonly set, as having localized text is a good thing. Additionally a LocaleChangeInterceptor
is configured, which looks for a "lang" param to suppport changing the Locale
. But there are no conventions for passing time zone information from the client.
The time zone id seems to me like something that you would ask for during user registration and store in the database with other profile information. Then when they authenticate, you can use the stored value if it exists and set it in the session where the LocaleResolver
will find it, e.g.
import org.springframework.web.servlet.i18n.SessionLocaleResolver
...
session[SessionLocaleResolver.TIME_ZONE_SESSION_ATTRIBUTE_NAME] =
TimeZone.getTimeZone(user.timeZoneId)
It is possible to get the user's local time and TimeZone in JavaScript and send it to the server via Ajax. For some examples see the links in this answer.