I'm trying to consolidate some code that is very messy but I want to make sure I don't break things. In some places I see a date created as Calendar.getInstance().getTime()
and in others it's just new Date()
. Will it break things if I convert them all to new Date()
or is there some reason I may want to use the other?
Java – Is Calendar.getInstance().getTime() Different from new Date()?
java
Related Solutions
System.currentTimeMillis()
is obviously the most efficient since it does not even create an object, but new Date()
is really just a thin wrapper about a long, so it is not far behind. Calendar
, on the other hand, is relatively slow and very complex, since it has to deal with the considerably complexity and all the oddities that are inherent to dates and times (leap years, daylight savings, timezones, etc.).
It's generally a good idea to deal only with long timestamps or Date
objects within your application, and only use Calendar
when you actually need to perform date/time calculations, or to format dates for displaying them to the user. If you have to do a lot of this, using Joda Time is probably a good idea, for the cleaner interface and better performance.
cal.getTime()
does indeed need to be called to re-calculate its internals. It is very strange behavior for the API but the Calendar javadocs state this explicitly:
Getting and Setting Calendar Field Values
The calendar field values can be set by calling the set methods. Any field values set in a Calendar will not be interpreted until it needs to calculate its time value (milliseconds from the Epoch) or values of the calendar fields. Calling the get, getTimeInMillis, getTime, add and roll involves such calculation.
...
Field Manipulation
The calendar fields can be changed using three methods: set(), add(), and roll(). set(f, value) changes calendar field f to value. In addition, it sets an internal member variable to indicate that calendar field f has been changed. Although calendar field f is changed immediately, the calendar's time value in milliseconds is not recomputed until the next call to get(), getTime(), getTimeInMillis(), add(), or roll() is made. Thus, multiple calls to set() do not trigger multiple, unnecessary computations. As a result of changing a calendar field using set(), other calendar fields may also change, depending on the calendar field, the calendar field value, and the calendar system. In addition, get(f) will not necessarily return value set by the call to the set method after the calendar fields have been recomputed. The specifics are determined by the concrete calendar class.
The behavior is unexpected and does not always occur but the following unit tests should exemplify this behavior and always occur.
/**
* Fails the assertion due to missing getTime()
* @throws ParseException
*/
public class DateTest {
@Test
public void testNoGetTime() throws ParseException {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
Date testDate = df.parse("04/15/2013");
Calendar testCal = Calendar.getInstance();
testCal.setTime(testDate);
Date expectedDate = df.parse("04/04/2013");
Date actualDate = null;
testCal.set(Calendar.DAY_OF_MONTH, testCal.getMinimum(Calendar.DAY_OF_MONTH));
//testCal.getTime();
testCal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
testCal.add(Calendar.DAY_OF_MONTH, -1);
actualDate = testCal.getTime();
assertEquals("Dates should be equal", expectedDate.toString(), actualDate.toString());
}
@Test
public void testWithGetTime() throws ParseException {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
Date testDate = df.parse("04/15/2013");
Calendar testCal = Calendar.getInstance();
testCal.setTime(testDate);
Date expectedDate = df.parse("04/04/2013");
Date actualDate = null;
testCal.set(Calendar.DAY_OF_MONTH, testCal.getMinimum(Calendar.DAY_OF_MONTH));
testCal.getTime();
testCal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
testCal.add(Calendar.DAY_OF_MONTH, -1);
actualDate = testCal.getTime();
assertEquals("Dates should be equal", expectedDate.toString(), actualDate.toString());
}
}
Best Answer
In theory, no, because both java.util.Date and java.util.Calendar.getInstance() eventually use System.currentTimeMillis() to return the current time.
The Calendar implementation, however, takes other things into consideration, like the Locale, or if the locale is JP or TH... you can see that in the source code of both classes.