Search code examples
jsflocaldatetime

f:convertDateTime with LocalDateTime throws "Cannot format given Object as a Date"


I have a local date time property:

private LocalDatetime date;

I want to show it in this format dd-MM-yyyy HH:mm:ss:

<h:outputText value="#{transaction.date}">
    <f:convertDateTime pattern="dd-MM-yyyy HH:mm:ss"/>
</h:outputText>

But I got this exception:

java.lang.IllegalArgumentException: Cannot format given Object as a Date

How is this caused and how can I solve it?


Solution

  • The <f:convertDateTime> defaults currently still to java.util.Date as expected date type and is currently not (yet?) capable of automatically detecting the date type. It will under the covers incorrectly continue to use java.text.SimpleDateFormat instead of java.time.format.DateTimeFormatter to format the LocalDateTime. This specific exception is coming from SimpleDateFormat.

    You need to explicitly set the type attribute of the <f:convertDateTime> tag to the desired date type if your actual date value is not a java.util.Date. You can find a list of supported types in in tag documentation:

    Name Required Type Description
    type false javax.el.ValueExpression
    (must evaluate to java.lang.String)
    Specifies what contents the string value will be formatted to include, or parsed expecting. Valid values are "date", "time", "both", "localDate", "localDateTime", "localTime", "offsetTime", "offsetDateTime", and "zonedDateTime". The values starting with "local", "offset" and "zoned" correspond to Java SE 8 Date Time API classes in package java.time with the name derived by upper casing the first letter. For example, java.time.LocalDate for the value "localDate". Default value is "date".

    So, in your specific case, setting it to localDateTime should fix it:

    <h:outputText value="#{transaction.date}">
        <f:convertDateTime type="localDateTime" pattern="dd-MM-yyyy HH:mm:ss"/>
    </h:outputText>
    

    In case it is output-only and you happen to use the utility library OmniFaces of version 3.6 or newer, then you can also use the #{of:formatDate()} function instead. It is capable of automatically detecting the date type and it currently supports all known instances of java.util.Date, java.util.Calendar and java.time.Temporal.

    #{of:formatDate(transaction.date, 'dd-MM-yyyy HH:mm:ss')}