f:convertDateTime 支持 Java8 LocalDate / LocalDateTime? [复制]

Posted

技术标签:

【中文标题】f:convertDateTime 支持 Java8 LocalDate / LocalDateTime? [复制]【英文标题】:f:convertDateTime support for Java8 LocalDate / LocalDateTime? [duplicate] 【发布时间】:2015-08-04 09:35:38 【问题描述】:

JSF 核心标签f:convertDateTime 可以格式化java.util.Date 对象。 Date 类有许多不推荐使用的方法,Java 8 中出现了新的类来显示本地日期和时间:LocalDateTime 和 LocalDate。

f:convertDateTime 不能格式化 LocalDateTime 和 LocalDate。

有谁知道,如果有一个等效于 JSF 核心标签 convertDateTime 可以处理 LocalDateTime 对象?是否计划在未来的版本中提供支持,或者是否有替代标签可用?

【问题讨论】:

在得到支持之前,您可以使用转换器。 java.util.Date 的替代品(顺便说一句,不推荐使用)是 java.time.Instant,而不是 LocalDate 或其他 local 类型。 确定日期类中充满了不推荐使用的方法。但是现有的 f:convertDateTime 没有使用任何那些已弃用的方法,但是您的问题以某种方式暗示了这一点,这并不是很好。无论如何,JSF 2.3 将需要 Java 8,因此为 Java 8 时间 API 的新标准转换器创造了空间。 JSF 2.3 支持新类型localDatelocalDateTimelocalTimeoffsetTimeoffsetDateTimezonedDateTime 以支持Java 8 time API。但请记住,在使用这些新类型时,转换器属性 timeZone 将被忽略,因为新的时间 API 拥有确定正确时区所需的一切!另见What's new in JSF 2.3? 我自己创造了这种体验——即使在 JSF 2.3 中,对 java.time 的支持似乎也受到了一些限制......或者至少对我来说很奇怪。 【参考方案1】:

只需编写您自己的转换器并扩展javax.faces.convert.DateTimeConverter - 这样您就可以重用<f:convertDateTime> 支持的所有属性。它也将处理本地化。不幸的是,写一个带有属性的转换器有点复杂。

创建组件 首先编写您自己的扩展 javax.faces.convert.DateTimeConverter 的转换器 - 只需让超级调用完成所有工作(包括 locale-stuff)并将结果从/转换为 LocalDate。

@FacesConverter(value = LocalDateConverter.ID)
public class LocalDateConverter extends DateTimeConverter 
    public static final String ID = "com.example.LocalDateConverter";

    @Override
    public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String value) 
        Object o = super.getAsObject(facesContext, uiComponent, value);

        if (o == null) 
            return null;
        

        if (o instanceof Date) 
            Instant instant = Instant.ofEpochMilli(((Date) o).getTime());
            return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).toLocalDate();
         else 
            throw new IllegalArgumentException(String.format("value=%s could not be converted to a LocalDate, result super.getAsObject=%s", value, o));
        
    

    @Override
    public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value) 
        if (value == null) 
            return super.getAsString(facesContext, uiComponent,value);
        

        if (value instanceof LocalDate) 
            LocalDate lDate = (LocalDate) value;
            Instant instant = lDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
            Date date = Date.from(instant);
            return super.getAsString(facesContext, uiComponent, date);
         else 
            throw new IllegalArgumentException(String.format("value=%s is not a instanceof LocalDate", value));
        
    

然后在META-INF中创建一个文件LocalDateConverter-taglib.xml

<facelet-taglib version="2.2"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facelettaglibrary_2_2.xsd">

    <namespace>http://example.com/LocalDateConverter</namespace>
    <tag>
        <tag-name>convertLocalDate</tag-name>
        <converter>
            <converter-id>com.example.LocalDateConverter</converter-id>
        </converter>
    </tag>
</facelet-taglib>

最后,在web.xml注册taglib:

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/META-INF/LocalDateConverter-taglib.xml</param-value>
</context-param>

用法 要在 JSF 页面中使用新标签,请添加新标签库 xmlns:ldc="http://example.com/LocalDateConverter" 并使用标签:

<ldc:convertLocalDate type="both" dateStyle="full"/>

【讨论】:

如果您的目标是 JSF 2.x Facelets,而不是 Facelets 1.x,会更好。否则,您会将 JSF 2.x 初学者与旧的/已弃用的方式混淆。 但这就是较新的 JSF 实现应该工作的方式......看起来是一个很好的解决方案 - 比 JSF 2.3 内部解决方案更好 JSF 2.3 现在支持 LocalDate 开箱即用:&lt;h:outputText value="#yourBean.yourLocalDateVar" &gt; &lt;f:convertDateTime type="localDate" dateStyle="long" locale="#yourBean.yourLocale" /&gt; &lt;/h:outputText&gt;

以上是关于f:convertDateTime 支持 Java8 LocalDate / LocalDateTime? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如果 bean 提供时区,f:convertDateTime 将显示错误的日期

JSF:<f:convertDateTime type="date" pattern="mm/DD/yyyy"/>

怎么让浏览器支持java?

Java支持的图像文件格式?

Java 8后的首个长期支持版本Java 11

如何将JAVA插件支持Chrome