Reputation: 233
Hello I'm new to the site and have a issue with my application using JUnit testing. My issue is when I try to compare the Date method with itself it always fails. I printed the Date object in the test to see the problem and always end up with the package name and random letters. Here is the Date constructor:
public class Date
{
SimpleDateFormat dformat = new SimpleDateFormat("dd-MM-yyyy");
private int day;
private int month;
private int year;
public Date()
{
String today;
Calendar present = Calendar.getInstance();
day = present.get(Calendar.DAY_OF_MONTH);
month = present.get(Calendar.MONTH);
year = present.get(Calendar.YEAR);
present.setLenient(false);
present.set(year, month - 1, day, 0, 0);
today = dformat.format(present.getTime());
System.out.println(today);
}
Here is my test:
@Test
public void currentDay()
{
Date current = new Date();
System.out.println(current);
assertEquals("today:", current, new Date());
}
Yet the result always fails and I get something on the lines of:
comp.work.wk.Date@d3ade7
Any help would be appreciated.
Upvotes: 22
Views: 70428
Reputation: 15052
You need to override both equals() and toString(). If you override equals, always override hashcode() so that your maps work properly.
Upvotes: 1
Reputation: 86296
For production code never create your own Date
class (as an exercise it’s fine). Use LocalDate
from java.time, the modern Java date and time API.
For example:
ZoneId zone = ZoneId.of("Africa/Niamey");
LocalDate current = LocalDate.now(zone);
System.out.println(current);
System.out.println("Is equal? " + current.isEqual(LocalDate.now(zone)));
Output when I ran this code just now:
2021-04-07 Is equal? true
If the code happens to run just over midnight so now()
is called just before and just after the day changes, then you will get two different dates, and the second line will be Is equal? false
.
Since it is never the same date in all time zones, specifying the desired time zone is crucial.
If you are doing an exercise requiring you to write your own date class, then it’s a fine exercise. In this case the answers stating that in your date class you should override equals()
, hashCode()
and toString()
are the correct ones.
In your own date class you should not base its functionality on Calendar
nor SimpleDateformat
. Calendar
is poorly designed, SimpleDateFormat
is notoriously troublesome, and both are long outdated. Instead use LocalDate
and DateTimeFormatter
from java.time.
Oracle tutorial: Date Time explaining how to use java.time.
Upvotes: 0
Reputation: 4172
I have this solution to test date order
// date1 has to be before date2
if( !date1.before(date2) ) Assert.fail("Date1 is not before date2");
// date1 has to be before or equals to date2
if( date1.after() ) Asssert.fail("Date1 is after date2")
Upvotes: 0
Reputation: 338835
Update The Joda-Time project is now in maintenance mode, with the team recommending migration to the java.time classes.
This kind of work is much easier with the Joda-Time library instead of the notoriously troublesome Date/Calendar classes.
Set up some data…
DateTime now = new DateTime();
DateTime yesterday = now.minusDays( 1 );
DateTime nowAgain = new DateTime( now.toString() ); // New object, but same value inside.
Compare…
boolean isNowEqualToYesterday = now.equals( yesterday );
boolean isNowEqualToNowAgain = now.equals( nowAgain );
Dump to console…
System.out.println( "now: " + now );
System.out.println( "yesterday: " + yesterday );
System.out.println( "nowAgain: " + nowAgain );
System.out.println( "isNowEqualToYesterday: " + isNowEqualToYesterday );
System.out.println( "isNowEqualToNowAgain: " + isNowEqualToNowAgain );
When run…
now: 2014-02-06T01:31:43.157-08:00
yesterday: 2014-02-05T01:31:43.157-08:00
nowAgain: 2014-02-06T01:31:43.157-08:00
isNowEqualToYesterday: false
isNowEqualToNowAgain: true
You can convert in and out of Joda-Time if need be.
org.joda.time.DateTime dateTime = new DateTime( date ); // From Date to DateTime.
java.util.Date date = dateTime.toDate(); // From DateTime to Date.
Upvotes: 1
Reputation: 628
Although the answer by @Shrikanth solves it, this issue also arises with normal Date objects. Two possible solutions are given here:
Make use of DateUtils.truncate (or even DateUtils.truncatedEquals) to compare the dates. This is something you could use in your equals method, or for normal Date objects directly in you assertEquals/assertTrue.
assertEquals(DateUtils.truncate(date1,Calendar.SECOND),
DateUtils.truncate(date2,Calendar.SECOND));
Don't check whether the dates are the same, but whether they are close enough to eachother (for JUnit test sake):
assertTrue("Dates aren't close enough to each other!",
Math.abs(date2.getTime() - date1.getTime()) < 1000);
Upvotes: 14
Reputation: 423
Overriding default equals method is not necessary. You simply use Date.compareTo() to compare two date objects.
Upvotes: 14
Reputation: 1157
The default equals object compares memory locations. If both objects are pointing to same memory location then only it will print equals which is not the case in your program. since they are pointing to two different memory locations it is always giving false which is expected.
If you feel your assertEquals(date1,date2) method should return true since the contents are equal then you should override the equals method. And when ever you override equals you should override hashcode() method also to ensure that you can confidently use your class instance as a key in any hashing based collection like HashMap or HashSet.
Here is a link explaining how to override equals() and hashcode() method
http://javarevisited.blogspot.in/2011/02/how-to-write-equals-method-in-java.html
And don't name your class same as any API class as Jon Skeet suggested.
Hope this helps.
Upvotes: 7