【问题标题】:DynamicReports doesn't apply pattern to format ZonedDateTimeDynamicReports 不应用模式来格式化 ZonedDateTime
【发布时间】:2018-01-29 13:00:11
【问题描述】:

我有一个模型类,其中包含ZonedDateTime 类型的字段。生成报表数据时显示为:

2017-08-17T16:09:03+03:00[欧洲/基希讷乌]

要格式化该日期,我使用方法setPattern("dd.MM.yyyy"),但没有任何变化。

所有东西都是通过反射生成的,检查来源:

for (Field field : entityClass.getDeclaredFields()) {
    String fieldName = field.getName();
    if (usedFields.contains(fieldName)) {
        field.setAccessible(true);
        if(field.getType().isAssignableFrom(Date.class) || field.getType().isAssignableFrom(ZonedDateTime.class)){
            report.addColumn(Columns.column(fieldName, fieldName, field.getType()).setPattern("dd.MM.yyyy"));
        }else {
            report.addColumn(Columns.column(fieldName, fieldName, field.getType()));
        }
    }
}

生成报告,其中 list 是元素的通用列表。

report
.title(
        Components.text("Documents Report")
        .setStyle(getHeaderCenteredBoldStyle())
        .setHorizontalTextAlignment(HorizontalTextAlignment.CENTER))
        .pageFooter(Components.pageXofY())
.setColumnTitleStyle(getColumnTitleStyle())
.highlightDetailEvenRows()
.setDataSource(list);

生成的 PDF

有任何想法吗?

【问题讨论】:

  • 实际渲染的作用是什么?仅仅调用 toString() 是不够的,您必须格式化您的 dateTimes,并且您的输出看起来与 toString() 结果完全相同。
  • @M.Prokhorov 检查更新,我该如何格式化。日期。我在 exaples 中找到的只是 setPattern() 方法。检查答案中的更新
  • 在我看来,您的DynamicReports 版本不支持java.time 库。既然您似乎是通过反射构建它,请尝试使用 setPatternExpression 方法,在该方法中您将使用正确的格式化程序表达式代码。

标签: java date datetime-format dynamic-reports zoneddatetime


【解决方案1】:

setPattern 似乎适用于 java.util.Date,但不适用于 java.time.ZonedDateTime。我创建了一个简单的实体:

public class Entity {

    private ZonedDateTime zonedDateTime = ZonedDateTime.parse("2017-08-17T16:09:03+03:00[Europe/Chisinau]");

    private Date date = new Date();

    // getters and setters
}

然后我使用您的代码 (for (Field field : entityClass.getDeclaredFields()) etc) 添加列。对于数据源list,我是手动创建的,只是为了测试:

DRDataSource ds = new DRDataSource("zonedDateTime", "date");
ds.add(entity.getZonedDateTime(), entity.getDate());

在生成的报告中,ZonedDateTime 未格式化(显示为2017-08-17T16:09:03+03:00[Europe/Chisinau]),但Date 正确显示为21.08.2017

解决此问题的一种方法是设置值格式化程序并使用java.time.format.DateTimeFormatterZonedDateTime 转换为String

if (field.getType().isAssignableFrom(ZonedDateTime.class)) {
    // ZonedDateTime, use a value formatter
    report.addColumn(Columns.column(fieldName, fieldName, ZonedDateTime.class)
        // set a custom value formatter
        .setValueFormatter(new AbstractValueFormatter<String, ZonedDateTime>() {
            @Override
            public String format(ZonedDateTime value, ReportParameters reportParameters) {
                // convert ZonedDateTime to dd.MM.yyyy format
                DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd.MM.yyyy");
                return value.format(fmt);
            }
        }));
} else if (field.getType().isAssignableFrom(Date.class)) {
    // java.util.Date: setPattern works
    report.addColumn(Columns.column(fieldName, fieldName, field.getType()).setPattern("dd.MM.yyyy"));
...

这样,ZonedDateTime 就会以DateTimeFormatter 中定义的格式显示:

17.08.2017

在此示例中,我在内部类中创建 DateTimeFormatter,但最好在 if 之外仅创建一个格式化程序(它可以在 static final 字段中,因为它是不可变的和线程 -安全)并在您的应用程序中重复使用它。


另一种选择是将ZonedDateTime 手动格式化为String,使用相同的java.time.format.DateTimeFormatter,但在数据源列表中。我还必须将列的类型更改为String(在for 内):

if (field.getType().isAssignableFrom(ZonedDateTime.class)) {
    // ZonedDateTime, manually convert to String
    report.addColumn(Columns.column(fieldName, fieldName, String.class));
} else if (field.getType().isAssignableFrom(Date.class)) {
    // java.util.Date: setPattern works
    report.addColumn(Columns.column(fieldName, fieldName, field.getType()).setPattern("dd.MM.yyyy"));
} else {
    report.addColumn(Columns.column(fieldName, fieldName, field.getType()));
}

然后,在数据源list 中,我不得不使用DateTimeFormatterZonedDateTime 格式化为String

// create formatter
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd.MM.yyyy");

// format the ZonedDateTime
ds.add(entity.getZonedDateTime().format(fmt), entity.getDate());

这样,ZonedDateTime 现在显示为17.08.2017

我不确定您是如何创建 list 值的,但您必须将其更改为以上述方式格式化 ZonedDateTime(或在实体内部进行)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 2017-05-31
    • 2019-05-07
    • 2020-11-27
    • 2021-09-04
    • 2017-07-14
    相关资源
    最近更新 更多