Problem comparing dates with if statement - java

I've got a problem comparing.
The second "if" is always fulfilled even if the second condition of the "if" is false.
First, I had to use Timestamp.valueOf so I could transform LocalDateTime to Date ("a" is a type of data "Date"). What i want to do is compare if the current time is greater than a predetermined time (a.getFinFecha()), if so, return 1. If the current time is greater or equal to the predetermined time (a.getFinFecha()) less seven days and is lower than the pretermined date, I want to return 2. Else (which means if the current time is lower than a.getFinFecha() and lower than a.getFinFecha() less 7 days) return 3. The object I'm passing is lower than the pretermined date less 7 days and it returns 2. Never returns 3.
if (java.sql.Timestamp.valueOf(LocalDateTime.now()).compareTo(a.getFinFecha()) > 0) {
return 1;
} else if (java.sql.Timestamp.valueOf(LocalDateTime.now()).getDate() >= (a.getFinFecha().getDate() - 7) && java.sql.Timestamp.valueOf(LocalDateTime.now()).compareTo(a.getFinFecha()) <= 0) {
return 2;
} else {
return 3;
}

I had to use Timestamp.valueOf so I could transform LocalDateTime to Date
No, you hadn't and you shoudn't. Avoid using deprecated methods like getDate() and make use of the java.time API. The simplest solution could be to convert the Date returned by a.getFinFecha() to LocalDateTime and compare according to your requierments:
private int yourMethod() {
Instant instant = Instant.ofEpochMilli(a.getFinFecha().getTime());
LocalDateTime finFecha = LocalDateTime.ofInstant(instant, ZoneOffset.UTC); // or use appropriate offset for your use case
if (LocalDateTime.now().isAfter(finFecha)) {
return 1;
} else if (LocalDateTime.now().isAfter(finFecha.minusDays(7))) {
return 2;
} else {
return 3;
}
}

Related

Filter by date in Java with startDate and endDate [duplicate]

