@CsvDate("yyyy-MM-dd hh:mm:ss")
@CsvBindByName(column = "date")
private Instant date;
I know that OpenCsv is supposed to support java.time
.
But when trying to use it I am getting the following exception:
Error parsing CSV line: 8.
Caused by: java.time.format.DateTimeParseException: Text '2022-04-21 00:00:00' could not be parsed: Unable to obtain Instant from TemporalAccessor: {HourOfAmPm=0, MicroOfSecond=0, NanoOfSecond=0, MilliOfSecond=0, MinuteOfHour=0, SecondOfMinute=0},ISO resolved to 2022-04-21 of type java.time.format.Parsed
Caused by: java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: {HourOfAmPm=0, MicroOfSecond=0, NanoOfSecond=0, MilliOfSecond=0, MinuteOfHour=0, SecondOfMinute=0},ISO resolved to 2022-04-21 of type java.time.format.Parsed
Caused by: java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: InstantSeconds
What comes from my investigation, is that the root cause is the lack of a time zone, but my question is how do I specify the time zone using the annotation only?
–
–
See DateTimeFormatter. It should be HH
for 24 hours time (0-23) i.o. hh
for 12 hours time (1-12). The error is caused by hour "00". Fortunately, otherwise you would have only the first half of the day.
See h, k, H and K.
The class Instant
does not use units like seconds, is more a long internally. Use LocalDateTime
for your format.
–
What comes from my investigation, is that the root cause is the lack of a time zone, but my question is how do I specify the time zone using the annotation only?
I haven't find a way to change the timezone of the DateTimeFormatter
used by OpenCSV. You could, in theory, use @CsvCustomBindByName
and provide a custom converter in which you can use your own DateTimeFormatter
with the timezone you want.
However, if you also control how your CSV is generated, you can simply use the following datetime patterns to make it work with Instant
:
@CsvBindByName(column = "date")
@CsvDate(
value = "yyyy-MM-dd'T'HH:mm:ssX",
writeFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'",
writeFormatEqualsReadFormat = false)
private Instant date;
value
is the pattern used when reading a bean from a CSV file. X
is a pattern letter which will corresponds to the zone offset, i.e. when reading the 'Z' character, it will assume the time to be in UTC+00:00. See doc.
When writing a bean to a CSV file, the writeFormat
pattern will be used and needs to be different, you need to print the 'Z' char manually at the end, hence the escaped 'Z'
. The reason is that internally OpenCSV does the following when writing an Instant
:
LocalDateTime ldt = LocalDateTime.ofInstant((Instant) value, ZoneId.of("UTC"));
return writeDtf.format(ldt);
LocalDateTime
does not have a timezone, so the X
cannot be used. Arguably, they could instead do the following:
return writeDtf.withZone(ZoneOffset.UTC).format(value);
Which would then allow us to use the X
. They could also do the same when parsing a date to an Instant
, in order to be consistent.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.