-6

I have the following code that I want to migrate to Java 17:

Gradle dependency:

implementation 'org.jadira.usertype:usertype.core:7.0.0.CR1'

Entity:

    import org.joda.time.DateTime;

    @Entity
    @Table(name = "logs")
    public class Log {
    
      @Column(name = "inserted_date")
      @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
      private DateTime insertedDate;
    }


.....

DateTimeFormatter dateFormatter = DateTimeFormat.forPattern("yy-mm-dd'T'HH:mm:ss'Z'");

log.setInsertedDate(DateTime.now());
dateFormatter.print(log.getInsertedDate().withZone(DateTimeZone.UTC)));

I updated the code to this:

Entity:

    import java.time.OffsetDateTime;

    @Entity
    @Table(name = "logs")
    public class Log {
    
      @Column(name = "inserted_date")
      private OffsetDateTime insertedDate;
    }


.....

DateTimeFormatter dateFormatter = DateTimeFormat.forPattern("yy-mm-dd'T'HH:mm:ss'Z'");

log.setInsertedDate(OffsetDateTime.now());
dateFormatter.print(log.getInsertedDate().withZone(DateTimeZone.UTC)));

But I get error Cannot resolve method 'withZone' in 'OffsetDateTime'. Do you know what is the proper way to update method withZone?

edit: I tried this

from: log.setTimestamp(dateFormatter.print(auditLog.getInsertedDate().withZone(DateTimeZone.UTC)));

to: log.setTimestamp(dateFormatter.print(auditLog.getInsertedDate().atZoneSameInstant(ZoneOffset.UTC)));

I get for this line: auditLog.getInsertedDate().atZoneSameInstant(ZoneOffset.UTC) error:

Cannot resolve method 'print(ZonedDateTime)'

