如何用模式格式化 java.time.LocalDateTime 和 java.time.LocalDate?

How to format java.time.LocalDateTime and java.time.LocalDate with pattern?

下面截取了属性$F是classjava.time.LocalDateTimejava.time.LocalDate.

<textField pattern="EE. dd.MM.yyyy">
    <reportElement...>
    </reportElement>
    <textFieldExpression><![CDATA[$F{theLocalDateTime}]]></textFieldExpression>
</textField>

如何在 jasper 报告中使用 textField pattern 格式化这个 属性?

要在当前版本的 jasper-report 中为 Date/Time 对象使用 pattern 属性,您需要 java.util.Date class 或以下之一低于classes.

解决方法是将java.time.LocalDatejava.time.LocalDateTime

转换

正在转换为 java.util.Date

from java.time.LocalDate

<textField pattern="EE. dd.MM.yyyy">
    <reportElement...>
    </reportElement>
    <textFieldExpression><![CDATA[java.util.Date.from($F{theLocalDate}.atStartOfDay(java.time.ZoneId.systemDefault()).toInstant())]]></textFieldExpression>
</textField>

from java.time.LocalDateTime

<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

来自 java.time.LocalDate

<textField pattern="EE. dd.MM.yyyy">
    <reportElement...>
    </reportElement>
    <textFieldExpression><![CDATA[java.sql.Timestamp.valueOf($F{theLocalDate}.atStartOfDay())]]></textFieldExpression>
</textField>

来自 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)

由于 java.time 模块有点复杂和冗长,我通常会创建一些变量来保存已编译的 DateTimeFormatter 以供进一步使用。

我希望我的报告适应任何语言环境,所以我不使用字符串文字进行格式化。

我正在使用报告区域设置,但您可以使用 java.util.Locale.forLanguageTag("en-US") 选择您的区域设置。

如果需要,您也可以更改 java.time.format.FormatStyle

LocalDate 格式化程序:

    <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 格式化程序:

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

现在我可以这样格式化 LocalDate 字段:

$F{localDateField}.format($V{dateFormatter})

还有这样一个 LocalDateTime 字段:

$F{localDateTimeField}.format($V{dateTimeFormatter})

我遇到了同样的问题,我通过向 JasperReports 引入自定义函数解决了这个问题。所以最后它可以在 LocalDate、LocalTime、LocalDateTime 上用作以下任何实现 TemporalAccessor 的东西:

FORMAT_DATETIME($F{someLocalDate}, "dd.MM.yyyy")
FORMAT_DATETIME($F{someLocalDateTime}, "dd.MM.yyyy HH:mm")
FORMAT_DATETIME($F{someLocalTime}, "HH:mm")

为此创建以下文件:

函数类别。这是必需的,以便 jasper 报告设计器的表达式编辑器在设置类别下显示该功能

package org.example.jrfunctions;

import net.sf.jasperreports.functions.annotations.FunctionCategory;

@FunctionCategory()
public class LocalDateTime {
}

Class 具有功能(可以添加更多功能)

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

}

下面的文件需要和上面两个在同一个目录下,并且需要设置每个参数的所有属性。否则 jasper 报表设计器将不会在表达式编辑器中显示自定义函数:

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=

以下文件需要在类路径中。我把它放到 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

现在自定义函数应该显示在表达式编辑器中,编译没有任何问题。

更多信息: