'How to format java.time.LocalDateTime and java.time.LocalDate with pattern?
In the following snipped the property $F
is of class java.time.LocalDateTime
or java.time.LocalDate
.
<textField pattern="EE. dd.MM.yyyy">
<reportElement...>
</reportElement>
<textFieldExpression><![CDATA[$F{theLocalDateTime}]]></textFieldExpression>
</textField>
How can I format this property with textField pattern
in jasper reports?
Solution 1:[1]
To use the pattern attribute in current version of jasper-report for Date/Time object you need a java.util.Date
class or one of it's subclasses.
The solution is to convert java.time.LocalDate
and java.time.LocalDateTime
Converting to java.util.Date
<textField pattern="EE. dd.MM.yyyy">
<reportElement...>
</reportElement>
<textFieldExpression><![CDATA[java.util.Date.from($F{theLocalDate}.atStartOfDay(java.time.ZoneId.systemDefault()).toInstant())]]></textFieldExpression>
</textField>
<textField pattern="EE. dd.MM.yyyy">
<reportElement...>
</reportElement>
<textFieldExpression><![CDATA[java.util.Date.from($F{theLocalDateTime}.atZone(java.time.ZoneId.systemDefault()).toInstant())]]></textFieldExpression>
</textField>
Converting to java.sql.Timestamp
from java.time.LocalDate
<textField pattern="EE. dd.MM.yyyy">
<reportElement...>
</reportElement>
<textFieldExpression><![CDATA[java.sql.Timestamp.valueOf($F{theLocalDate}.atStartOfDay())]]></textFieldExpression>
</textField>
from java.time.LocalDateTime
<textField pattern="EE. dd.MM.yyyy">
<reportElement...>
</reportElement>
<textFieldExpression><![CDATA[java.sql.Timestamp.valueOf($F{theLocalDateTime})]]></textFieldExpression>
</textField>
Note: Applying pattern is always preferable solution, specially when exporting to excel since correct class will be passed to poi (hence excel will recognize column as a date and apply same formatting as in pattern)
Solution 2:[2]
As java.time
module is kind of complex and verbose, I usually create some variables which holds the compiled DateTimeFormatter for further use.
I want my reports to adapt to any Locale, so I don't use string literals for formatting.
I am using the report Locale, but you can choose your Locale with java.util.Locale.forLanguageTag("en-US")
, for example.
You can also change the java.time.format.FormatStyle
if needed
LocalDate formatter:
<variable name="dateFormatter" class="java.time.format.DateTimeFormatter">
<variableExpression><![CDATA[java.time.format.DateTimeFormatter
.ofLocalizedDate(java.time.format.FormatStyle.SHORT)
.withLocale($P{REPORT_LOCALE})
.withChronology(java.time.chrono.Chronology.ofLocale($P{REPORT_LOCALE}))]]></variableExpression>
</variable>
LocalDateTime formatter:
<variable name="dateTimeFormatter" class="java.time.format.DateTimeFormatter">
<variableExpression><![CDATA[java.time.format.DateTimeFormatter
.ofLocalizedDateTime(java.time.format.FormatStyle.SHORT)
.withLocale($P{REPORT_LOCALE})
.withChronology(java.time.chrono.Chronology.ofLocale($P{REPORT_LOCALE}))]]></variableExpression>
</variable>
Now I can format a LocalDate field this way:
$F{localDateField}.format($V{dateFormatter})
And a LocalDateTime field this way:
$F{localDateTimeField}.format($V{dateTimeFormatter})
Solution 3:[3]
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:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Community |
Solution 2 | Fabiano Bonin |
Solution 3 | RMM |