Can you advice how to solve this?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Peter Penzov
  • 1,126
  • 134
  • 430
  • 808
  • Do you mean `atZoneSameInstant(ZoneId)` – Mark Rotteveel Feb 12 '23 at 17:23
  • sorry can you clarify more? – Peter Penzov Feb 12 '23 at 17:25
  • The method `atZoneSameInstant(ZoneId)` seems to be the closest equivalent of `org.joda.time.DateTime.withZone(..)` for `java.time.OffsetDateTime`. Or maybe you intended to use `java.time.Instant`, and then you'd need to use the method `atZone(ZoneId)`. – Mark Rotteveel Feb 12 '23 at 17:26
  • ok but for `atZoneSameInstant(.....)` what argument I need to pass which will be same as `DateTimeZone.UTC`? – Peter Penzov Feb 12 '23 at 17:28
  • Do you mean to migrate from the *Joda-Time* library to the *java.time* classes built into Java 8+? If so, say so. Edit the body of your Question. – Basil Bourque Feb 12 '23 at 17:47
  • I want to migrate the code to java 17 but keeping the same functionality as much as I can. Can you guide me how to do it properly, please? – Peter Penzov Feb 12 '23 at 18:18
  • You can use `ZoneOffset.UTC`, or `ZoneId.of("UTC")` – Mark Rotteveel Feb 13 '23 at 09:01
  • 1
    That said, migrating to Java 17 has nothing to do with switching to Jodatime. The `java.time` classes have been there since Java 8, and as far as I'm aware, Jodatime works fine on Java 17. – Mark Rotteveel Feb 13 '23 at 09:02
  • I updated the post with your proposal but I get now error: `Cannot resolve method 'print(ZonedDateTime)'` – Peter Penzov Feb 13 '23 at 16:01
  • @PeterPenzov Just trying to migrate by trying to replace types and ask a question or comment for each compilation error you get is not a fruitful exercise. Study the actual API and you'll see that the [`java.time.format.DateTimeFormatter`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/format/DateTimeFormatter.html) doesn't have a `print` method (you probably want `format`). – Mark Rotteveel Feb 13 '23 at 16:04
  • Sorry but the code is very critical and I don't have much of experience with DateTime. I get `Cannot resolve method 'format' in 'DateTimeFormatter'` There is no method format. – Peter Penzov Feb 13 '23 at 16:08
  • 1
    Then you're probably still using the `DateTimeFormatter` of Joda-Time, not of Java. And if the code is so critical, then either don't migrate away from Joda-Time, or it should be done by someone with more experience in Joda-Time and the java.time API. As far as I'm aware, it works fine on Java 17, so that cannot be the reason why you're migrating away from it. – Mark Rotteveel Feb 13 '23 at 16:10
  • yes, you're right. Last question which formatter I need to use for Java time? – Peter Penzov Feb 13 '23 at 16:32
  • `.withOffsetSameInstant(ZoneOffset.UTC)`? – Ole V.V. Feb 19 '23 at 20:56
  • 1
    `log` is the entity (public class Log {...}) – Peter Penzov Feb 19 '23 at 21:30
  • I got confused because you are trying to call `log.setTimestamp()` but in your `Log` entity I don’t see any `setTimestamp` method? Which type has its parameter got? – Ole V.V. Feb 20 '23 at 04:19
  • You format string `yy-mm-dd'T'HH:mm:ss'Z'` is weird and wrong (both in the old and the new code). It is trying to be [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601), but in ISO 8601 two digit year is not allowed. The first lower case `mm` is wrong as explained in the answer. Putting `Z` in quotes is wrong too. It’s the offset, so format the offset from the datetime. To produce proper ISO 8601 you don’t need a format pattern string since both Joda-Time and java.time produce ISO 8601 natively. – Ole V.V. Feb 20 '23 at 04:23
  • So to produce a string, assuming `auditLog` is a `Log`: `auditLog .getInsertedDate() .withOffsetSameInstant(ZoneOffset.UTC) .toString()`. Or if you don’t want the fraction of second: `... .withOffsetSameInstant(ZoneOffset.UTC) .truncatedTo(ChronoUnit.SECONDS) .toString()`. – Ole V.V. Feb 20 '23 at 04:29
  • 1
    (You may know this already), for better response to your question (1) provide full reproducible code ([mre]) (2) add all the right tags. – Ole V.V. Feb 20 '23 at 04:34

1 Answers1

3

First of all, it looks like your time format isn't what you intended it to be.

"yy-mm-dd'T'HH:mm:ss'Z'" would mean a format that prints:
year-minutes-days'T'Hours(24 hour format):minutes:secondsZ
example: 23-48-19T14:48:17Z

I'm assuming you want to follow years with month of the year and so the format should be:
"yy-MM-dd'T'HH:mm:ss'Z'"
example: 23-02-19T14:48:17Z

To know more about constructing patterns for formatting please refer the section "Patterns for Formatting and Parsing" in the java time api docs



Now, coming to your question,
You seem to be mixing the joda time library with java date time api. Written purely with the java date time api, your code should look something like:

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;


DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yy-MM-dd'T'HH:mm:ss'Z'");
log.setInsertedDate(OffsetDateTime.now());
log.setTimestamp(dateFormatter.format(auditLog.getInsertedDate().atZoneSameInstant(ZoneId.of("UTC"))));

PS: I know that working with date time objects can be frustrating and confusing in Java especially because there used to be more than one way to do it. I would recommend reading the java date time api tutorials to get a better understanding and to always use it (when writing in java 8+) to avoid confusion.

Neil Menezes
  • 255
  • 1
  • 6
  • Thank you for your answer. One follow-up question which is not clear to me. Should I use `joda time library` or `java date time api` from Java 17? – Peter Penzov Feb 19 '23 at 18:28
  • 2
    [The Joda-time homepage](https://www.joda.org/joda-time/) answera that part clearly: *Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to `java.time` (JSR-310).* – Ole V.V. Feb 19 '23 at 21:02