Calendar dates are not equal - java

I am having problem with java Calendar dates.
Bassically I have a list of holidays and want to check if a date belong
to the list. Still confused about how the Calendar class
is creating and formating its dates.
Please see the folowing code sample:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class CompareCalendarDates {
public static void main(String args[]) {
Date date1 = null;
try {
date1= new SimpleDateFormat("yyyy-MM-dd").parse("2019-12-25");
} catch (ParseException e) {
date1 = null;
}
Calendar calendar1 = Calendar.getInstance();
calendar1.clear();
calendar1.setTime(date1);
Calendar calendar2 = Calendar.getInstance();
calendar2.clear();
calendar2.setLenient(false); // Don't automatically convert invalid date.
calendar2.set(2019, 11, 25, 0, 0, 0);
calendar2.getTimeInMillis();
boolean isEqual = calendar1.equals(calendar2);
System.out.println ("Are to dates equal: " + isEqual);
}
}
I'm creating in 2 dates using different methods from Calendar class.
In my opinion the dates should be equal but there are not.
What am I missing? What is the difference between the methods
setTime () and set ?

You should use
boolean isEqual = calendar1.getTime().equals(calendar2.getTime());
Instead of
boolean isEqual = calendar1.equals(calendar2);
because the equals() method in Calendar class looks like these:
public boolean equals(Object obj) {
return obj instanceof Date && getTime() == ((Date) obj).getTime();
}
So it checks if the dates in these two calendars are the same objects, and in your case they are not the same objects, they jut have the same value.

tl;dr
LocalDate
.parse( "2019-12-25" )
.isEqual(
LocalDate.of( 2019 , Month.DECEMBER , 25 )
)
true
Details
Never use Date/Calendar. Use only java.time classes.
LocalDate::isEqual
For a date-only value without time-of-day and without time zone, use LocalDate.
LocalDate ld = LocalDate.parse( "2019-12-25" ) ;
LocalDate other = LocalDate.of( 2019, 11, 25 ) ;
Compare using isEqual, isBefore, isAfter.
boolean sameDates = ld.isEqual( other ) ;
This has been addressed many many times already on Stack Overflow. So I am keeping this Answer brief. Search to learn more.
December versus November
Unlike those legacy classes, the java.time classes use sane numbering. Months are counted 1-12 for January-December.
So notice that your pair of inputs differ, one for December, and one for November.
For clarity, you can use Month enum rather than an integer. Another benefit of enums is to ensure valid values.
LocalDate other = LocalDate.of( 2019 , Month.NOVEMBER , 25 ) ;

java.time
If you have got a Calendar object from a legacy API that you cannot afford to upgrade to java.time, the modern Java date and time API, just now, and you want to know whether it denotes the same date as some string, convert both to LocalDate and compare using the isEqual method:
String date1Str = "2019-12-25";
Calendar calendar2 = new GregorianCalendar(2019, Calendar.DECEMBER, 25);
LocalDate date1 = LocalDate.parse(date1Str);
LocalDate date2 = ((GregorianCalendar) calendar2).toZonedDateTime().toLocalDate();
boolean isEqual = date1.isEqual(date2);
System.out.println ("Are to dates equal: " + isEqual);
Output:
Are to dates equal: true
A LocalDate is a date without time of day, time zone, and all the other things that an old-fashioned Calendar object carries with it. So comparing two LocalDate will give you the result that you had expected.
What went wrong in your code?
While your two Calendar objects do denote the same point in time and also the same calendar date (which is not the same thing to ask), there are some differences, for example:
calendar1 has got all its fields set while calendar2 has got some uncomputed fields including for example era, week of year, AM/PM, millisecond of second and zone offset.
calendar1 is lenient, calendar2 is not.
I believe that this is more than enough that the objects are not considered equal. I haven’t checked the documentation for the exact criteria. You may do that out of curiosity, but I suggest that you don’t need to because you are not going to need to compare two Calendar objects for equality.
To answer your question, it seems that setTime() sets all fields while set obviuosly only sets some. I was surprised to see that getTimeInMillis() didn’t calculate the rest, but it doesn’t.
Link
Oracle tutorial: Date Time explaining how to use java.time.

Related

I want to get last date of the month and add n months to it but calendar instance is taking only 30 days in Java

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar calender = Calendar.getInstance();
calender.set(Calendar.DAY_OF_MONTH, calender.getActualMaximum(Calendar.DATE));
int months = 1;
calender.add(Calendar.MONTH, months );
String time = sdf .format(calender .getTime());
System.out.println(time);
Since current month is April and last date is 2020-04-30
Next month last date I should get 2020-05-31
but I am getting last date as 2020-05-30
Any thing am i doing wrong ?
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work. It’s much nicer to work with than the old classes Calendar and SimpleDateFormat.
LocalDate endOfNextMonth =
YearMonth // Represent an entire month in a particular year.
.now(ZoneId.of("Europe/Volgograd")) // Capture the current year-month as seen in a particular time zone. Returns a `YearMonth` object.
.plusMonths(1) // Move to the next month. Returns another `YearMonth` object.
.atEndOfMonth(); // Determine the last day of that year-month. Returns a `LocalDate` object.
String time = endOfNextMonth.toString(); // Represent the content of the `LocalDate` object by generating text in standard ISO 8601 format.
System.out.println("Last day of next month: " + time);
Output when running today:
Last day of next month: 2020-05-31
A YearMonth, as the name maybe says, is a year and month without day of month. It has an atEndOfMonth method that conveniently gives us the last day of the month as a LocalDate. A LocalDate is a date without time of day, so what we need here. And its toString method conveniently gives the format that you wanted (it’s ISO 8601).
Depending on the reason why you want the last day of another month there are a couple of other approaches you may consider. If you need to handle date ranges that always start and end on month boundaries, you may either:
Represent your range as a range of YearMonth objects. Would this free you from knowing the last day of the month altogether?
Represent the end of your range as the first of the following month exclusive. Doing math on the 1st of each month is simpler since it is always day 1 regardless of the length of the month.
What went wrong in your code?
No matter if using Calendar, LocalDate or some other class you need to do things in the opposite order: first add one month, then find the end of the month. As you know, months have different lengths, so the important part is getting the end of that month where you want to get the last day. Putting it the other way: setting either a LocalDate or a Calendar to the last day of the month correctly sets it to the last day of the month in qustion but does not instruct it to stay at the last day of the month after subsequent changes to its value, such as adding a month. If you add a month to April 29, you get May 29. If you add a month to April 30, you get May 30. Here it doesn’t matter that 30 is the last day of April while 30 is not the last day of May.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
You'd better use LocalDate like this:
LocalDate now = LocalDate.now();
LocalDate lastDay = now.withDayOfMonth(now.lengthOfMonth());
LocalDate nextMonth = lastDay.plusMonths(1);
Don't use deprecated classes from java.util.*.
Use classes from java.time.*.
Example with LocalDate :
public class Testing {
public static void main(String args[]) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.now();
int months = 1;
date = date.plusMonths(months);
date = date.withDayOfMonth(date.lengthOfMonth());
System.out.println(date.format(dateTimeFormatter));
}
}
Output :
2020-05-31
Example with Calendar :
public class Testing {
public static void main(String args[]) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar calender = Calendar.getInstance();
int months = 1;
calender.add(Calendar.MONTH, months);
calender.set(Calendar.DAY_OF_MONTH, calender.getActualMaximum(Calendar.DAY_OF_MONTH));
String time = sdf.format(calender.getTime());
System.out.println(time);
}
}
Output :
2020-05-31

How can I add validation onto a Date that rolls into another year using Java Date class

I'm currently trying to improve an aspect of a project of mine.
Users are allowed to do a specific task, but they must book a date in order to do it.
I'm trying to add some more realistic validation onto my date, so that the tasks can't be booked a year in advance, and only a few months.
Currently I'm only checking the year of the input and comparing it to the current year, so if they try to assign themselves a task on 31st of December, they will not be able to because any date they enter will roll over to the next year, and my validation prevents this.
How can I make it so it will check the amount of months, rather than the current year?
I am able to do this for the current year, I just get stuck when the year comes to december and the months roll into January again.
Edit:
Those looking for a way to fix this, go here: Calculating the difference between two Java date instances
Because the lengths of months are different, I would test the number of days. Here's a couple of utility methods that get the job done in one line:
// Tests if the end date is within so many days of the start date
public static boolean isWithinRange(int days, Date end, Date start) {
return TimeUnit.DAYS.convert(end.getTime() - start.getTime(), TimeUnit.MILLISECONDS) < days;
}
// Tests if the specified date is within so many days of today
public static boolean isWithinRange(int days, Date end) {
return isWithinRange(days, end, new Date());
}
Here I've used the TimeUnit class to do the calculation for me.
you can use your own method. Something like this
public boolean isLaterDay(Date date, Date reference) {
if (date.getYear () > reference.getYear ()) return true;
if (date.getYear () < reference.getYear ()) return false;
return (date.getMonth() > reference.getMonth());
}
Another way of doing this would be as follows.
boolean validDate(Calendar inputDate)
{
Calendar validationDate = Calendar.getInstance().add(Calendar.MONTH, numOfMonths);
return inputDate.before(validationDate);
}
You can do something like this to validate the time
private static final int MAX_MONTHS_IN_ADVANCE = 3;
public boolean isValidDate(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MONTH, MAX_MONTHS_IN_ADVANCE);
return date.before(calendar.getTime());
}
Using the Joda-Time library:
If ( dateTimeInQuestion.isBefore( DateTime.now().plusMonths(3) )
java.time
The modern way to do this work is with the java.time classes. These classes supplant the troublesome old legacy date-time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
ZoneId z = ZoneId.of( “America/Montreal” );
LocalDate today = LocalDate.now( z );
Construct the date desired by the user.
LocalDate ld = LocalDate.of( 2016 , 12 , 31 );
Determine the boundaries, say six months ago and six months from now.
LocalDate past = today.minusMonths( 6 );
LocalDate future = today.plusMonths( 6 );
You can compare LocalDate objects with isBefore, isAfter, equals, and compareTo.
Let's test by asking if the user's date is equal to or later than the before boundary (in other words, not before) AND the user's date is before the future boundary. This comparison uses the Half-Open approach commonly used with date-time work. The beginning is inclusive while the ending is exclusive.
Boolean validDate = ( ( ! ld.isBefore( past) ) && ( ld.isBefore( future) ) );
Interval
If you often work with the spans of time, consider using the Interval class found in the ThreeTen-Extra project that adds onto the java.time classes. That class has handy methods such as contains, abuts, overlaps, and more.

Comparing dates with JUnit testing

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.
Overriding default equals method is not necessary. You simply use Date.compareTo() to compare two date objects.
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);
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.
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.
Example Code in Joda-Time 2.3
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
Convert
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.
You need to override both equals() and toString(). If you override equals, always override hashcode() so that your maps work properly.
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")
java.time.LocalDate
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 this was for an exercise
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.
Tutorial link
Oracle tutorial: Date Time explaining how to use java.time.

Comparing only the time component of Date

