123

Edit: Well, apparently it was too opinion based, so let me try to reword it more precisely -

Are there any clear caveats or drawbacks of using LocalDate, LocalTime etc. in a Java code that does not need any backwards compatibility, and if so - what are they?

I'm looking for things like "Current EE libraries X and Y don't work correctly with LocalDate" or "This very useful pattern is broken with LocalTime" et cetera.


(here is the original question for reference)

With Java 8, a new time API is introduced, namely the java.time.LocalDate etc., but java.util.Date is not marked as deprecated.

I am writing a new project, which does not need to be backwards compatible. Should I only use LocalDate, LocalDateTime etc.? Are there any drawbacks to using this new API as opposed to the good old java.util.Date?

In particular - I am going to be working mainly with JDBC. From what I have seen JDBC handles java.util.Date well. Is it as well suited for LocalDate?

Searching yielded lots of sites telling how to convert from one format to the other, but no definitive answer as to should new code use the old API.

Thanks.

Itai
  • 6,641
  • 6
  • 27
  • 51
  • 18
    `good old java.util.Date` - it is old, but not good. new code should use new API. – Iłya Bursov Feb 25 '15 at 21:38
  • 8
    There's a reason an entirely new date API was created. If you have a greenfield project, go with the Java 8 introduced API. – Jeroen Vannevel Feb 25 '15 at 21:38
  • 1
    Please, use the new API. :-P – Paul Vargas Feb 25 '15 at 21:41
  • 1
    Thank you. Is there any particular reason why java.util.Date isn't marked as @Deprecated in newer version of Java if it is to be replaced by java.time classes? – Itai Feb 25 '15 at 21:41
  • 5
    Java is leery of using the @Deprecated annotation for things that are bad but not going to be deleted. – Louis Wasserman Feb 25 '15 at 21:44
  • 6
    Oracle's own documentation gives three main reasons to deprecate an API: ["It is insecure, buggy, or highly inefficient; It is going away in a future release; It encourages bad coding practices."](http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/deprecation/deprecation.html) Whether these apply to java.util.Date may be a matter of opinion. – MarsAtomic Feb 25 '15 at 21:48
  • 1
    Ask yourself this question, does the new api provide you any functionality you need? I'm not sure if JDBC has been updated to handle the new api and still relies on java.sql.Date. The conversion from Date to LocalDateTime os not a difficult one either, so you may still need to provide some bridging anyway...this is what you need to weigh up, is it worth the time and effort to convert from Date to LocalDateTime if all you're going to do is, for example, format the value for output? If you're doing date calculations, then yes, without a doubt, go for the new API – MadProgrammer Feb 25 '15 at 22:02
  • Ok, so apparently MySQL connector J doesn't support Java 8 (go figure!), so it is impossible to use LocalDate / LocalTime etc. with MySQL. As my project uses MySQL - it seems I will stick with bad old Date. – Itai Mar 03 '15 at 00:40
  • No drawbacks on using java.time API since it is supported by MySQL JDBC driver now..? – Wuaner Sep 11 '18 at 08:04
  • 1
    In a nutshell: [Sun Microsystems](https://en.wikipedia.org/wiki/Sun_Microsystems), [Oracle](https://en.wikipedia.org/wiki/Oracle_Corporation), and the [JCP](https://en.wikipedia.org/wiki/Java_Community_Process) community [all gave up](https://jcp.org/en/jsr/results?id=5639) on the terrible legacy date-time classes with the adoption of [JSR 310](https://jcp.org/en/jsr/detail?id=310). And so should you. Now years later, many libraries have been updated to support *java.time* classes. If some library lacks support, file a bug report. – Basil Bourque Jun 10 '19 at 22:50

3 Answers3

83

Despite the name, java.util.Date can be used to store both date and time (it stores UTC milliseconds offset since epoch)

I would definitely use the new API because of greater features:

  • Easier format/parsing. The API has its own format/parse methods
  • The API includes addition/subtraction operation (minusMinutes, plusDays, etc)

None of above are available on java.util.Date

Old Date can also be converted into LocalDateTime like this:

    Date oldDate = ...
    LocalDateTime newDateTime = 
      LocalDateTime.from(Instant.ofEpochMilli(oldDate.getTime()));
kohane15
  • 809
  • 12
  • 16
gerrytan
  • 40,313
  • 9
  • 84
  • 99
  • 3
    So in your oponion it's time to discard old Date at all? – Sheldon Wei Mar 01 '18 at 05:53
  • 1
    @ShedomWei It all depends on your project requirements. OP decided to stick with old Date because "apparently MySQL connector J doesn't support Java 8" (Itai Mar 3 '15 at 0:40). – Stephan May 31 '18 at 16:54
47

I’m adding to the correct Answer by Ole V.V.

JDBC 4.2

In particular - I am going to be working mainly with JDBC.

JDBC 4.2 added support for exchanging java.time objects with the database. See the PreparedStatement::setObject and ResultSet::getObject methods.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( z ) ;
myPreparedStatement.setObject( … , today ) ;

Retrieval.

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

For reasons that escape me, the JDBC spec does not require support for the two most commonly used classes: Instant and ZonedDateTime. Your database and JDBC driver may or may not add support for these.

If not, you can easily convert. Start with OffsetDateTime, with support required in JDBC.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

To see this moment through the wall-clock time used by people of a particular region (a time zone), apply a ZoneId to get a ZonedDateTime object.

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant() ;

To adjust into UTC, extract an Instant. An Instant is always in UTC, by definition.

Instant instant = odt.toInstant() ;

You can convert the other way, to write to a database.

myPreparedStatement.setObject( … , zdt.toOffsetDateTime() ;  // Converting from `ZonedDateTime` to `OffsetDateTime`. Same moment, same point on the timeline, different wall-clock time.

…and:

myPreparedStatement.setObject( … , instant.atOffset( ZoneOffset.UTC ) ) ;  // Converting from `Instant` to `OffsetDateTime`. Same moment, same point on the timeline, and even the same offset. `OffsetDateTime` is a more flexible class with abilities such as (a) applying various offsets and (b) flexible formatting when generating text, while `Instant` is meant to be a more basic building-block class. 

Notice the naming convention used in java.time: at, from, to, with, and so on.

Table of date-time types in Java (both modern and legacy) and in standard SQL.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    ThreeTenBackport is a good library but now for Android **(2021 and after that)** using Java 8+ API desugaring support is suggested by [official documents](https://developer.android.com/studio/write/java8-support#library-desugaring) and JakeWharton(ThreeTen's author). – YaMiN Dec 14 '21 at 13:03
6

Java 8 and later: no worries

No, there is no reason why you shouldn’t want to use java.time, the modern Java date and time API if you’re on Java 8 or later (where it’s built in).

The only thing one may briefly consider, is the one you have already excluded.

I am writing a new project, which does not need to be backwards compatible.

And even for backward compatibility you can safely use java.time since conversion methods are built into the old classes from Java 8.

Java 6 and 7: weigh

If you’re on Java 6 or 7, you will need to use the ThreeTen-Backport for java.time, further adapted for Android below API level 26 in ThreeTenABP. If you’re doing only very little very simple date and time work and forward compatibility somehow isn’t an issue, you may consider whether the external dependency is worth it. Please take into account that your external dependency is but a backport of what is built into Java 8 and later, so rock solid, and therefore furthermore that you will only need it until you migrate to Java 8 or later. At which time you can change your imports, retest and do away with the backport.

Your examples of thinkable liabilities

Current EE libraries X and Y don't work correctly with LocalDate

There are some examples of that, also library classes in the JDK. My choice would be to use java.time in my own code and only convert just before calling into the API that doesn’t yet accept a java.time type. And conversely if I get an instance of an outdated class from the API, convert it first thing and use java.time for the rest.

This very useful pattern is broken with LocalTime

I know of no such pattern. On the contrary java.time uses patterns immutable objects and factory method, in contrast to most of the old classes.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161