What is really meant when using Java Date utilities and something has been deprecated. Does this mean that it is discouraged to use, or does it imply that it is forbidden?
I am guessing it is bad practice to use deprecated methods, but am not sure and wanted to find out.
For example, I am trying to use code such as the following
String date = request.getParameter("date");
model.setDate(new Date(date));
Of course...this is a high level example, but in this situation, my model uses type Date and I need to pull the date off the request as a String and create a date with it.
It works fine how I have it, but it is using a deprecated method.
EDIT - I have gone back and used
SimpleDateFormat formatter = new SimpleDateFormat();
model.setDate(formatter.parse(request.getParameter("date");
The date is in the format MM/DD/YYY like 07/23/2010 but I am getting a ParseException
What could this be from?
You're right that this is bad practice. In almost all cases, deprecated methods tell you what to use instead, and this is no exception (see the Javadocs).
You're trying to create a Date out of a String. But what format is the String in? How should it be parsed? Is it UK or US date format?
The "proper" way to do this is to create an instance of SimpleDateFormat, and call its parse() method passing in your text string. This is guaranteed to work in future, and will be more robust now.
A lot of people have mentioned what Deprecated means, but I don't see any explanation of why these methods are deprecated:
Sun (before they were part of Oracle) deprecated a number of methods in Date to get people to use the Calendar/GregorianCalendar classes for date manipulation instead.
Deprecated objects or methods merely means that if you want to use it in current project, rather use what is recommended. The reason why they still have it is for legacy codes who have used the deprecated method before it was deprecated. Typical example is StringTokenizer vs String.split() method.
For your Date example use SimpleDateFormat to do conversion from String to Date. This allows you to create a date format from which your string date can be parsed to create a Date object.
For your EDIT do this
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
model.setDate(formatter.parse(request.getParameter("date")));
ParseException is caused since you didn't provide a date format structure so the SimpleDateFormat didn't know how your date was structured.
What "Deprecated" Means
You may have heard the term,
"self-deprecating humor," or humor
that minimizes the speaker's
importance. A deprecated class or
method is like that. It is no longer
important. It is so unimportant, in
fact, that you should no longer use
it, since it has been superseded and
may cease to exist in the future.
Java provides a way to express
deprecation because, as a class
evolves, its API (application
programming interface) inevitably
changes: methods are renamed for
consistency, new and better methods
are added, and fields change. But such
changes introduce a problem. You need
to keep the old API around until
developers make the transition to the
new one, but you don't want them to
continue programming to the old API.
The ability to deprecate a class,
method, or member field solves the
problem. Java supports two mechanisms
for deprecation: and an annotation,
(supported starting with J2SE 5.0) and
a Javadoc tag (supported since 1.1).
Existing calls to the old API continue
to work, but the annotation causes the
compiler to issue a warning when it
finds references to deprecated program
elements. The Javadoc tag and
associated comments warn users against
using the deprecated item and tell
them what to use instead.them what to use instead.
http://download-llnw.oracle.com/javase/1.5.0/docs/guide/javadoc/deprecation/deprecation.html
You are right, Its discouraged to use deprecated methods.
This is because these methods may have issues in some situation or have been replaced with more optimistic solutions And also future versions may not support these.
Deprecated means it is planned for removal, because it is buggy or some other bad reason.
It is better to use SimpleDateFormat.parse(); to parse your strings.
In general, when Sun (Oracle, whatever) declares a Java method deprecated, it means that they changed their minds about including it, they discourage you from using it, and they may remove it in some future version. Of course it's likely to be a long time before it gets removed as who knows how much existing code there is out there using it, and what's the point of breaking existing programs just because the inventors of Java think they now have a better idea about how to do something?
Presumably they had a good reason for deprecating something, so you should investigate WHY they say that some newer function is better.
In the case of deprecated Date methods, usually this means that they suggest you now use the Calendar or SimpleDateFormat classes. In your case, probably the latter.
deprecated: something that exists in the current version of Java, but will be removed from future versions at some point.
For your edit, you need to properly initialize the SimpleDateFormat, so it knows what format is coming in. For 07/22/1978 format:
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
As other said, the java.util.Date methods were deprecated because the Java team believed they had a better solution in the java.util.Calendar.
Unfortunately that class also proved to be confusing, troublesome, and poorly designed.
So, yes, you should avoid deprecated methods in deference to their replacements. But now those replacements (.Calendar) have a replacement (java.time).
java.time
All the old date-time classes have been supplanted by the java.time framework built into Java 8. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
Use the java.time.format package for parsing and generating String representations of date-time values.
String input = "07/23/2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MM/dd/yyyy" );
The new classes include LocalDate for representing a date-only value without time-of-day.
LocalDate localDate = LocalDate.parse( input , formatter );
If you call toString on a LocalDate you get a String representation of the date value in the standard ISO 8601 format, YYYY-MM-DD. To generate a String in other formats, define another formatter. Or call the 'localize' methods to let java.time do the heavy lifting in determining a particular localized format.
Nothing will break if you use them...yet.
But they may well be removed in future versions.
Related
I was working on code in Java 7 which used extensive date conversions to String and From string to Date object, for which they were creating new SimpleDateFormat("Pattern") whenever they needed the date to be converted(5-6 patterns were there overall). So I need to ask that what if I write some code like this:
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
private SimpleDateFormat getsiSimpleDateFormat(SimpleDateFormat simpleDateFormat, String format){
simpleDateFormat.applyPattern(format);
return simpleDateFormat;
}
So here I am reusing my simpleDateFormat and just adding a pattern where ever necessary.
Is this approach good?
Or there can be some more improvement?
By using this approach would I face increase in processing or memory?
Those two are sensibly the same. Looking into the code, you can see that using the basic constructor leads to :
public SimpleDateFormat(String pattern)
{
this(pattern, Locale.getDefault(Locale.Category.FORMAT));
}
The this leads to:
public SimpleDateFormat(String pattern, Locale locale)
{
if (pattern == null || locale == null) {
throw new NullPointerException();
}
initializeCalendar(locale);
this.pattern = pattern; // This part is important
this.formatData = DateFormatSymbols.getInstanceRef(locale);
this.locale = locale;
initialize(locale);
}
Using applyPattern(pattern) on the other hand gives this result:
public void applyPattern(String pattern)
{
compiledPattern = compile(pattern);
this.pattern = pattern; // Same as initialization
}
As pointed out by Roby Cornelissen in the comments, both approaches are not exactly the same. applyPattern supposes you have already initialized your SimpleDateFormat, but skips the locale + calendar initialization.
In both performance and memory, using applyPattern is better that re-creating an object. The former answer was:
There are, subsequently, only one difference: using applyPattern will use less memory, as you are using only one object instead of re-initializing a new SimpleDateFormat(). The choice is up to you.
And is not completely correct (there are more than one difference).
EDIT
If any of you wonder, the initialize() method from the constructor compiles the pattern, thus throwing an IllegalArgumentException if you give it a wrong pattern either. The code (I posted here in the first place) makes it look like it would not crash.
java.time
The SimpleDateFormat class is part of the old troublesome date-time classes bundled with the earliest versions of Java that are no longer used. Now legacy, they are supplanted entirely by the java.time classes.
Use DateTimeFormatter instead.
Thread Safety
The legacy date-time classes are not thread-safe. If your app uses threads, or might possibly in the future, then you should not pass around an instance of SimpleDateFormat to be reused.
In contrast, the java.time classes use immutable objects and are thread-safe. You may indeed retain a DateTimeFormatter to be passed around and reused.
Premature Optimization
You seem to be falling into the trap known as premature optimization. Programmers are notoriously inept at predicting the performance of their apps. Expected bottlenecks often run smoothly while other ignored code chokes. Modern hardware and operating systems make performance even trickier to predict.
Today’s JVM implementations are highly tuned, likely the most highly tuned software in history. Trust them to run your code well.
Other than a few basics such as avoiding unnecessary instantiations and network connections within large loops that run often, do not worry about performance. Instead use profiling tools, monitoring tools, and some logging, to determine and measure the actual performance of your app to identify legitimate performance concerns.
First, please note that this question is not a duplicate of this Question:
Java Date vs Calendar. My question is much more specific. The referenced question asks "what" (or "which"), but I already know the "what" and am asking the "why".
I am on a team working on enhancements to an existing Java project for a client. This Java project uses java 6, and does not have Joda Time as a dependency. After inquiring, it looks like adding Joda Time or upgrading to Java 8 are not options.
So, when it comes to representing date/time as a field in an object, we have to use either Calendar or Date for property typing. The legacy code of this project is littered with Objects that use Calendar to represent date/time fields -- fields that we would never have cause to manipulate (as in add or subtract units of time, etc). I know that this is bad practice, as Calendar is a more complex object, while Date is simpler and would work just as well. (And granted, I know that both are fundamentally wrappers for a long of epoch millis, are mutable, and are poorly designed, but again these are our only two options.)
In other words, an object like this:
public class Reservation {
private Guest guest;
// Set only once, never used for calculations
private Calendar dateReserved;
...
}
Should be this instead:
public class Reservation {
private Guest guest;
// Set only once, never used for calculations
private Date dateReserved;
...
}
I then noticed that when adding new Objects for new features, my team was following the same convention of using Calendar instead of Date. When I brought this up, the reply was that it's better to use Calendar because it can do more and doesn't have all these deprecated methods like Date does.
I know that this reasoning is oversimplified. I also see that this answer to the broader question of usage expresses the same view, namely that Calendar should not be used for property typing. However, the answer doesn't contain much explanation as to why Calendar should not be preferred.
So I already know the "What". But I'm trying to make the case to my team, so my question is, "Why"? Why, when property typing, should Date be preferred to Calendar? What are the disadvantages of using Calendar instead of Date for property typing?
I agree with Jon Skeet's comment regarding calendar systems and time zones, and I think your premise is fundamentally flawed. Dates aren't better than Calendars. If you're never ever ever going to compare times, or never ever ever have two dates in different time zones, then sure, the smaller footprint can be nice, I guess, but at that point, just use longs and Unix timestamps. Calendars are by far the better object model, and after all, if you absolutely need it, you can get a Date object from it.
If you are stuck having to choose between Date and Calendar when property typing:
Use Calendar if either one of these is true:
You need to be able to adjust the date/time after it is initially set
(such as changing the month while leaving the day and hour the same).
You need to be aware of timezone.
Otherwise, use Date for the following reasons:
Expressing your intentions accurately. If you use Calendar, you are implying that you want a certain functionality that you don't actually intend to use (timezones, changing the day or month, etc).
Less hassle with String representations. For example, consider this class:
public class Reservation {
private Guest guest;
private Calendar dateReserved;
#Override
public String toString() {
return String.format("Reservation{guest=%s,dateReserved=\"%s\"}",
guest, dateReserved);
}
}
Now if you print out an instance of this class, you'll get something hideous:
Reservation{guest=Guest{id=17,name="John Smith"},dateReserved="java.util.GregorianCalendar[time=1426707020619,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2015,MONTH=2,WEEK_OF_YEAR=12,WEEK_OF_MONTH=3,DAY_OF_MONTH=18,DAY_OF_YEAR=77,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=0,HOUR_OF_DAY=12,MINUTE=30,SECOND=20,MILLISECOND=619,ZONE_OFFSET=-28800000,DST_OFFSET=3600000]"}
Whereas if you had used Date instead, you'd get this:
Reservation{guest=Guest{id=17,name="John Smith"},dateReserved="Wed Mar 18 12:34:26 PDT 2015"}
So if you use Calendar and you want your toString() to be usable, you would need to call dateReserved.getTime() -- which means you'd need to add a null check. This goes for whether or not you end up using a DateFormat object.
Date is a smaller object, quicker to instantiate and with less overhead.
Date is practically immutable -- meaning that the only way to change a date object is to use deprecated methods. So, as said in point 1, expressing your intentions matters. If your date field should be immutable, don't confuse developers who will touch your code in the future by using Calendar (unless of course you need timezone awareness).
"Date" is a more intuitive name than "Calendar" for the type of a field that represents a single point in time.
Date object has fewer fields and occupies less memory than Calendar object and is also faster to instantiate.
As most people are painfully aware of by now, the Java API for handling calendar dates (specifically the classes java.util.Date and java.util.Calendar) are a terrible mess.
Off the top of my head:
Date is mutable
Date represents a timestamp, not a date
no easy way to convert between date components (day, month, year...) and Date
Calendar is clunky to use, and tries to combine different calendar systems into one class
This post sums it up quite well, and JSR-310 also expains these problems.
Now my question is:
How did these classes make it into the Java SDK? Most of these problems seem fairly obvious (especially Date being mutable) and should have been easy to avoid. So how did it happen? Time pressure? Or are the problems obvious in retrospect only?
I realize this is not strictly a programming question, but I'd find it interesting to understand how API design could go so wrong. After all, mistakes are always a good learning opportunity (and I'm curious).
Someone put it better than I could ever say it:
Class Date represents a specific instant in time, with millisecond
precision. The design of this class is a very bad joke - a sobering
example of how even good programmers screw up. Most of the methods in
Date are now deprecated, replaced by methods in the classes below.
Class Calendar is an abstract class for converting between a Date
object and a set of integer fields such as year, month, day, and hour.
Class GregorianCalendar is the only subclass of Calendar in the JDK.
It does the Date-to-fields conversions for the calendar system in
common use. Sun licensed this overengineered junk from Taligent - a
sobering example of how average programmers screw up.
from Java Programmers FAQ, version from 07.X.1998, by Peter van der Linden - this part was removed from later versions though.
As for mutability, a lot of the early JDK classes suffer from it (Point, Rectangle, Dimension, ...). Misdirected optimizations, I've heard some say.
The idea is that you want to be able to reuse objects (o.getPosition().x += 5) rather than creating copies (o.setPosition(o.getPosition().add(5, 0))) as you have to do with immutables. This may even have been a good idea with the early VMs, while it's most likely isn't with modern VMs.
Java's early APIs are nothing more than a product of their time. Immutability only became a popular concept years after that. You say that immutability is "obvious". That might be true now but it wasn't then. Just like dependency injection is now "obvious" but it wasn't 10 years ago.
It was also at one time expensive to create Calendar objects.
They remain that way for backwards compatibility reasons. What is perhaps more unfortunate was that once the mistake was realized the old class wasn't deprecated and new date/time classes were created for all APIs going forward. This has to some degree occurred with the JDK 8 adoption of a JodaTime like API (java.time, JSR 310) but really it's too little too late.
Time is itself not easy to measure and to handle with. Just look at the length of the wikipedia article about time. And then, there are different understandings about time itself: a absoulte time point (as a constant), a time point at a certain place, a time range, the resolution of time....
I remember, when i saw java.util.Date the first time (JDK 1.0?) i was really happy about it. The languages i knew of didn't had such a feature. I didn't have think about time conversion etc.
I think it's mess, because everything that changes leaves a mess if you evolve from one level of understanding (XMLGregorianCaldender vs. Date) and requirements (Nanoseconds, past 2030) to higher level, but keeping the old untouched. And java.util.Date is not a Exception. Just look at the I/O subsystem or the transition from AWT to Swing...
And because of that, "we should sometimes press the reset button." (who said that, btw.?)
I am using netbeans 7.2. the IDE is applying a line-through to a class name, what does it means and how can I resolve it?
Date cookiedate = new Date(timeStamp);
see the shot how its looking
I suspect it means it's deprecated. See here for more info.
Java provides a way to express deprecation because, as a class
evolves, its API (application programming interface) inevitably
changes: methods are renamed for consistency, new and better methods
are added, and fields change. But such changes introduce a problem.
You need to keep the old API around until developers make the
transition to the new one, but you don't want them to continue
programming to the old API.
The ability to deprecate a class, method, or member field solves the
problem.
I would suggest using Joda-Time instead (with respect to the suggestions made by other posters here), since the Date/Calendar stuff that isn't deprecated is such a pain to use (non-untuitive api, mutable, thread-unsafe)
new Date(timeStamp);
You are using parameterized constructor of Date class which is deprecated, so you see that line cross. In fact most of the methods of Date class is now deprecated.
See documentation of Date class which clearly marks the parameterized constructor as Deprecated.
Date(String s)
Deprecated.
As of JDK version 1.1, replaced by
DateFormat.parse(String s).
I would rather suggest to use Joda Time API if you want to make your life easier while working with Dates.
It means the API you are invoking is deprecated, you should use Calendar API for example or if you are looking for a more sophisticated API I suggest to use Joda
Linethrough means it is deprecated. There is some other class/method available in place of that class/method. And also Netbeans shows somewhere around that deprecated class/method what you can use use instead of it if you have javadoc set up in it
I am just going through a tutorial and the instructor seemed to gloss over something which didn't make sense
In Java if I am looking to instantiate a new Gregorgian Date Object I would use:
GregorianCalendar gc= new GregorianCalendar (2010,1,14);
but if I am looking to use the Data Format object I would use:
DateFormat df = DateFormat.getDateInstance();
I would really like to understand why dateformat doesn't follow the first way of instantiating the class?
How would I know to lookout in future for a similar gotcha?
You should always consult the API documentation to see how you are to use it.
A new X() always create a new object so if you have multiple places you need it, you end up with multiple X'es which may be inefficient if a single X would do.
The .getDateInstance() call is a Factory that allow the API to decide by itself whether to return the same X even to multiple callers or a new one to each. For very expensive but reusable/sharable objects this is the typical way you get them.
The Calendar API was donated to Java a very long time ago and is not as well designed as could be. These days the typical response to "I have problem X with Calendar and/or java.util.Date" in java is to use the Joda library which is well designed. For new code using Java 8 or later, use the new java.time classes as commented by Basil Bourque.
The short answer is that the core Java API is poorly designed and inconsistent. There's often no good reason for these inconsistencies, you just need to live with them.
More generally, factory methods like DateFormat.getDateInstance() allow the API to select different implementation classes depending on the situation, whereas using a constructor directly means there's no such flexibility.
Incidentally, unless you specifically want a GregorianCalendar, then the recommended method for obtaining one is Calendar.getInstance(), which will return you a GregorianCalendar if your locale is appropriate. Other locales will return different Calendar implementations. This would be consistent with your DateFormat example.
this is because it's an abstract class more info on that can be found here: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
same, look if a class is abstract or not.
The Answer by Thorbjørn Ravn Andersen is correct. Here are some more thoughts.
Avoid legacy date-time classes
GregorianCalendar is one of the terrible date-time classes bundled with the earliest versions of Java, designed by people who did not understand date-time handling.
These classes were years ago supplanted by the modern java.time classes. The GregorianCalendar class is specifically replaced by ZonedDateTime.
Immutable classes
The java.time classes are designed to be immutable, making them thread-safe.
This means you never use new. Instead, call factory methods. Read about the naming conventions on such methods.
Let’s capture the current moment as seen through the wall-clock time used by the people of a particular region (a time zone). We call ZonedDateTime.now to capture the current moment. As you can see in the source code, the constructor of ZonedDateTime is marked private to prevent us from instantiating via new. Internally to that class, the factory method performs the new. You can see for yourself, searching that source code for new ZonedDateTime.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
By the way, if you must use a GregorianCalendar to interoperate with old code not yet updated to java.time, you can convert. See new conversion methods added to the old classes.
ZonedDateTime zdt = myGregCal.toZonedDateTime() ;
…and…
GregorianCalendar myGregCal = GregorianCalendar.from( zdt ) ;