Consider the following code to only determine if the time component of one Date object is before the time component of another Date object:
private boolean validStartStopTime( Date start, Date stop ) {
Calendar startCal = Calendar.getInstance();
Calendar stopCal = Calendar.getInstance();
startCal.clear();
stopCal.clear();
startCal.setTime( start );
stopCal.setTime( stop );
startCal.set( Calendar.YEAR, 2011 );
stopCal.set( Calendar.YEAR, 2011 );
startCal.set( Calendar.MONTH, 1 );
stopCal.set( Calendar.MONTH, 1 );
startCal.set( Calendar.DAY_OF_YEAR, 1 );
stopCal.set( Calendar.DAY_OF_YEAR, 1 );
return startCal.before( stopCal );
}
Would this insure that time comparison is correct? Is there a better alternative (Joda is not an option)? I believe that this is equivalent to setting the Calendar objects to current date/time and manually copying over the hour, minutes, and milliseconds component. You can assume that timezone are the same.
EDIT: To clarify what I mean by comparing only the time component of a Date object. I mean that when looking specifically at the time portion, the start time is before the stop time. The date portion is ABSOLUTELY irrelevant (in that start="Jan 2 20011 10AM" and end="Jan 1 2011 11AM" is perfectly fine), if I had a choice I'd simply use something that contained just the time but a Date object is what I'm given. I'd like to not write a sequence of if-else which is why I have the approach above but I welcome a cleaner/better approach.
Your code should work fine. You could also format just the time components in a zero-based string notation and compare them lexicographically:
public static boolean timeIsBefore(Date d1, Date d2) {
DateFormat f = new SimpleDateFormat("HH:mm:ss.SSS");
return f.format(d1).compareTo(f.format(d2)) < 0;
}
[Edit]
This is assuming that the dates have the same timezone offset. If not you'll have to adjust them manually beforehand (or as part of this function).
There are 86,400,000 milliseconds in a day, why not just use that to figure it out?
You could just mod timeInMilliseconds with that number and compare the results.

How to compare two Dates without the time portion?

