Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am trying to parse Instant from a CSV using OpenCsv this way:

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

An Instant is a point in time independent of time zone and therefore neither defines year, month, day-of-month. hour, minute nor second. So trying to parse it using a format holding those elements does not make sense, at least not if you don’t specify the time zone or offset from UTC. – Ole V.V. Apr 6, 2022 at 18:49 That is a good point, but as I was saying in the question I understand that the issue here is the lack of a time zone. So, you can say that my question is more about - is it possible to specify the time zone in OpenCsv + @CsvDate. Also, I'd assume that it would get a default UTC time zone if not supplied (though it seems like it isn't). – Tom Carmi Apr 7, 2022 at 11:26

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.

Extended the answer. Already thought that Instant is a too amorph class. The same as adding time HH:mm for a LocalDate (no time). – Joop Eggen Apr 6, 2022 at 19:41

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.