285

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?

11
  • 57
    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! Commented Apr 15, 2011 at 13:36
  • 4
    @Paul Sasik, yes, but there is Calendar.JANUARY constant for example, and one for each month Commented Apr 15, 2011 at 14:07
  • 9
    @PaulSasik lol. Yeah, stupid Java. Had to switch from C# to Java and OMG the pain and misery. Commented Mar 22, 2013 at 13:56
  • 2
    possible duplicate of Why were most java.util.Date methods deprecated? Commented Nov 26, 2013 at 8:00
  • 11
    The snarky "lol" remarks about Java from C# people made me laugh because .Net got its decent date-time library (Noda Time) from a port of the excellent Java library Joda-Time. Commented Feb 6, 2014 at 8:48

14 Answers 14

296

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

Sign up to request clarification or add additional context in comments.

6 Comments

By saying "doesn't work well with internationalization", do you mean that for Date, you cannot assign TimeZone for it? Thanks
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.
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(<timezone id>));
"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.
FYI, the terribly troublesome old date-time classes such as java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat are now legacy, supplanted by the java.time classes built into Java 8 and later. See Tutorial by Oracle.
|
150

tl;dr

LocalDate.of( 1985 , 1 , 1 ) // Months 1-12 for January-December. 

…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

5 Comments

Props for actually mentioning the root cause and providing coverage of all available alternatives.
This is the correct answer and Calendar class should be avoided. ThreeTen is the best option
@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 That info is already laid out in the last section of the Answer, "About java.time", which I updated just now.
Very good, thanks for the update.
106

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.

2 Comments

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.
FYI, the terribly troublesome old date-time classes such as java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat are now legacy, supplanted by the java.time classes built into Java 8 and later. See Tutorial by Oracle.
14

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.

Comments

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.

1 Comment

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();
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)

Comments

7

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

Use java.util.Calendar instead.

Comments

7

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 

2 Comments

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.
@BasilBourque thanks for the suggestion, i am looking forward to update it soon.
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.

Comments

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 Comments

Both of these terrible classes were supplanted years ago by the java.time classes defined in JSR 310.
Updated answer to show Date, Calendar, and Java 1.8 versions.
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

Comments

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

2 Comments

These terribly troublesome classes were supplanted years ago by the modern java.time classes, specifically Instant and ZonedDateTime.
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).
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.

Comments

1
new GregorianCalendar(1985, Calendar.JANUARY, 1).getTime(); 

(the pre-Java-8 way)

1 Comment

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.