I would like to have a compareTo method that ignores the time portion of a java.util.Date. I guess there are a number of ways to solve this. What's the simplest way?
Update: while Joda Time was a fine recommendation at the time, use the java.time library from Java 8+ instead where possible.
My preference is to use Joda Time which makes this incredibly easy:
DateTime first = ...;
DateTime second = ...;
LocalDate firstDate = first.toLocalDate();
LocalDate secondDate = second.toLocalDate();
return firstDate.compareTo(secondDate);
EDIT: As noted in comments, if you use DateTimeComparator.getDateOnlyInstance() it's even simpler :)
// TODO: consider extracting the comparator to a field.
return DateTimeComparator.getDateOnlyInstance().compare(first, second);
("Use Joda Time" is the basis of almost all SO questions which ask about java.util.Date or java.util.Calendar. It's a thoroughly superior API. If you're doing anything significant with dates/times, you should really use it if you possibly can.)
If you're absolutely forced to use the built in API, you should create an instance of Calendar with the appropriate date and using the appropriate time zone. You could then set each field in each calendar out of hour, minute, second and millisecond to 0, and compare the resulting times. Definitely icky compared with the Joda solution though :)
The time zone part is important: java.util.Date is always based on UTC. In most cases where I've been interested in a date, that's been a date in a specific time zone. That on its own will force you to use Calendar or Joda Time (unless you want to account for the time zone yourself, which I don't recommend.)
Quick reference for android developers
//Add joda library dependency to your build.gradle file
dependencies {
...
implementation 'joda-time:joda-time:2.9.9'
}
Sample code (example)
DateTimeComparator dateTimeComparator = DateTimeComparator.getDateOnlyInstance();
Date myDateOne = ...;
Date myDateTwo = ...;
int retVal = dateTimeComparator.compare(myDateOne, myDateTwo);
if(retVal == 0)
//both dates are equal
else if(retVal < 0)
//myDateOne is before myDateTwo
else if(retVal > 0)
//myDateOne is after myDateTwo
Apache commons-lang is almost ubiquitous. So what about this?
if (DateUtils.isSameDay(date1, date2)) {
// it's same
} else if (date1.before(date2)) {
// it's before
} else {
// it's after
}
If you really want to use the java.util.Date, you would do something like this:
public class TimeIgnoringComparator implements Comparator<Date> {
public int compare(Date d1, Date d2) {
if (d1.getYear() != d2.getYear())
return d1.getYear() - d2.getYear();
if (d1.getMonth() != d2.getMonth())
return d1.getMonth() - d2.getMonth();
return d1.getDate() - d2.getDate();
}
}
or, using a Calendar instead (preferred, since getYear() and such are deprecated)
public class TimeIgnoringComparator implements Comparator<Calendar> {
public int compare(Calendar c1, Calendar c2) {
if (c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR))
return c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
if (c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH))
return c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
return c1.get(Calendar.DAY_OF_MONTH) - c2.get(Calendar.DAY_OF_MONTH);
}
}
My preference would be to use the Joda library insetad of java.util.Date directly, as Joda makes a distinction between date and time (see YearMonthDay and DateTime classes).
However, if you do wish to use java.util.Date I would suggest writing a utility method; e.g.
public static Date setTimeToMidnight(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime( date );
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
Any opinions on this alternative?
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
sdf.format(date1).equals(sdf.format(date2));
If you want to compare only the month, day and year of two dates, following code works for me:
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
sdf.format(date1).equals(sdf.format(date2));
Thanks Rob.
tl;dr
myJavaUtilDate1.toInstant()
.atZone( ZoneId.of( "America/Montreal" ) )
.toLocalDate()
.isEqual (
myJavaUtilDate2.toInstant()
.atZone( ZoneId.of( "America/Montreal" ) )
.toLocalDate()
)
Avoid legacy date-time classes
Avoid the troublesome old legacy date-time classes such as Date & Calendar, now supplanted by the java.time classes.
Using java.time
A java.util.Date represents a moment on the timeline in UTC. The equivalent in java.time is Instant. You may convert using new methods added to the legacy class.
Instant instant1 = myJavaUtilDate1.toInstant();
Instant instant2 = myJavaUtilDate2.toInstant();
You want to compare by date. A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
Apply the ZoneId to the Instant to get a ZonedDateTime.
ZonedDateTime zdt1 = instant1.atZone( z );
ZonedDateTime zdt2 = instant2.atZone( z );
The LocalDate class represents a date-only value without time-of-day and without time zone. We can extract a LocalDate from a ZonedDateTime, effectively eliminating the time-of-day portion.
LocalDate localDate1 = zdt1.toLocalDate();
LocalDate localDate2 = zdt2.toLocalDate();
Now compare, using methods such as isEqual, isBefore, and isAfter.
Boolean sameDate = localDate1.isEqual( localDate2 );
See this code run live at IdeOne.com.
instant1: 2017-03-25T04:13:10.971Z | instant2: 2017-03-24T22:13:10.972Z
zdt1: 2017-03-25T00:13:10.971-04:00[America/Montreal] | zdt2: 2017-03-24T18:13:10.972-04:00[America/Montreal]
localDate1: 2017-03-25 | localDate2: 2017-03-24
sameDate: false
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.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I too prefer Joda Time, but here's an alternative:
long oneDay = 24 * 60 * 60 * 1000
long d1 = first.getTime() / oneDay
long d2 = second.getTime() / oneDay
d1 == d2
EDIT
I put the UTC thingy below in case you need to compare dates for a specific timezone other than UTC. If you do have such a need, though, then I really advise going for Joda.
long oneDay = 24 * 60 * 60 * 1000
long hoursFromUTC = -4 * 60 * 60 * 1000 // EST with Daylight Time Savings
long d1 = (first.getTime() + hoursFromUTC) / oneDay
long d2 = (second.getTime() + hoursFromUTC) / oneDay
d1 == d2
Already mentioned apache commons-utils:
org.apache.commons.lang.time.DateUtils.truncate(date, Calendar.DAY_OF_MONTH)
gives you Date object containing only date, without time, and you can compare it with Date.compareTo
If you're using Java 8, you should use the java.time.* classes to compare dates - it's preferred to the various java.util.* classes
eg; https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html
LocalDate date1 = LocalDate.of(2016, 2, 14);
LocalDate date2 = LocalDate.of(2015, 5, 23);
date1.isAfter(date2);
I am afraid there is no method of comparing two dates that could be called "easy" or "simple".
When comparing two time instances with any sort of reduced precision (e.g. just comparing dates), you must always take into account how time zone affects the comparison.
If date1 is specifying an event that occurred in +2 timezone and date2 is specifying an event that occurred in EST, for example, you must take care to properly understand the implications of the comparison.
Is your purpose to figure out if the two events occurred in the same calendar date in their own respective time zones? Or do You need to know if the two dates fall into the same calendar date in a specific time zone (UTC or your local TZ, for example).
Once you figure out what it is actually that You are trying to compare, it is just a matter of getting the year-month-date triple in an appropriate time zone and do the comparison.
Joda time might make the actual comparison operation look much cleaner, but the semantics of the comparison are still something You need to figure out yourself.
Simply Check DAY_OF_YEAR in combination with YEAR property
boolean isSameDay =
firstCal.get(Calendar.YEAR) == secondCal.get(Calendar.YEAR) &&
firstCal.get(Calendar.DAY_OF_YEAR) == secondCal.get(Calendar.DAY_OF_YEAR)
EDIT:
Now we can use the power of Kotlin extension functions
fun Calendar.isSameDay(second: Calendar): Boolean {
return this[Calendar.YEAR] == second[Calendar.YEAR] && this[Calendar.DAY_OF_YEAR] == second[Calendar.DAY_OF_YEAR]
}
fun Calendar.compareDatesOnly(other: Calendar): Int {
return when {
isSameDay(other) -> 0
before(other) -> -1
else -> 1
}
}
If you just want to compare only two dates without time, then following code might help you:
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
Date dLastUpdateDate = dateFormat.parse(20111116);
Date dCurrentDate = dateFormat.parse(dateFormat.format(new Date()));
if (dCurrentDate.after(dLastUpdateDate))
{
add your logic
}
I don't know it is new think or else, but i show you as i done
SimpleDateFormat dtf = new SimpleDateFormat("dd/MM/yyyy");
Date td_date = new Date();
String first_date = dtf.format(td_date); //First seted in String
String second_date = "30/11/2020"; //Second date you can set hear in String
String result = (first_date.equals(second_date)) ? "Yes, Its Equals":"No, It is not Equals";
System.out.println(result);
Here is a solution from this blog: http://brigitzblog.blogspot.com/2011/10/java-compare-dates.html
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.println("Time in days: " + diffDays + " days.");
i.e. you can see if the time difference in milliseconds is less than the length of one day.
`
SimpleDateFormat sdf= new SimpleDateFormat("MM/dd/yyyy")
Date date1=sdf.parse("03/25/2015");
Date currentDate= sdf.parse(sdf.format(new Date()));
return date1.compareTo(currentDate);
`
Using http://mvnrepository.com/artifact/commons-lang/commons-lang
Date date1 = new Date();
Date date2 = new Date();
if (DateUtils.truncatedCompareTo(date1, date2, Calendar.DAY_OF_MONTH) == 0)
// TRUE
else
// FALSE
In Java 8 you can use LocalDate which is very similar to the one from Joda Time.
public Date saveDateWithoutTime(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime( date );
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
This will help you to compare dates without considering the time.
Using the getDateInstance of SimpleDateFormat, we can compare only two date object without time. Execute the below code.
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date();
DateFormat dfg = SimpleDateFormat.getDateInstance(DateFormat.DATE_FIELD);
String dateDtr1 = dfg.format(date1);
String dateDtr2 = dfg.format(date2);
System.out.println(dateDtr1+" : "+dateDtr2);
System.out.println(dateDtr1.equals(dateDtr2));
}
Another Simple compare method based on the answers here and my mentor guidance
public static int compare(Date d1, Date d2) {
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.setTime(d1);
c1.set(Calendar.MILLISECOND, 0);
c1.set(Calendar.SECOND, 0);
c1.set(Calendar.MINUTE, 0);
c1.set(Calendar.HOUR_OF_DAY, 0);
c2.setTime(d2);
c2.set(Calendar.MILLISECOND, 0);
c2.set(Calendar.SECOND, 0);
c2.set(Calendar.MINUTE, 0);
c2.set(Calendar.HOUR_OF_DAY, 0);
return c1.getTime().compareTo(c2.getTime());
}
EDIT:
According to #Jonathan Drapeau, the code above fail some cases (I would like to see those cases, please) and he suggested the following as I understand:
public static int compare2(Date d1, Date d2) {
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.clear();
c2.clear();
c1.set(Calendar.YEAR, d1.getYear());
c1.set(Calendar.MONTH, d1.getMonth());
c1.set(Calendar.DAY_OF_MONTH, d1.getDay());
c2.set(Calendar.YEAR, d2.getYear());
c2.set(Calendar.MONTH, d2.getMonth());
c2.set(Calendar.DAY_OF_MONTH, d2.getDay());
return c1.getTime().compareTo(c2.getTime());
}
Please notice that, the Date class is deprecated cause it was not amenable to internationalization. The Calendar class is used instead!
First, be aware that this operation depends on the time zone. So choose whether you want to do it in UTC, in the computer’s time zone, in your own favourite time zone or where. If you are not yet convinced it matters, see my example at the bottom of this answer.
Since your question isn’t quite clear about this, I am assuming that you have a class with an instance field representing a point in time and implementing Comparable, and you want the natural ordering of your objects to be by the date, but not the time, of that field. For example:
public class ArnesClass implements Comparable<ArnesClass> {
private static final ZoneId arnesTimeZone = ZoneId.systemDefault();
private Instant when;
#Override
public int compareTo(ArnesClass o) {
// question is what to put here
}
}
Java 8 java.time classes
I have taken the freedom of changing the type of your instance field from Date to Instant, the corresponding class in Java 8. I promise to return to the treatment of Date below. I have also added a time zone constant. You may set it to ZoneOffset.UTC or ZoneId.of("Europe/Stockholm") or what you find appropriate (setting it to a ZoneOffset works because ZoneOffset is a subclass of ZoneId).
I have chosen to show the solution using the Java 8 classes. You asked for the simplest way, right? :-) Here’s the compareTo method you asked for:
public int compareTo(ArnesClass o) {
LocalDate dateWithoutTime = when.atZone(arnesTimeZone).toLocalDate();
LocalDate otherDateWithoutTime = o.when.atZone(arnesTimeZone).toLocalDate();
return dateWithoutTime.compareTo(otherDateWithoutTime);
}
If you never need the time part of when, it is of course easier to declare when a LocalDate and skip all conversions. Then we don’t have to worry about the time zone anymore either.
Now suppose that for some reason you cannot declare your when field an Instant or you want to keep it an old-fashioned Date. If you can still use Java 8, just convert it to Instant, then do as before:
LocalDate dateWithoutTime = when.toInstant().atZone(arnesTimeZone).toLocalDate();
Similarly for o.when.
No Java 8?
If you cannot use java 8, there are two options:
Solve it using one of the old classes, either Calendar or SimpleDateFormat.
Use the backport of the Java 8 date and time classes to Java 6 and 7, then just do as above. I include a link at the bottom. Do not use JodaTime. JodaTime was probably a good suggestion when the answers recommending it were written; but JodaTime is now in maintenance mode, so the ThreeTen backport is a better and more futureproof option.
The old-fashioned ways
Adamski’s answer shows you how to strip the time part off a Date using the Calendar class. I suggest you use getInstance(TimeZone) to obtain the Calendar instance for the time zone you want. As an alternative you may use the idea from the second half of Jorn’s answer.
Using SimpleDateFormat is really an indirect way of using Calendar since a SimpleDateFormat contains a Calendar object. However, you may find it less troublesome than using Calendar directly:
private static final TimeZone arnesTimeZone = TimeZone.getTimeZone("Europe/Stockholm");
private static final DateFormat formatter = new SimpleDateFormat("yyyyMMdd");
static {
formatter.setTimeZone(arnesTimeZone);
}
private Date when;
#Override
public int compareTo(ArnesClass o) {
return formatter.format(when).compareTo(formatter.format(o.when));
}
This was inspired by Rob’s answer.
Time zone dependency
Why do we have to pick a specific time zone? Say that we want to compare two times that in UTC are March 24 0:00 (midnight) and 12:00 (noon). If you do that in CET (say, Europe/Paris), they are 1 am and 1 pm on March 24, that is, the same date. In New York (Eastern Daylight Time), they are 20:00 on March 23 and 8:00 on March 24, that is, not the same date. So it makes a difference which time zone you pick. If you just rely on the computer’s default, you may be in for surprises when someone tries to run your code on a computer in another place in this globalized world.
Link
Link to ThreeTen Backport, the backport of the Java 8 date and time classes to Java 6 and 7: http://www.threeten.org/threetenbp/.
My proposition:
Calendar cal = Calendar.getInstance();
cal.set(1999,10,01); // nov 1st, 1999
cal.set(Calendar.AM_PM,Calendar.AM);
cal.set(Calendar.HOUR,0);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MILLISECOND,0);
// date column in the Thought table is of type sql date
Thought thought = thoughtDao.getThought(date, language);
Assert.assertEquals(cal.getTime(), thought.getDate());
Using Apache commons you can do:
import org.apache.commons.lang3.time.DateUtils
DateUtils.truncatedEquals(first, second, Calendar.DAY_OF_MONTH)
public static Date getZeroTimeDate(Date fecha) {
Date res = fecha;
Calendar calendar = Calendar.getInstance();
calendar.setTime( fecha );
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
res = calendar.getTime();
return res;
}
Date currentDate = getZeroTimeDate(new Date());// get current date
this is the simplest way to solve this problem.
I solved this by comparing by timestamp:
Calendar last = Calendar.getInstance();
last.setTimeInMillis(firstTimeInMillis);
Calendar current = Calendar.getInstance();
if (last.get(Calendar.DAY_OF_MONTH) != current.get(Calendar.DAY_OF_MONTH)) {
//not the same day
}
I avoid to use Joda Time because on Android uses a huge space. Size matters. ;)
Another solution using Java 8 and Instant, is using the truncatedTo method
Returns a copy of this Instant truncated to the specified unit.
Example:
#Test
public void dateTruncate() throws InterruptedException {
Instant now = Instant.now();
Thread.sleep(1000*5);
Instant later = Instant.now();
assertThat(now, not(equalTo(later)));
assertThat(now.truncatedTo(ChronoUnit.DAYS), equalTo(later.truncatedTo(ChronoUnit.DAYS)));
}
// Create one day 00:00:00 calendar
int oneDayTimeStamp = 1523017440;
Calendar oneDayCal = Calendar.getInstance();
oneDayCal.setTimeInMillis(oneDayTimeStamp * 1000L);
oneDayCal.set(Calendar.HOUR_OF_DAY, 0);
oneDayCal.set(Calendar.MINUTE, 0);
oneDayCal.set(Calendar.SECOND, 0);
oneDayCal.set(Calendar.MILLISECOND, 0);
// Create current day 00:00:00 calendar
Calendar currentCal = Calendar.getInstance();
currentCal.set(Calendar.HOUR_OF_DAY, 0);
currentCal.set(Calendar.MINUTE, 0);
currentCal.set(Calendar.SECOND, 0);
currentCal.set(Calendar.MILLISECOND, 0);
if (oneDayCal.compareTo(currentCal) == 0) {
// Same day (excluding time)
}
If you strictly want to use Date ( java.util.Date ), or without any use of external Library. Use this :
public Boolean compareDateWithoutTime(Date d1, Date d2) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
return sdf.format(d1).equals(sdf.format(d2));
}
Date today = new Date();
Date endDate = new Date();//this
endDate.setTime(endDate.getTime() - ((endDate.getHours()*60*60*1000) + (endDate.getMinutes()*60*1000) + (endDate.getSeconds()*1000)));
today.setTime(today.getTime() - ((today.getHours()*60*60*1000) + (today.getMinutes()*60*1000) + (today.getSeconds()*1000)));
System.out.println(endDate.compareTo(today) <= 0);
I am simply setting hours/minutes/second to 0 so no issue with the time as time will be same now for both dates. now you simply use compareTo. This method helped to find "if dueDate is today" where true means Yes.

Categories