2

I'm using LocalDateTime to represent time. In the debugging mode, I noticed that the time format is not in ISO 8601, which makes me hard to send directly to other apis.

Request class:

public class AgreementRequest {
    @NonNull
    private String name;
    @NonNull
    private String description;
    @JsonProperty("start_date")
    @DateTimeFormat(iso = DATE_TIME)
    @NonNull
    private String startDate;
}

Initialization:

request = AgreementRequest.builder()
                .name("Premium subscription")
                .description("Montly subscription")
                .startDate(LocalDateTime.now().plusDays(1).toString()).build();

enter image description here

The LocalDateTime.toString is not either in ISO 8601, the letter z in ISO8601 is gone.

I have objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); disabled, is this the problem?

Cosaic
  • 497
  • 2
  • 9
  • 15
  • *"The LocalDateTime.toString is not either in ISO 8601, the letter z in ISO8601 is gone."* Yes, it is. ISO-8601 doesn't require a timezone on strings; the string shown is a perfectly valid ISO-8601 datetime string. If there is no timezone, ISO-8601 assumes "local time." Given that the class is `LocalDateTime`, that representation makes sense. – T.J. Crowder Sep 04 '18 at 15:12
  • 1
    The "local" part indicates the LocalDateTime is for a date/time without a timezone. – Peter Lawrey Sep 04 '18 at 15:15
  • Should I use `Instant` instead of `LocalDateTime`? If so, what should I change in my PostgreSQL DB? – Cosaic Sep 04 '18 at 15:16
  • @Cosaic See the [documentation](https://jdbc.postgresql.org/documentation/head/8-date-time.html). – cassiomolin Sep 04 '18 at 15:19
  • 1
    @Cosaic Use `Instant` for an actual moment, a point on the timeline, in UTC. Use `LocalDateTime` when you mean all time zones or any time zone. These are completely different animals, not at all interchangeable, because **`LocalDateTime` cannot represent a moment**. See: [*What’s the difference between `Instant` and `LocalDateTime`?*](https://stackoverflow.com/q/32437550/642706). – Basil Bourque Sep 04 '18 at 16:14
  • @BasilBourque Your answer is golden. I wish I could upvote it again. – cassiomolin Sep 04 '18 at 16:28

1 Answers1

6

The LocalDateTime.toString is not either in ISO 8601, the letter Z in ISO8601 is gone.

LocalDateTime a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

Z is the zone designator for the zero UTC offset and that's why you won't see it when invoking toString() from a LocalDateTime instance. Use ZonedDateTime or OffsetDateTime if you need a time-zone or an offset.

To (de)serialize JSR-310 types with Jackson, consider the JavaTimeModule. See the documentation for details.


Should I use Instant instead of LocalDateTime? If so, what should I change in my PostgreSQL DB?

Check what the PostgreSQL JDBC driver documentation says about it:

The PostgreSQL™ JDBC driver implements native support for the Java 8 Date and Time API (JSR-310) using JDBC 4.2.

+--------------------------------+----------------+
| PostgreSQL™                    | Java SE 8      |
+--------------------------------+----------------+
| DATE                           | LocalDate      |
| TIME [ WITHOUT TIMEZONE ]      | LocalTime      |
| TIMESTAMP [ WITHOUT TIMEZONE ] | LocalDateTime  |
| TIMESTAMP WITH TIMEZONE        | OffsetDateTime |
+--------------------------------+----------------+

This is closely aligned with tables B-4 and B-5 of the JDBC 4.2 specification.

Note
ZonedDateTime, Instant and OffsetTime / TIME [ WITHOUT TIMEZONE ] are not supported. Also note that all OffsetDateTime will instances will have be in UTC (have offset 0). This is because the backend stores them as UTC.

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • 3
    Or use `Instant` if you always want to use the UTC timezone. `ZonedDateTime`/`OffsetDateTime`s are only useful if you want to use variable timezones. Please note that the actual timezone might be lost if saved to a database such as postgres (only the timestamp in utc is saved). They are supported by (some) JPA implementations. – ST-DDT Sep 04 '18 at 16:02
  • If I have an `Instant` in UTC, I then convert it to `LocalDateTime` and store it in DB. Is this a valid process? – Cosaic Sep 04 '18 at 16:25
  • @Cosaic It depends. `Instant` and `LocalDateTime` are different things. Have a look at this [answer](https://stackoverflow.com/a/32443004/1426227) from Basil Bourque. – cassiomolin Sep 04 '18 at 17:41