Why is the Date constructor deprecated, and what do I use instead?
Asked Answered
N

14

279

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?

Nickolai answered 15/4, 2011 at 13:25 Comment(12)
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!Hizar
@Paul Sasik, yes, but there is Calendar.JANUARY constant for example, and one for each monthFrance
possible duplicate of Why was "new Date(int year, int month, int day)" deprecated?Underdrawers
@PaulSasik lol. Yeah, stupid Java. Had to switch from C# to Java and OMG the pain and misery.Chukker
possible duplicate of Why were most java.util.Date methods deprecated?Morbidezza
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.Airdrop
It was recommended by Oracle to switch to java.time in Java 8. docs.oracle.com/javase/tutorial/datetime/iso/legacy.htmlHemicellulose
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 project, and further adapted to Android in ThreeTenABP.Airdrop
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.Electron
To future readers: this question was asked in 2011, and its accepted answer is not the way you should do it nowadays. This answer is better.Counterwork
@MCEmperor Thanks, I updated the "Accepted answer" to be that one instead. 🙂Nickolai
The big thing here is you have to realize that MONTH is 0-based, that's a classic error.Nataline
A
141

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

Airdrop answered 6/2, 2014 at 9:12 Comment(5)
Props for actually mentioning the root cause and providing coverage of all available alternatives.Bozovich
This is the correct answer and Calendar class should be avoided. ThreeTen is the best optionOuphe
@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.Garlinda
@Garlinda That info is already laid out in the last section of the Answer, "About java.time", which I updated just now.Airdrop
Very good, thanks for the update.Garlinda
W
289

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

Wynd answered 15/4, 2011 at 13:30 Comment(6)
By saying "doesn't work well with internationalization", do you mean that for Date, you cannot assign TimeZone for it? ThanksAntoinette
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.Verein
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>));Thetos
"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.Sanfred
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.Airdrop
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();Electron
A
141

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

Airdrop answered 6/2, 2014 at 9:12 Comment(5)
Props for actually mentioning the root cause and providing coverage of all available alternatives.Bozovich
This is the correct answer and Calendar class should be avoided. ThreeTen is the best optionOuphe
@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.Garlinda
@Garlinda That info is already laid out in the last section of the Answer, "About java.time", which I updated just now.Airdrop
Very good, thanks for the update.Garlinda
G
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.

Grindelia answered 15/4, 2011 at 13:27 Comment(2)
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.Verein
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.Airdrop
S
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.

Sapodilla answered 28/5, 2015 at 1:33 Comment(0)
S
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.

Sanfred answered 15/4, 2011 at 13:45 Comment(1)
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();Electron
V
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)

Vaccaro answered 20/12, 2013 at 10:3 Comment(0)
I
7

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

Use java.util.Calendar instead.

Impoverished answered 15/4, 2011 at 13:28 Comment(0)
A
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.

Andante answered 5/2, 2014 at 22:49 Comment(0)
F
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
Famulus answered 24/9, 2019 at 11:57 Comment(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.Airdrop
@BasilBourque thanks for the suggestion, i am looking forward to update it soon.Famulus
E
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));
Electron answered 3/5, 2019 at 23:13 Comment(2)
Both of these terrible classes were supplanted years ago by the java.time classes defined in JSR 310.Airdrop
Updated answer to show Date, Calendar, and Java 1.8 versions.Electron
T
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

Tucana answered 15/4, 2011 at 13:30 Comment(0)
B
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

Bareback answered 11/7, 2018 at 7:36 Comment(2)
These terribly troublesome classes were supplanted years ago by the modern java.time classes, specifically Instant and ZonedDateTime.Airdrop
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).Electron
A
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.

Aubin answered 13/7, 2020 at 7:35 Comment(0)
I
1
new GregorianCalendar(1985, Calendar.JANUARY, 1).getTime();

(the pre-Java-8 way)

Innocence answered 5/10, 2018 at 18:57 Comment(1)
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.Androsphinx

© 2022 - 2024 — McMap. All rights reserved.