-1

I receive this error when trying to get response from Api Call:

I receive this field like this from the object:

"createdAt":1620133356550

My Dto has this field, so i can get the value with object mapper:

@JsonSerialize(using = LocalDateTimeSerializer.class)
  private LocalDateTime createdAt;

And i receive this error:

com.fasterxml.jackson.databind.exc.MismatchedInputException: raw timestamp (1620133356550) not allowed for `java.time.LocalDateTime`: need additional information such as an offset or time-zone (see class Javadocs)

Possible setter of the object:

 public void setCreatedAt(long createdAt) {
        Instant instant = Instant.ofEpochMilli(createdAt);
LocalDateTime localMark =
  instant.atZone(ZoneId.of("Europe/Amsterdam"))
  .toLocalDateTime();
    this.createdAt = localMark;
  }
Liverpool
  • 265
  • 7
  • 21
  • 4
    What's your question here? The error explains everything pretty well. A `LocalDateTime` comprises of more than just a point in time and needs *"additional information such as an offset or time-zone"*. – Henry Twist May 04 '21 at 13:12
  • 4
    You don't want LocalDateTime because you don't care about *where* (what country) this thing was created. You just care about *when*. You want Instant, which has [`ofEpochMilli`](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#ofEpochMilli-long-) – Michael May 04 '21 at 13:16

1 Answers1

6

That's because you're asking jackson to silently convert an apple into a pear and it won't do that. There is no way to do this without additional information.

This: 1620133356550 looks like a milliseconds-since-epoch value.

This represents an instant in time. Instants in time and LocalDateTime are a real guns and grandmas situation: They are almost entirely unrelated, and one cannot be transformed into the other; at least, not without parameters that are simply not present here.

First you need to 'localize' the timestamp: That's milliseconds since some instant in time. Which instant in time? A common format is 'milliseconds since midnight, new years, 1970, in the UTC timezone'. If that's indeed what it is, all you need to do is to say Instant.ofEpochMilli(1620133356550L), and you now have that properly represented (namely, as an Instant).

This still isn't a LocalDateTime though. The problem is: Local to whom?

UTC isn't actually used by anybody except space flight, aviation in general, and computers talking to each other. Unless you're writing software specifically intended to run on the Dragon space capsule and nowhere else, by definition then this isn't yet ready to be put in terms of local date and time.

First you need to transform your instant to a locale. THEN you can have a LocalDateTime.

For example, if you want to know: Okay, so if I walk around Amsterdam at the exact instant as represented by this java.time.Instant I made, and I ask somebody the date and time, what would they say? Then you do:

Instant instant = Instant.ofEpochMilli(1620133356550L);
LocalDateTime localMark =
  instant.atZone(ZoneId.of("Europe/Amsterdam"))
  .toLocalDateTime();

In case this is some bizarro format where a LocalDateTime is serialized by way of: Take the local date time, turn that into an instant by assuming you're asking the current date and time at that exact instant by asking someone zipping about the international space station, and then turn that into epochmillis and put that on the wire, okay, then, write that. Use ZoneOffset.UTC instead of ZoneId.of("Europe/Amsterdam") in the above code.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • So i need to do this in the setter of the object? i will put and update in the question so you can see it – Liverpool May 04 '21 at 13:24
  • @Liverpool No, Jackson won't use your setter. It has no way to know, other than by inferring it from the name of the method, that it even *is* a setter. It might be called `setFoo` and not actually set anything. Jackson sets fields using reflection. If you want custom serialization, you need to replace this `@JsonSerialize(using = LocalDateTimeSerializer.class)` with `MyCustomSerializer.class`, where that custom class implements the required interface – Michael May 04 '21 at 13:27
  • Do you have some exmaple for custom converter – Liverpool May 04 '21 at 13:39