270

I come from the C# world, so not too experienced with Java yet. I was just told by Eclipse that Date was deprecated:

Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));

Why? And what (especially in cases like above) should be used instead?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Svish
  • 152,914
  • 173
  • 462
  • 620
  • 52
    I'm experiencing a similar learning curve, also going from C# to Java. The other thing that bit me is that the month of year is a 0-based system (0 to 11 where Jan. = 0 and Dec. = 11) but the days of the month are 1-based (1 to 31). Heads up on that one! – Paul Sasik Apr 15 '11 at 13:36
  • 3
    @Paul Sasik, yes, but there is Calendar.JANUARY constant for example, and one for each month – Diogo Apr 15 '11 at 14:07
  • 1
    possible duplicate of [Why was "new Date(int year, int month, int day)" deprecated?](http://stackoverflow.com/questions/460423/why-was-new-dateint-year-int-month-int-day-deprecated) – Pops Apr 15 '11 at 14:20
  • 8
    @PaulSasik lol. Yeah, stupid Java. Had to switch from C# to Java and OMG the pain and misery. – cbmeeks Mar 22 '13 at 13:56
  • 2
    possible duplicate of [Why were most java.util.Date methods deprecated?](http://stackoverflow.com/questions/2901262/why-were-most-java-util-date-methods-deprecated) – Thomas Nov 26 '13 at 08:00
  • 11
    The snarky "lol" remarks about Java from C# people made *me* laugh because .Net got its decent date-time library ([Noda Time](https://code.google.com/p/noda-time/)) from a port of the excellent Java library [Joda-Time](http://www.joda.org/joda-time/). – Basil Bourque Feb 06 '14 at 08:48
  • 2
    It was recommended by Oracle to switch to java.time in Java 8. https://docs.oracle.com/javase/tutorial/datetime/iso/legacy.html – Demwis Apr 11 '16 at 04:15
  • 1
    The Joda-Time team also advises us to migrate to java.time. No reason not to begin migrating. Much of the java.time functionality is back-ported to Java 6 & 7 in the [ThreeTen-Backport](http://www.threeten.org/threetenbp/) project, and further adapted to Android in ThreeTenABP. – Basil Bourque Jun 10 '16 at 15:38
  • Note: This Date constructor expects the years input using 1900 as a base. So to represent the year 1985 in the Date object, you need to pass 85 as the year input. The Date from your example will store the year 3885. – Joel Richard Koett May 03 '19 at 23:31
  • 1
    **To future readers**: this question was asked in 2011, and its accepted answer is not the way you should do it nowadays. [This answer](https://stackoverflow.com/a/21598394/507738) is better. – MC Emperor Mar 09 '21 at 10:45
  • 1
    @MCEmperor Thanks, I updated the "Accepted answer" to be that one instead. – Svish Mar 10 '21 at 14:09

14 Answers14

286

The java.util.Date class isn't actually deprecated, just that constructor, along with a couple other constructors/methods are deprecated. It was deprecated because that sort of usage doesn't work well with internationalization. The Calendar class should be used instead:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1988);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date dateRepresentation = cal.getTime();

Take a look at the date Javadoc:

http://download.oracle.com/javase/6/docs/api/java/util/Date.html

erakitin
  • 11,437
  • 5
  • 44
  • 49
BuffaloBuffalo
  • 7,703
  • 4
  • 28
  • 29
  • 1
    By saying "doesn't work well with internationalization", do you mean that for Date, you cannot assign TimeZone for it? Thanks – DiveInto Dec 01 '15 at 05:55
  • What Date did was parse a String, so instead we now have to substring a String which contains the year, month and day? Seems like a lot of extra hassle for something which in most cases doesn't need such complex logic and methods added to it. – G_V Mar 06 '17 at 08:39
  • 2
    Just to add, this will take the default timezone in consideration. If we want to specify any other timezone, we can use `Calendar cal = Calendar.getInstance(TimeZone.getTimeZone());` – Vikas Prasad Mar 17 '17 at 16:45
  • 3
    *"The Calendar class should be used instead"* - For Java 8 and later, the `java.time.*` classes are the better option ... if you are changing your code. – Stephen C May 30 '18 at 06:15
  • FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Nov 28 '18 at 19:17
  • This solution works great, except that it doesn't use zero-time for hours-minutes-seconds-milliseconds like new Date(year, month, day) did. Also, the Date constructor expects years in the format of years since 1900. So to give an accurate replacement for the deprecated date constructor, we need something like: Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year + 1900, month, date); Date dateRepresentation = cal.getTime(); – Joel Richard Koett May 03 '19 at 23:00
135

tl;dr

LocalDate.of( 1985 , 1 , 1 )

…or…

LocalDate.of( 1985 , Month.JANUARY , 1 )

Details

The java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat classes were rushed too quickly when Java first launched and evolved. The classes were not well designed or implemented. Improvements were attempted, thus the deprecations you’ve found. Unfortunately the attempts at improvement largely failed. You should avoid these classes altogether. They are supplanted in Java 8 by new classes.

Problems In Your Code

A java.util.Date has both a date and a time portion. You ignored the time portion in your code. So the Date class will take the beginning of the day as defined by your JVM’s default time zone and apply that time to the Date object. So the results of your code will vary depending on which machine it runs or which time zone is set. Probably not what you want.

If you want just the date, without the time portion, such as for a birth date, you may not want to use a Date object. You may want to store just a string of the date, in ISO 8601 format of YYYY-MM-DD. Or use a LocalDate object from Joda-Time (see below).

Joda-Time

First thing to learn in Java: Avoid the notoriously troublesome java.util.Date & java.util.Calendar classes bundled with Java.

As correctly noted in the answer by user3277382, use either Joda-Time or the new java.time.* package in Java 8.

Example Code in Joda-Time 2.3

DateTimeZone timeZoneNorway = DateTimeZone.forID( "Europe/Oslo" );
DateTime birthDateTime_InNorway = new DateTime( 1985, 1, 1, 3, 2, 1, timeZoneNorway );

DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );
DateTime birthDateTime_InNewYork = birthDateTime_InNorway.toDateTime( timeZoneNewYork ); 

DateTime birthDateTime_UtcGmt = birthDateTime_InNorway.toDateTime( DateTimeZone.UTC );

LocalDate birthDate = new LocalDate( 1985, 1, 1 );

Dump to console…

System.out.println( "birthDateTime_InNorway: " + birthDateTime_InNorway );
System.out.println( "birthDateTime_InNewYork: " + birthDateTime_InNewYork );
System.out.println( "birthDateTime_UtcGmt: " + birthDateTime_UtcGmt );
System.out.println( "birthDate: " + birthDate );

When run…

birthDateTime_InNorway: 1985-01-01T03:02:01.000+01:00
birthDateTime_InNewYork: 1984-12-31T21:02:01.000-05:00
birthDateTime_UtcGmt: 1985-01-01T02:02:01.000Z
birthDate: 1985-01-01

java.time

In this case the code for java.time is nearly identical to that of Joda-Time.

We get a time zone (ZoneId), and construct a date-time object assigned to that time zone (ZonedDateTime). Then using the Immutable Objects pattern, we create new date-times based on the old object’s same instant (count of nanoseconds since epoch) but assigned other time zone. Lastly we get a LocalDate which has no time-of-day nor time zone though notice the time zone applies when determining that date (a new day dawns earlier in Oslo than in New York for example).

ZoneId zoneId_Norway = ZoneId.of( "Europe/Oslo" );
ZonedDateTime zdt_Norway = ZonedDateTime.of( 1985 , 1 , 1 , 3 , 2 , 1 , 0 , zoneId_Norway );

ZoneId zoneId_NewYork = ZonedId.of( "America/New_York" );
ZonedDateTime zdt_NewYork = zdt_Norway.withZoneSameInstant( zoneId_NewYork );

ZonedDateTime zdt_Utc = zdt_Norway.withZoneSameInstant( ZoneOffset.UTC );  // Or, next line is similar.
Instant instant = zdt_Norway.toInstant();  // Instant is always in UTC.

LocalDate localDate_Norway = zdt_Norway.toLocalDate();

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. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?

Table of which java.time library to use with which version of Java or Android

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 5
    Props for actually mentioning the root cause and providing coverage of all available alternatives. – mabi Apr 11 '16 at 13:52
  • 1
    This is the correct answer and Calendar class should be avoided. ThreeTen is the best option – ant2009 Nov 16 '19 at 14:21
  • @Basil Bourque You mention later versions of Android bundle implementations of java.time classes. Can you be more specific about which versions? I am trying to replace old Date and Calendar code for an Android app and am not sure where to begin. – AJW Nov 22 '21 at 03:37
  • 1
    @AJW That info is already laid out in the last section of the Answer, "About java.time", which I updated just now. – Basil Bourque Nov 22 '21 at 06:10
  • Very good, thanks for the update. – AJW Nov 22 '21 at 15:17
105

The specific Date constructor is deprecated, and Calendar should be used instead. The JavaDoc for Date describes which constructors are deprecated and how to replace them using a Calendar.

Sae1962
  • 1,122
  • 15
  • 31
Ruben
  • 9,056
  • 6
  • 34
  • 44
  • 33
    Calendar requires an extra object and like 8 lines more code to do the same thing which is create a Date object from what I can tell. It's confusing and seems unnecessary when you just need a Date and not a timezone adjusted variable. – G_V Mar 06 '17 at 08:37
  • 9
    FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Nov 28 '18 at 19:18
13

I came across this question as a duplicate of a newer question which asked what the non-deprecated way to get a Date at a specific year, month, and day was.

The answers here so far say to use the Calendar class, and that was true until Java 8 came out. But as of Java 8, the standard way to do this is:

LocalDate localDate = LocalDate.of(1985, 1, 1);

And then if you really really need a java.util.Date, you can use the suggestions in this question.

For more info, check out the API or the tutorials for Java 8.

Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
12

One reason that the constructor is deprecated is that the meaning of the year parameter is not what you would expect. The javadoc says:

As of JDK version 1.1, replaced by Calendar.set(year + 1900, month, date).

Notice that the year field is the number of years since 1900, so your sample code most likely won't do what you expect it to do. And that's the point.

In general, the Date API only supports the modern western calendar, has idiosyncratically specified components, and behaves inconsistently if you set fields.

The Calendar and GregorianCalendar APIs are better than Date, and the 3rd-party Joda-time APIs were generally thought to be the best. In Java 8, they introduced the java.time packages, and these are now the recommended alternative.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • This solution works great, except that it doesn't use zero-time for hours-minutes-seconds-milliseconds like new Date(year, month, day) did. So we need something like: Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year + 1900, month, date); Date dateRepresentation = cal.getTime(); – Joel Richard Koett May 03 '19 at 23:02
9

Please note that Calendar.getTime() is nondeterministic in the sense that the day time part defaults to the current time.

To reproduce, try running following code a couple of times:

Calendar c = Calendar.getInstance();
c.set(2010, 2, 7); // NB: 2 means March, not February!
System.err.println(c.getTime());

Output eg.:

Sun Mar 07 10:46:21 CET 2010

Running the exact same code a couple of minutes later yields:

Sun Mar 07 10:57:51 CET 2010

So, while set() forces corresponding fields to correct values, it leaks system time for the other fields. (Tested above with Sun jdk6 & jdk7)

nbrooks
  • 18,126
  • 5
  • 54
  • 66
Tijnkabouter
  • 157
  • 1
  • 10
7

Date itself is not deprecated. It's just a lot of its methods are. See here for details.

Use java.util.Calendar instead.

Rob W
  • 341,306
  • 83
  • 791
  • 678
Mike Thomsen
  • 36,828
  • 10
  • 60
  • 83
6

Most Java developers currently use the third party package Joda-Time. It is widely regarded to be a much better implementation.

Java 8 however will have a new java.time.* package. See this article, Introducing the New Date and Time API for JDK 8.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
davesbrain
  • 606
  • 7
  • 12
6

As the Date constructor is deprecated, you can try this code.

import java.util.Calendar;

  Calendar calendar = Calendar.getInstance();
     calendar.set(Calendar.HOUR_OF_DAY, 6);// for 6 hour
     calendar.set(Calendar.MINUTE, 0);// for 0 min
     calendar.set(Calendar.SECOND, 0);// for 0 sec
     calendar.set(1996,0,26);// for Date [year,month(0 to 11), date]

    Date date = new Date(calendar.getTimeInMillis());// calendar gives long value

    String mConvertedDate = date.toString();// Fri Jan 26 06:00:00 GMT+05:30 1996
Divyanshu Kumar
  • 1,272
  • 15
  • 15
  • 2
    These terrible classes are now legacy, having been supplanted years ago by the *java.time* classes defined in JSR 310. Suggesting `Date` and `Calendar` in 2019 is poor advice. – Basil Bourque Sep 24 '19 at 15:32
  • @BasilBourque thanks for the suggestion, i am looking forward to update it soon. – Divyanshu Kumar Sep 25 '19 at 09:31
3

The Date constructor expects years in the format of years since 1900, zero-based months, one-based days, and sets hours/minutes/seconds/milliseconds to zero.

Date result = new Date(year, month, day);

So using the Calendar replacement (zero-based years, zero-based months, one-based days) for the deprecated Date constructor, we need something like:

Calendar calendar = Calendar.getInstance();
calendar.clear(); // Sets hours/minutes/seconds/milliseconds to zero
calendar.set(year + 1900, month, day);
Date result = calendar.getTime();

Or using Java 1.8 (which has zero-based year, and one-based months and days):

Date result = Date.from(LocalDate.of(year + 1900, month + 1, day).atStartOfDay(ZoneId.systemDefault()).toInstant());

Here are equal versions of Date, Calendar, and Java 1.8:

int year = 1985; // 1985
int month = 1; // January
int day = 1; // 1st

// Original, 1900-based year, zero-based month, one-based day
Date date1 = new Date(year - 1900, month - 1, day);

// Calendar, zero-based year, zero-based month, one-based day
Calendar calendar = Calendar.getInstance();
calendar.clear(); // Sets hours/minutes/seconds/milliseconds to zero
calendar.set(year, month - 1, day);
Date date2 = calendar.getTime();

// Java-time back to Date, zero-based year, one-based month, one-based day
Date date3 = Date.from(LocalDate.of(year, month, day).atStartOfDay(ZoneId.systemDefault()).toInstant());

SimpleDateFormat format = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss.SSS");

// All 3 print "1985-Jan-01 00:00:00.000"
System.out.println(format.format(date1));
System.out.println(format.format(date2));
System.out.println(format.format(date3));
2

You can make a method just like new Date(year,month,date) in your code by using Calendar class.

private Date getDate(int year,int month,int date){
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.MONTH, month-1);
    cal.set(Calendar.DAY_OF_MONTH, day);
    return cal.getTime();
}

It will work just like the deprecated constructor of Date

  • 1
    These terribly troublesome classes were supplanted years ago by the modern *java.time* classes, specifically `Instant` and `ZonedDateTime`. – Basil Bourque Jul 11 '18 at 09:32
  • Solution above should add 1900 to the year, and should NOT subtract 1 from the month, and also should run cal.clear() after the Calendar.getInstance() line, so that the hours/minutes/seconds/milliseconds get zeroed (as they do in the Date constructor). – Joel Richard Koett May 03 '19 at 23:24
2

Similar to what binnyb suggested, you might consider using the newer Calendar > GregorianCalendar method. See these more recent docs:

http://download.oracle.com/javase/6/docs/api/java/util/GregorianCalendar.html

Joshua
  • 3,615
  • 1
  • 26
  • 32
2

I got this from Secure Code Guideline for Java

The examples in this section use java.util.Date extensively as it is an example of a mutable API class. In an application, it would be preferable to use the new Java Date and Time API (java.time.*) which has been designed to be immutable.

Ender
  • 835
  • 1
  • 12
  • 23
0
new GregorianCalendar(1985, Calendar.JANUARY, 1).getTime();

(the pre-Java-8 way)

Floern
  • 33,559
  • 24
  • 104
  • 119
Curtis Yallop
  • 6,696
  • 3
  • 46
  • 36
  • It’s probably the best you can do without java.time. However also pre-Java 8 you can use java.time, there is a backport: [the ThreeTen Backport library](https://www.threeten.org/threetenbp/). – Ole V.V. Oct 08 '18 at 07:01