JSF convertDateTime с часовым поясом в формате данных - PullRequest
14 голосов
/ 19 августа 2011

Попытка вывести список элементов в таблице данных, например:

<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>

Всегда форматирует время в GMT.Это работает, как и ожидалось, если я использую строковую константу или бин, который не является переменной с датой (например, '# {mybean.timeZone}').

1 Ответ

25 голосов
/ 19 августа 2011

К сожалению, такова природа тегов <f:xxx>. Когда должно быть построено представление, создается единственный экземпляр тега, в котором создается экземпляр преобразователя. Все его атрибуты были прочитаны и установлены только один раз. В момент построения представления #{item} разрешается в null (доступно только при визуализации представления), поэтому атрибут timeZone будет null, а затем по умолчанию будет UTC. Когда необходимо отобразить представление, один и тот же экземпляр преобразователя используется повторно для каждой строки таблицы.

Есть несколько способов решить эту проблему. Я могу придумать собственный преобразователь или функцию EL. Я думаю, что пользовательский преобразователь, в конце концов, является лучшим, так как он также может быть повторно использован во входных компонентах. Следующий зарезервированный пример должен сработать для вас (nullchecks и on для краткости опущены):

@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);
    }

}

, который можно использовать как

<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>

Таким образом, часовой пояс разрешается при каждом вызове конвертера, а не во время его создания.


Обновление : 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...