I have a model class that contains field of type ZonedDateTime. When generate report data is shown as:
2017-08-17T16:09:03+03:00[Europe/Chisinau]
To format that date I use method setPattern("dd.MM.yyyy")
but nothing changes.
All stuff is generated via reflection, check source:
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()));
}
}
}
Generate report where list is a generic list of elements.
report
.title(
Components.text("Documents Report")
.setStyle(getHeaderCenteredBoldStyle())
.setHorizontalTextAlignment(HorizontalTextAlignment.CENTER))
.pageFooter(Components.pageXofY())
.setColumnTitleStyle(getColumnTitleStyle())
.highlightDetailEvenRows()
.setDataSource(list);
Generated PDF
It seems that setPattern
works fine for java.util.Date
, but not for java.time.ZonedDateTime
. I've created a simple entity:
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
}
Then I've used your code (for (Field field : entityClass.getDeclaredFields()) etc
) to add the columns. For the data source list
, I've created it manually, just to test:
DRDataSource ds = new DRDataSource("zonedDateTime", "date");
ds.add(entity.getZonedDateTime(), entity.getDate());
In the resulting report, the ZonedDateTime
wasn't formatted (it's shown as 2017-08-17T16:09:03+03:00[Europe/Chisinau]
), but the Date
was correctly displayed as 21.08.2017
.
One way to fix this is to set a value formatter and use a java.time.format.DateTimeFormatter
to convert the ZonedDateTime
to a 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"));
...
With this, the ZonedDateTime
is displayed with the format defined in the DateTimeFormatter
:
17.08.2017
In this example I'm creating the DateTimeFormatter
inside the inner class, but it's better to create just one formatter outside of the if
(it can be in a static final
field, as it's immutable and thread-safe) and reuse it accross your application.
Another alternative is to manually format the ZonedDateTime
to a String
, using the same java.time.format.DateTimeFormatter
, but in the data source list. I also had to change the type of the column to String
(inside the 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()));
}
Then, in the data source list
, I had to use the DateTimeFormatter
to format the ZonedDateTime
to a String
:
// create formatter
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd.MM.yyyy");
// format the ZonedDateTime
ds.add(entity.getZonedDateTime().format(fmt), entity.getDate());
With this, the ZonedDateTime
is now shown as 17.08.2017
.
I'm not sure how you're creating the list
of values, but you'll have to change it to format the ZonedDateTime
in the way described above (or do it internally in the entity).