Having thought about this problem, I think I have a clean solution for implementing Timezone support without affecting current projects.
My starting point is that the solution should be backward compatible and should not break current projects. Also the change should be as little as possible.
I tested it and it works, also when my web application runs on Openshift, where it is hosted in TimeZone GMT-5:00 and me living in West Europe, GMT +1:00
Please give me your opinions.
I will describe the solution / proposal for the show.jspx views. But in the same way it can be implemented for the other views as well.
The essense of the change is that I added timeZone to the fmt:formatDate .. statement in WEB-INF/tags/form/fields/column.tagx/display.jspx:
Old:
<fmt:formatDate value="${object[field]}" pattern="${fn:escapeXml(dateTimePattern)}" />
New:
<fmt:timeZone value="${timeZone}">
<fmt:formatDate value="${object[field]}" pattern="${fn:escapeXml(dateTimePattern)}" timeZone="${timeZone}" />
</fmt:timeZone>
For this to work I also added the declaration and a default timeZone setting when not used.
<jsp:root xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:fmt="http://java.sun.com/jsp/jstl/fmt" xmlns:spring="http://www.springframework.org/tags" xmlns:form="http://www.springframework.org/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:output omit-xml-declaration="yes" />
<jsp:directive.attribute name="id" type="java.lang.String" required="true" rtexprvalue="true" description="The identifier for this tag (do not change!)" />
<jsp:directive.attribute name="object" type="java.lang.Object" required="true" rtexprvalue="true" description="The form backing object" />
<jsp:directive.attribute name="field" type="java.lang.String" required="true" rtexprvalue="true" description="The field name" />
<jsp:directive.attribute name="label" type="java.lang.String" required="false" rtexprvalue="true" description="The label used for this field, will default to a message bundle if not supplied" />
<jsp:directive.attribute name="date" type="java.lang.Boolean" required="false" rtexprvalue="true" description="Indicate that this field is of type java.util.Date" />
<jsp:directive.attribute name="calendar" type="java.lang.Boolean" required="false" rtexprvalue="true" description="Indicate that this field is of type java.util.Calendar" />
<jsp:directive.attribute name="dateTimePattern" type="java.lang.String" required="false" rtexprvalue="true" description="The date / time pattern to use if the field is a date or calendar type" />
========== Added declaration
<jsp:directive.attribute name="timeZone" type="java.lang.String" required="false" rtexprvalue="true" description="The timezone to use if the field is a date or calendar type" />
========== End
<jsp:directive.attribute name="render" type="java.lang.Boolean" required="false" rtexprvalue="true" description="Indicate if the contents of this tag and all enclosed tags should be rendered (default 'true')" />
<jsp:directive.attribute name="z" type="java.lang.String" required="false" description="Used for checking if element has been modified (to recalculate simply provide empty string value)" />
<c:if test="${empty render or render}">
<c:if test="${not empty object and empty label}">
<spring:message code="label_${fn:toLowerCase(fn:substringAfter(id,'_'))}" var="label" htmlEscape="false" />
</c:if>
<c:if test="${empty dateTimePattern}">
<c:set value="MM/dd/yyyy" var="dateTimePattern" />
</c:if>
========== Added default setting. Taking the timezone of the server!
<c:if test="${empty timeZone}">
<jsp:scriptlet>
jspContext.setAttribute("timeZone", java.util.TimeZone.getDefault().getID());
</jsp:scriptlet>
</c:if>
========== End
<div id="_${fn:escapeXml(id)}_id">
<label for="_${fn:escapeXml(field)}_id">
<c:out value="${label}" />
:
</label>
<div class="box" id="_${fn:escapeXml(id)}_${fn:escapeXml(field)}_id">
<c:choose>
<c:when test="${date}">
<spring:escapeBody>
========== Changed: added timeZone support for Date
<fmt:timeZone value="${timeZone}">
<fmt:formatDate value="${object[field]}" pattern="${fn:escapeXml(dateTimePattern)}" timeZone="${timeZone}" />
</fmt:timeZone>
========== End
</spring:escapeBody>
</c:when>
<c:when test="${calendar}">
<spring:escapeBody>
========== Changed: added timeZone support for Calendar
<fmt:timeZone value="${timeZone}">
<fmt:formatDate value="${object[field].time}" pattern="${fn:escapeXml(dateTimePattern)}" timeZone="${timeZone}" />
</fmt:timeZone>
========== End
</spring:escapeBody>
</c:when>
<c:otherwise>
<spring:eval expression="object[field]" />
</c:otherwise>
</c:choose>
</div>
</div>
<br />
</c:if>
</jsp:root>
When adding / changing these few lines, all the old code will continue to work.
You will have to apply these changes also to the WEB-INF/tags/form/fields/column.tagx file.
I you use gvNIX JQuery the same changes should be applied there also.
This is all the change you have to do!!!!
To add timezone support in all your show.jspx files:
1) add the extra timezone option for any date.
old:
<field:display date="true" dateTimePattern="${fileUpload_uploaddate_date_format}" field="uploadDate" id="s_com_myproject_onlineviewer_domain_FileUpload_uploadDate" object="${fileupload}" z="user-managed"/>
new:
<field:display date="true" dateTimePattern="${fileUpload_uploaddate_date_format}" field="uploadDate" id="s_com_myproject_onlineviewer_domain_FileUpload_uploadDate" object="${fileupload}" timeZone="${fileUpload_uploaddate_date_timezone}" z="user-managed"/>
2) In your controller specify your timeZone like:
uiModel.addAttribute("fileUpload_uploaddate_date_timezone", "Europe/Amsterdam");
In the spirit of Spring Roo's dataformat addDateTimeFormatPatterns(uiModel); I added addTimeZone(uiModel); .
In this method you can specify the source of the timezone.
In my web application I ask the user to specify his/her timezone when they reigster. All other workaround fail somewhere.
void addTimeZone(Model uiModel) {
uiModel.addAttribute("fileUpload_uploaddate_date_timezone", UserUtils.geTimeZone());
}
BTW, an addTimeZone default method in the AspectJ controller could be as the sample below, leaving the programmer to be able to push in and alter it.
void FileUploadController.addTimeZone(Model uiModel) {
uiModel.addAttribute("fileUpload_uploaddate_date_timezone", TimeZone.getDefault().getID());
}