This question already has answers here:
Determine Whether Two Date Ranges Overlap
(39 answers)
Closed 2 years ago.
In database I have
eventName: "TestEvent",
startDate : ISODate("2018-11-07T13:24:03.124Z"),
endDate: ISODate("2020-11-07T13:24:03.124Z")
I am setting two dates fromDate and toDate,
for example
fromDate:01/01/2020
toDate:01/01/2021
I want to check if the event is within this range I entered.
I tried like this but the results are not correct.
if ((fromDate.after(s.getStartDate()) && toDate.before(s.getEndDate()))
|| s.getStartDate().equals(fromDate) || s.getEndDate().equals(toDate))
Please help me, I am using utils.Date in my project.
If i use :
fromDate:08/08/2017
toDate: 09/09/2022
or
fromDate:08/08/2019
toDate: 09/09/2019
it should return this event in this range.
If i use :
fromDate:01/01/2000
toDate: 01/01/2001
this event should not be in the results
You are trying to check whether two (time) intervals overlap. A simple way to look at it is to say that overlap occurs if (and only if) one or more of the start and end of the 1st interval is within the 2nd, or vice-versa. Test it with:
boolean contains(Date d, Date startInclusive, Date endExclusive) {
return d.compareTo(startInclusive) >= 0 && d.before(endExclusive);
}
yielding
boolean intersects(Date from, Date to, Date start, Date end) {
return contains(from, start, end) || // s <= f < e (from inside start-end)
contains(to, start, end) || // s <= t < e (to inside start-end)
contains(start, from, to); // f <= s < t (from-to fully contains start-end)
}
Note that this is much more readable than writing the (equivalent) boolean expression.
I also fully agree with #deHaar's comment: use classes in java.time instead of java.util.Date. There are many problems with java.util.Date, which is deprecated as of Java 8.
Make sure when you compare the dates they are in the same format.
I think there is an issue with condition and it should look more like :
Date startDate = s.getStartDate();
Date endDate = s.getEndDate();
if ((fromDate.before(startDate) || fromDate.equals(startDate)) &&
(toDate.after(endDate) || toDate.equals(endDate)){
// do you magic here
}

Check if the time is within the min and max range

I don't know what's happening here: I need to return true if the current time is between a given range, ex: now is 15:45:00 and is between 12:00:00(min) and 18:00:00(max), but this method is doing it wrong:
private boolean verifyIfInside(String max, String min){
try {
DateFormat dateFormat = new SimpleDateFormat ("HH:mm:ss");
Date date = new Date();
String hour1 = min;
String hour2 = max;
String newHour = dateFormat.format(date);
Date minHour, maxHour, nowHour;
minHour = dateFormat.parse(hora1);
maxHour = dateFormat.parse(hora2);
nowHour = dateFormat.parse(newHour );
if ((minHour.compareTo(nowHour) <= 0) && (maxHour.compareTo(nowHour) >= 0)){
return true;
} else {
return false;
}
} catch (ParseException parseException){
parseException.printStackTrace();
return false;
}
}
I have tested it with .before() and .after() Its working fine and you can also reduce the code like:-
private static boolean verifyIfInside(String min , String max){
try {
DateFormat dateFormat = new SimpleDateFormat ("HH:mm:ss");
String current_time = dateFormat.format(new Date());
Date minHour = dateFormat.parse(min);
Date maxHour = dateFormat.parse(max);
Date curr_time = dateFormat.parse(current_time);
return minHour.before(curr_time) && maxHour.after(curr_time);
} catch (ParseException parseException){
parseException.printStackTrace();
return false;
}
}
Time zone is crucial. Your verification makes no sense unless you know in which time zone you want the current time. For the reader’s sake, also specify it in your code.
The date and time classes you use, Date, DateFormat and SimpleDateFormat, are not only long outdated, the last one in particular is also renowned for being troublesome to work with. Instead I recommend you use java.time, the modern Java date and time API. This even furnishes a LocalTime class, a time of day without a date, which matches your need much more precisely than Date.
So your method is written clearly and tersely thus:
private static boolean verifyIfInside(String max, String min) {
LocalTime now = LocalTime.now(ZoneId.of("Europe/Budapest"));
LocalTime minHour = LocalTime.parse(min);
LocalTime maxHour = LocalTime.parse(max);
return ! (now.isBefore(minHour) || now.isAfter(maxHour));
}
Please substitute your desired time zone if it didn’t happen to be Europe/Budapest.
Since I understood that you wanted your range to be inclusive, and since isBefore and isAfter mean strictly before and after, I used a negation to test that the time is “not outside the range”.
I am furthermore exploiting the fact that your time format, 12:00:00, agrees with ISO 8601, the format that the modern classes parse as their default, that is, without any explicit formatter. A potential downside is that validation of the time strings is weaker: parse() will also accept 12:00 and 12:23:29.82376342. If you need to reject these as errors, you do need an explicit formatter.
What went wrong in your code?
As far as I can tell, your code in the question is working correctly (if we just change hora1 to hour1 or the other way around, and hora2 too). You may have been confused about the order of the arguments. The following returns true if run between 12 and 18: verifyIfInside("18:00:00", "12:00:00"). However, many would find it natural to write the call as verifyIfInside("12:00:00", "18:00:00"), which returns false always. So it would almost surely be better to declare the method as verifyIfInside(String min, String max), that is, with min before max.
Another possibility is, of course, as I mentioned, that your JVM is using a different time zone from the one you think it is using. This would very likely give you unexpected results. The only way to be sure this is not the case is to specify explicitly which time zone it should use.
It works correctly with the suggested modifications:
Reverse the min and max parameters.
Use .before() and .after() to compare if the current hour is after min hour and before max hour.
To include the min/max time boundaries you can use: !nowHour.after(maxHour) && !nowHour.before(minHour);
To exclude the min/max time boundaries use this instead: nowHour.after(minHour) && nowHour.before(maxHour);
If you are constrained to an older version of java, consider using the appropriate java.time ThreeTen-Backport project as #Basil Bourque suggested. Otherwise, use the latest time API in Java 8+.
code:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class scratch_21 {
public static void main(String[] args) {
System.out.println(verifyIfInside("14:00:00", "14:15:00"));
}
private static boolean verifyIfInside(String min, String max) {
try {
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
String hora1 = min;
String hora2 = max;
String newHour = dateFormat.format(date);
Date minHour, maxHour, nowHour;
minHour = dateFormat.parse(hora1);
maxHour = dateFormat.parse(hora2);
nowHour = dateFormat.parse(newHour);
return nowHour.after(minHour) && nowHour.before(maxHour);
} catch (ParseException parseException) {
parseException.printStackTrace();
return false;
}
}
}

Check if additional hour due to DST

In my application I must often check if given hour as ZonedDateTime is the additional hour due to DST. Consider the transition from Summer time to Winter time
1) *date* 01:00:00+02:00
2) *date* 02:00:00+02:00
3) *date* 02:00:00+01:00
4) *date* 03:00:00+01:00
I want to write the simplest possible function isExtraHour(ZonedDate time) that for 1,2,4 will return false and for 3 case will return true Of course using the Java8 Time API.
This is what I would use:
public boolean isExtraHour(final ZonedDateTime time) {
return time.getZone().getRules().getValidOffsets(time.toLocalDateTime()).size() > 1;
}
Note that it returns true for the whole hour of overlap, which I assume is the answer you need.
The easiest I got so far is:
public boolean isExtraHour(final ZonedDateTime time) {
final ZoneOffsetTransition dayTransition = time.getZone().getRules()
.getTransition(time.toLocalDateTime());
return dayTransition != null && dayTransition.isOverlap() && dayTransition.getInstant()
.equals(time.toInstant());
}

