0

I get this field from kafka that use avro schema:

long dateTime = 1499070300000L;  //value is just for example, but have to be micros 

It has logicalType: "logical-timestamp-micros"

And I have this kind of Dto:

@JsonFormat(pattern = "dd.MM.yy HH:mm:ss")
  private LocalDateTime time;

And I am trying to convert field dateTime to be currentDateTime field format:

long dateTime = 1499070300000L;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yy HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.parse(Instant.ofEpochMilli(dateTime)
                .atZone(ZoneId.systemDefault())
                .format(dateTimeFormatter));

But I am getting this error:

Exception in thread "main" java.time.format.DateTimeParseException: Text '03.07.17 11:25:00' could not be parsed at index 0

Where am I doing wrong?

Alex
  • 21
  • 5
  • Do not use `LocalDateTime` for a point in time. It does not work. Stick to the `ZonedDateTime` you get from `atZone()`. You can use it for everyting that you can use a `LocalDateTime` for and more. If you need to call an API that requires a `LocalDateTime`, then pass `yourZonedDateTime.toLocalDateTime()` to it. – Ole V.V. Oct 23 '22 at 08:38

1 Answers1

2

Don't convert your ZonedDateTime to a String and back to a LocalDateTime.

Instead, use what the API provides. In your case, LocalDateTime.ofInstant seems to be just what you need:

LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTime), ZoneId.systemDefault());

Aside from that, you meantioned that the timestamp has the type logical-timestamp-micros. Instant.ofEpochMilli requires milliseconds. If your long is actually the time in microseconds, you might want to divide it by 1000 before using it in Instant.ofEpochMilli. Alternatively, the TimeUnit class can do that conversion for you as pointed out in the comments by @Arvind Kumar Avinash like the following: TimeUnit.MILLISECONDS.convert(milliTime, TimeUnit.MICROSECONDS)

If you care about preserving microseconds, you can use Instant.EPOCH.plus(timeMicros, ChronoUnit.MICROS) for obtaining the Instant instead of using Instant.ofEpochMilli as suggested in the comments by Ole V. V. (the comment has been deleted). See this answer for details on that.

Both methods assume the timestamp being in microseconds since January 1st, 1970 (the UNIX-Epoch).

dan1st
  • 12,568
  • 8
  • 34
  • 67
  • Yes, right you are. Its just for example. In fact its gonna be real micros. – Alex Oct 23 '22 at 09:41
  • @dan1st But how about formatting it? When I write like this: LocalDateTime localDateTime = LocalDateTime.parse(LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTime), ZoneId.systemDefault()).format(dateTimeFormatter)); It still returning parse exception. – Alex Oct 24 '22 at 07:13
  • 1
    Don't use `LocalDateTime.parse` here. If you want to print it, you can use `.format`. – dan1st Oct 24 '22 at 09:26
  • @ArvindKumarAvinash I was talking about converting microseconds to milliseconds, not the other way. – dan1st Nov 27 '22 at 19:38
  • If one has 5 seconds in microseconds, they'd have `5_000_000` microseconds. In order to convert that to milliseconds, one needs to divide it by 1000 so they get `5_000` milliseconds that can be used in `Instant.ofEpochMilli`. I was talking about converting milliseconds to an `Instant`. What should be wrong about that (apart from my typo)? – dan1st Nov 27 '22 at 19:49
  • 1
    As I had said in my previous comment (which I deleted later because I had mentioned the wrong calculation in hurry), it's a great answer. There is no problem with division but I strongly recommend using `TimeUnit.MILLISECONDS.convert(timestamp-in-mircoseconds, TimeUnit.MICROSECONDS)`. – Arvind Kumar Avinash Nov 28 '22 at 08:33