I've stumpled over the same problem and I solved it by introducing a custom function to JasperReports. So at the end it can be used as following on LocalDate, LocalTime, LocalDateTime, just anything implementing TemporalAccessor:
FORMAT_DATETIME($F{someLocalDate}, "dd.MM.yyyy")
FORMAT_DATETIME($F{someLocalDateTime}, "dd.MM.yyyy HH:mm")
FORMAT_DATETIME($F{someLocalTime}, "HH:mm")
To achieve that create following files:
Function Category. This is needed so the Expression Editor of the jasper report designer shows the function, under the set category
package org.example.jrfunctions;
import net.sf.jasperreports.functions.annotations.FunctionCategory;
@FunctionCategory()
public class LocalDateTime {
}
Class with the function(s) (more functions could be added)
package org.example.jrfunctions;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import net.sf.jasperreports.functions.annotations.Function;
import net.sf.jasperreports.functions.annotations.FunctionCategories;
import net.sf.jasperreports.functions.annotations.FunctionParameter;
import net.sf.jasperreports.functions.annotations.FunctionParameters;
@FunctionCategories({
org.example.jrfunctions.LocalDateTime.class })
public class JRDateTimeFunctions {
@Function("FORMAT_DATETIME")
@FunctionParameters({
@FunctionParameter("temporalObject"),
@FunctionParameter("format")
})
public static String FORMAT_DATETIME(TemporalAccessor temporalObject, String format) {
if (temporalObject == null) {
return null;
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
return formatter.format(temporalObject);
}
}
The following file needs to be in the same directory as the above two, and all the properties for every parameter needs to be set. Otherwise the jasper report designer will not show the custom functions in the expression editor:
jasperreports_messages.properties
org.example.jrfunctions.JRDateTimeFunctions.FORMAT_DATETIME.description = Formats the Temporal Object according to format
org.example.jrfunctions.JRDateTimeFunctions.FORMAT_DATETIME.name = Format Temporal Accessor (Object)
org.example.jrfunctions.JRDateTimeFunctions.FORMAT_DATETIME.temporalObject.name = Temporal Accessor
org.example.jrfunctions.JRDateTimeFunctions.FORMAT_DATETIME.temporalObject.description = Object to format
org.example.jrfunctions.JRDateTimeFunctions.FORMAT_DATETIME.format.name = Format
org.example.jrfunctions.JRDateTimeFunctions.FORMAT_DATETIME.format.description = Fromat
org.example.jrfunctions.LocalDateTime.name=Local Date & Time
org.example.jrfunctions.LocalDateTime.description=
The following file needs to be in the classpath. I put it into src/main/resources
jasperreports_extension.properties
net.sf.jasperreports.extension.registry.factory.functions=net.sf.jasperreports.functions.FunctionsRegistryFactory
net.sf.jasperreports.extension.functions.jrdatetimefunctions=org.example.jrfunctions.JRDateTimeFunctions
Now the custom function should be shown in the expression editor, and compile without any problems.
More infos:
DateTimeFormatter.ofPattern(myPattern).format($F{thedatetime})
. – SprinkleLocalDateTime
. Thejava.sql.Timestamp
class was replaced byjava.time.Instant
orOffsetDateTime
(with its offset set to UTC). See this Question, What's the difference between Instant and LocalDateTime?. – Barbados