JSF convertDateTime与数据表中的时区

Per*_*son 14 datatable jsf timezone

尝试输出数据表中的项列表,如下所示:

<t:dataTable value="#{mybean.list}" var="item">
        <h:column>
            <h:outputText value="#{item.time}">
                <f:convertDateTime pattern="yyyy-MM-dd HH:mm:ssZ"  timeZone="#{item.timeZone}" />
            </h:outputText>
        </h:column>
</t:dataTable>
Run Code Online (Sandbox Code Playgroud)

它总是以GMT格式化时间.如果我使用字符串常量或不是datatable变量的bean(如'#{mybean.timeZone}'),它会按预期工作.

Bal*_*usC 25

不幸的是,这就是<f:xxx>标签的本质.在构建视图时,将构建转换器实例化的标记的单个实例.它的所有属性都只被读取和设置一次.在构建视图时,#{item}解析为null(它仅在呈现视图期间可用),因此该timeZone属性将null默认为UTC.当要呈现视图时,对表的每一行重用相同的转换器实例.

有几种方法可以解决这个问题.我可以想到自定义转换器或EL功能.我认为自定义转换器是最好的,因为它也可以在输入组件中重用.下面的启动示例应该适合您(nullchecks和为简洁而省略):

@FacesConverter("extendedDateTimeConverter")
public class ExtendedDateTimeConverter extends DateTimeConverter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        setPattern((String) component.getAttributes().get("pattern"));
        setTimeZone(TimeZone.getTimeZone((String) component.getAttributes().get("timeZone")));
        return super.getAsObject(context, component, value);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        setPattern((String) component.getAttributes().get("pattern"));
        setTimeZone(TimeZone.getTimeZone((String) component.getAttributes().get("timeZone")));
        return super.getAsString(context, component, value);
    }

}
Run Code Online (Sandbox Code Playgroud)

可以用作

<h:outputText value="#{item.time}">
    <f:converter converterId="extendedDateTimeConverter" />
    <f:attribute name="pattern" value="yyyy-MM-dd HH:mm:ssZ" />
    <f:attribute name="timeZone" value="#{item.timeZone}" />
</h:outputText>
Run Code Online (Sandbox Code Playgroud)

这样,每次调用转换器时都会解析时区,而不是在构造期间.


更新:OmniFaces<o:converter>完全解决了这个问题,无需自定义转换器.

<h:outputText value="#{item.time}">
    <o:converter converterId="javax.faces.DateTime" pattern="yyyy-MM-dd HH:mm:ssZ" timeZone="#{item.timeZone}" />
</h:outputText>
Run Code Online (Sandbox Code Playgroud)