apache.commons.lang3.DateUtils.setMonths with December

I am facing very strange issue..
Here is the code, which generates a new Date object:
Date result = DateUtils.setYears(new Date(), year);
result = DateUtils.setMonths(result, month);
return DateUtils.setDays(result, day);
If I pass any value for month starting from 1 till 11 - everything works fine, 1 means January, 2 - February ... 11 - November. But with 12 it always fails with java.lang.IllegalArgumentException: MONTH exception..
When I try to pass 0-based values, the first one 0 means December of previous year..
Any ideas?
Thank you in advance
The method setMonths look like
public static Date setMonths(Date date, int amount) {
return set(date, Calendar.MONTH, amount);
}
As you can notice that internally it uses Calendar.MONTH from java. Months in Calendar class starts from 0 till 12(12 value mean UNDECIMBER i.e. thireteenth month of the year Although GregorianCalendar does not use this value, lunar calendars do). So when you are passing 0 it means January, 1 it means February,... and 11 means December. For invalid month value calendar class throw
java.lang.IllegalArgumentException
Let's trace it.
The setMonths method in DateUtils is defined as follows:
public static Date setMonths(Date date, int amount) {
return set(date, Calendar.MONTH, amount);
}
Let's check out the set method. This methods throws the same exception class but for a different reason.
private static Date set(Date date, int calendarField, int amount) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
// getInstance() returns a new object, so this method is thread safe.
Calendar c = Calendar.getInstance(); //returns an "empty" Calendar instance using default TimeZone and Local. Does not throw any exception
c.setLenient(false); // Just set the leniency value of the Calendar.
c.setTime(date); // set the time of the Calendar to the reference time by converting the date input into milliseconds
c.set(calendarField, amount); // this one looks interesting, but not quite
return c.getTime(); //returns the Date Object, possible source of the thrown Exception
}
The getTime method in Calendar.java looks like:
public final Date getTime() {
return new Date(getTimeInMillis());
}
The method getTimeInMillis in Calendar.java is defined as follows:
public long getTimeInMillis() {
if (!isTimeSet) {
updateTime();
}
return time;
}
The only statement in this method that looks interesting is updateTime which in turn is defined as follows:
private void updateTime() {
computeTime();
// The areFieldsSet and areAllFieldsSet values are no longer
// controlled here (as of 1.5).
isTimeSet = true;
}
The computeTime method in Calendar.java is an abstract method which for this case is concretely implemented in GregorianCalendar.java. I'll only show statements in the method that can throw that exception because the whole method is very long.
protected void computeTime() {
// In non-lenient mode, perform brief checking of calendar
// fields which have been set externally. Through this
// checking, the field values are stored in originalFields[]
// to see if any of them are normalized later.
if (!isLenient()) {
if (originalFields == null) {
originalFields = new int[FIELD_COUNT];
}
for (int field = 0; field < FIELD_COUNT; field++) {
int value = internalGet(field);
if (isExternallySet(field)) {
// Quick validation for any out of range values
**This is the part of the code that has thrown that Exception**
if (value < getMinimum(field) || value > getMaximum(field)) {
throw new IllegalArgumentException(getFieldName(field));
}
}
originalFields[field] = value;
}
//After this part, code that computes the time in milliseconds follows
.............................
.............................
}
As you can see, the value being supplied for a particular field is compared to the field's predefined minimum and maximum value. For the MONTH field, the minimum value is 0 (January) and the maximum value is 11 (December). You can verify these values from here.
Now as for your other question, the information you have provided is limited for us to provide a concrete answer. By the implementation of the Calendar API, if the leniency mode is set to false, the value 0 for the month should correspond to January and 11 to December. The only way for a 0 month value to correspond to December is when you set the leniency mode to true and you have a day value that "wraps around (roll over)" to December e.g. month = 0 but day = 369.
The best guess here as mentioned in one of the comments above is perhaps you are modifying the value of month somehow, somewhere.

Check if two date periods overlap [duplicate]

This question already has answers here:
Determine Whether Two Date Ranges Overlap
(39 answers)
Closed 8 years ago.
I have two date ranges, (start1,end1):::>>date1 && (start2,end2):::>>date2 .
I want to check if the two dates isOverLaped.
My flow chart I assume "<>=" operators is valid for comparing.
boolean isOverLaped(Date start1,Date end1,Date start2,Date end2) {
if (start1>=end2 && end2>=start2 && start2>=end2) {
return false;
} else {
return true;
}
}
Any Suggestion will be appreciated.
You can use Joda-Time for this.
It provides the class Interval which specifies a start and end instants and can check for overlaps with overlaps(Interval).
Something like
DateTime now = DateTime.now();
DateTime start1 = now;
DateTime end1 = now.plusMinutes(1);
DateTime start2 = now.plusSeconds(50);
DateTime end2 = now.plusMinutes(2);
Interval interval = new Interval( start1, end1 );
Interval interval2 = new Interval( start2, end2 );
System.out.println( interval.overlaps( interval2 ) );
prints
true
since the end of the first interval falls between the start and end of the second interval.
boolean overlap(Date start1, Date end1, Date start2, Date end2){
return start1.getTime() <= end2.getTime() && start2.getTime() <= end1.getTime();
}
//the inserted interval date is start with fromDate1 and end with toDate1
//the date you want to compare with start with fromDate2 and end with toDate2
if ((int)(toDate1 - fromDate2).TotalDays < 0 )
{ return true;}
else
{
Response.Write("<script>alert('there is an intersection between the inserted date interval and the one you want to compare with')</script>");
return false;
}
if ((int)(fromDate1 - toDate2).TotalDays > 0 )
{ return true;}
else
{
Response.Write("<script>alert('there is an intersection between the inserted date interval and the one you want to compare with')</script>");
return false;
}
You have two intervals, i1 and i2. There are six cases for how the intervals can be temporally related (at least in a Newtonian world view) but only two are important: if i1 is entirely before i2 or i1 is entirely after i2; otherwise the two intervals are overlapping (the other four cases are i1 contains i2, i2 contains i1, i1 contains the start of i2 and i1 contains the end of i2). Assume i1 and i2 are of type Interval that have Date fields beginTime and endTime. The function then is (note, the assumption here is that if i1 starts at the same time i2 ends, or vice versa, we don't consider that an overlap and we assme for a given interval endTime.before(beginTime) is false):
boolean isOverlapped(Interval i1, Interval i2) {
return i1.endTime.before(i2.beginTime) || i1.beginTime.after(i2.endTime);
}
In the original question, you specify DateTime instead of Date. In java, Date has both date and time. This is in contrast to sql where Date does not have a time element while DateTime does. That is a point of confusion that I stumbled across when I first started using sql after having done only java for many years. Anyway, I hope this explanation is helpful.

Categories

Resources