I have a method wherein have to check whether a LocalDate falls in between two java.util.Date values.
there are methods after and before in java.util.Date
and there are methods isAfter and isBefore in LocalDate.
The code snippet which i have is as :
/**
* checks if date passed falls between start & end date
*
* #param date
* #param startDate
* #param endDate
* #return
*/
public static boolean isBetween(Date date, Date startDate, Date endDate) {
return (startDate == null || date.after(startDate) || date.equals(startDate))
&& (endDate == null || date.before(endDate) || date.equals(endDate));
}
There is no method in the API to compare across..
You need to decide on many corner and edge cases. Here’s a shot.
public static boolean isBetween(LocalDate date, Date startDate, Date endDate) {
ZoneId zone = ZoneId.systemDefault();
// Is before start?
if (startDate != null) {
LocalDate startLocalDate = startDate.toInstant().atZone(zone).toLocalDate();
if (date.isBefore(startLocalDate)) {
return false;
}
}
// Is after end?
if (endDate != null) {
LocalDate endLocalDate = endDate.toInstant().atZone(zone).toLocalDate();
if (date.isAfter(endLocalDate)) {
return false;
}
}
// If we end up here, the date is between start and end inclusive
return true;
}
I am assuming that the old-fashioned Date objects are to be interpreted in the default time zone of the JVM. On one hand this is standard, on the other hand the default time zone can be changed at any time, also from other programs running in the same JVM, so this is fragile. I am discarding the time of day part of the thus interpreted date. Whether the time is 00:00 or it’s 23:59:59.999, I deem the LocalDate inside the interval if the date agrees. You may want quite different behaviour.
If you wanted to take the time into account, you should probably convert everything to Instant or ZonedDateTime instead.
As you can see, mixing old-fashioned and modern classes leads to quite some complication. I am converting Date to LocalDate in order to take advantage of java.time, which in turn also gets more complicated since the Dates may be null.
Convert LocalDate to String and convert this String to java.util.Date and you can use your method.
To convert LocalDate to String:
LocalDate localDate = LocalDate.now();
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String localDateToString = localDate.format(dateFormatter1);
And to convert String to Date:
SimpleDateFormat formatter=new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
Date date1=formatter1.parse(sDate1);
Once you've converted LocalDate to Date, you can compare dates using your method.
You will have to convert java.util.Date to LocalDate instances for comparison. Since you have to compare LocalDate with other dates, so losing the time part seems to be a logical compromise here.
public static boolean isBetween(LocalDate localDate, Date start, Date end){
LocalDate startLocalDate = Instant.ofEpochMilli(start.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate endLocalDate = Instant.ofEpochMilli(end.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
return (localDate.isEqual(startLocalDate) || localDate.isEqual(endLocalDate)) || (localDate.isAfter(startLocalDate) && localDate.isBefore(endLocalDate));
}
I have made the endDate as inclusive upper limit.
Related
I'm trying to check if a selected dates range by the user is within a range of dates exist in database.
e.g.
User select :
Start date : 24/09/2022
End date : 30/09/2022
Date range in database is :
Start date : 28/09/2022
End date : 30/09/2022
Imagine you have a reservation car between 28/09 → 30/09, if a user wants to reserve this car between 24/09 --> 30/09, then the app should notify them that the car is reserved in that date because it's already reserved between 28--> 30.
My situation is similar to this: Check if a date range is within a date range. Only that question is about C#, and I am coding Java.
My code so far :
boolean isFound = DateHelper.isWithinRange2Dates(
/*ENTERED BY USER*/
string2Date("24/09/2022"),
string2Date("30/09/2022"),
/*IN DATABASE*/
string2Date("28/09/2022"),
string2Date("30/09/2022"));
ToastUtils.showLong(isFound ? "FOUND" : "NOT FOUND");
Methods used :
public static boolean isWithinRange(Date selectedDate, Date startDate, Date endDate) {
return selectedDate.after(startDate) && (selectedDate.before(endDate) || DateUtils.isSameDay(selectedDate, endDate));
}
public static boolean isWithinRange2Dates(Date selectedStartDate, Date selectedEndDate, Date startDate, Date endDate) {
return isWithinRange(selectedStartDate, startDate, endDate) && isWithinRange(selectedEndDate, startDate, endDate);
}
#SuppressLint("SimpleDateFormat")
public static Date string2Date(String dateStr) {
try {
return new SimpleDateFormat("dd/MM/yyyy").parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
Issue:
28/09 --> 30/09 is within the 24/09 --> 30/09 so the method should true
Question:
How I can check if a selected start and end date are within a date range or not?
tl;dr
org.threeten.extra.LocalDateRange.of
(
LocalDate.of( … ) ,
LocalDate.of( … )
)
.encloses
(
LocalDateRange.of
(
startJavaSqlDate.toLocalDate() ,
stopJavaSqlDate.toLocalDate()
)
)
Avoid legacy date-time classes
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.
One of the many design flaws in the Date class is that there are actually two Date classes:
java.util.Date
java.sql.Date
The first represents a moment as seen in UTC. The second pretends to represent a date-only, without a time-of-day and without an offset or time zone. But actually, in a case of extremely poor judgement, the second class extends from the first… so it does indeed internally represent a moment in UTC. Messy? Yes, a terrible mess.
LocalDate
You neglect to mention in your Question which class you are using. So I'll go with the second one, java.sql.Date.
When handed a java.sql.Date object, immediately convert to the modern replacement: LocalDate. Do so by calling the new conversion method added to the old class.
LocalDate ld = myJavaSqlDate.toLocalDate() ;
LocalDateRange
To compare date ranges, you could write the code yourself. But why bother? Add the ThreeTen-Extra library to your project. Doing so gives you access to the LocalDateRange class. That class provides several handy methods such as contains, abuts, encloses, overlaps, etc.
LocalDateRange target =
LocalDateRange.of(
LocalDate.of( … ) ,
LocalDate.of( … )
)
;
… and:
LocalDateRange selected =
LocalDateRange.of(
startJavaSqlDate.toLocalDate() ,
stopJavaSqlDate.toLocalDate()
)
;
Compare.
boolean enclosed = target.encloses( selected ) ;
Your isWithin range functions operator
Precedence is wrong.Also checking isSameDate for both end and start dates are missing. In your code it return false if user startDate is simmilar to your dateRange start date or if user end date simmilar to datarange end date. Correct implementation as follows of isWithinRange function.
return (selectedDate.after(startDate) || DateUtils.isSameDay(selectedDate, startDate)) && (selectedDate.before(endDate) || DateUtils.isSameDay(selectedDate, endDate));
Use || operator not && for isWithinRange2Dates function as follows.
return isWithinRange(selectedStartDate, startDate, endDate) || isWithinRange(selectedEndDate, startDate, endDate);
This question already has answers here:
How to check if a date is greater than another in Java? [duplicate]
(4 answers)
Closed 2 years ago.
My date time formatter is , "yyyy-MM-DD"
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-DD")
I want to check the date is later than today's date or not. I checked it using this validation.
if(dateFormatter.format(given_Date).compareTo(dateFormatter.format(new Date())) > 0){ ...}
But every time this returns false when the given date is later or not. Can anyone help with this me, please?
tl;dr
You asked:
check the date is later than today's date
LocalDate // Represent a date-only value, without time-of-day and without time zone or offset-from-UTC.
.parse( "2020-01-23" ) // No need to specify formatting pattern when parsing a string in standard ISO 8601 format. Returns a `LocalDate` object.
.isAfter // Compare one `LocalDate` object to another.
(
LocalDate.now // Capture the current date as seen in a particular time zone.
(
ZoneId.of( "Africa/Tunis" ) // or: ZoneId.systemDefault()
) // Returns a `LocalDate` object.
) // Returns `boolean`.
Details
Modern solution uses java.time classes, specifically java.time.LocalDate. Compare with isAfter method. You are using terrible date-time classes that were years ago supplanted by java.time.
No need to specify a formatting pattern. Your input strings comply with the ISO 8601 standard used by default in java.time.
By the way, formatting codes are case-sensitive, and day-of-month is dd rather than the DD you used. So the formatting pattern used here by default is akin to uuuu-MM-dd.
boolean isFuture = LocalDate.parse( "2020-01-23" ).isAfter( LocalDate.now() ) ;
Better to explicitly specify desired/expected time by which to determine today’s date. If omitted, the JVM’s current default time zone is implicitly applied.
boolean isFuture = LocalDate.parse( "2020-01-23" ).isAfter( LocalDate.now( ZoneId.of( "America/Edmonton" ) ) ) ;
If you can work with the variable givenDate as a String there is another way. Check out my code:
import java.util.Calendar;
public class compareDates {
public static void main(String[] args){
Calendar c = Calendar.getInstance();
String givenDate = "2021-01-10";
boolean later = false;
int yr_now = c.get(Calendar.YEAR);
int m_now = c.get(Calendar.MONTH) + 1;
int day_now = c.get(Calendar.DAY_OF_MONTH);
int given_yr = Integer.parseInt(givenDate.substring(0,4));
int given_m = Integer.parseInt(givenDate.substring(5,7));
int given_day = Integer.parseInt(givenDate.substring(8,10));
//is "given date" later than today's date?
if(yr_now > given_yr) {
System.out.print(later);
}
else if (yr_now == given_yr && m_now > given_m){
System.out.print(later);
}
else if (m_now == given_m && day_now >= given_day){
System.out.print(later);
}
else {later = true; System.out.print(later);}
}}
I assumed this would have already been asked, but I couldn't find anything.
Using java.time what is the best way to determine if a given ZonedDateTime is "today"?
I've come up with at least two possible solutions. I'm not sure if there are any loopholes or pitfalls with these approaches. Basically the idea is to let java.time figure it out and not do any math myself:
/**
* #param zonedDateTime a zoned date time to compare with "now".
* #return true if zonedDateTime is "today".
* Where today is defined as year, month, and day of month being equal.
*/
public static boolean isZonedDateTimeToday1(ZonedDateTime zonedDateTime) {
ZonedDateTime now = ZonedDateTime.now();
return now.getYear() == zonedDateTime.getYear()
&& now.getMonth() == zonedDateTime.getMonth()
&& now.getDayOfMonth() == zonedDateTime.getDayOfMonth();
}
/**
* #param zonedDateTime a zoned date time to compare with "now".
* #return true if zonedDateTime is "today".
* Where today is defined as atStartOfDay() being equal.
*/
public static boolean isZoneDateTimeToday2(ZonedDateTime zonedDateTime) {
ZonedDateTime now = ZonedDateTime.now();
LocalDateTime atStartOfToday = now.toLocalDate().atStartOfDay();
LocalDateTime atStartOfDay = zonedDateTime.toLocalDate().atStartOfDay();
return atStartOfDay == atStartOfToday;
}
If you mean today in the default time zone:
return zonedDateTime.toLocalDate().equals(LocalDate.now());
//you may want to clarify your intent by explicitly setting the time zone:
return zonedDateTime.toLocalDate().equals(LocalDate.now(ZoneId.systemDefault()));
If you mean today in the same timezone as the ZonedDateTime:
return zonedDateTime.toLocalDate().equals(LocalDate.now(zonedDateTime.getZone()));
How do I check if request is in between this window? I have a time of request as 2011-12-03T15:15:30-05:00 and a time window which could be defined in any zone, example 09:00:00+00:00 and 17:00:00+00:00.
Now if i parse the datetime to LocalTime i loose the timezone.
public LocalTime time(String time){
return LocalTime.from(DateTimeFormatter.ISO_OFFSET_TIME.parse(time));
}
private ZonedDateTime dateTime(String dateTime){
return ZonedDateTime.from(DateTimeFormatter.ISO_DATE_TIME.parse(dateTime));
}
//Compare function
public boolean compare(ZonedDateTime dateTime, LocalTime localTime, LocalTime localTime2) {
LocalTime time = dateTime.withZoneSameInstant(utc).toLocalTime();
int start = time.compareTo(localTime);
int end = time.compareTo(localTime2);
return start >= 0 && end <= 0;
}
now i invoke the above compare function as:
service.compare(dateTime("2011-12-03T15:15:30-05:00"), time("09:00:00+00:00"), time("17:00:00+00:00"));
Here is example of code that will compare a ZonedDateTime value in any time zone, to see if it falls within a time-of-day window define in another (or same) time zone, correctly adjusting for the time zone difference.
Notice that time window values are now OffsetTime, not LocalTime, so the window time zone offset is known.
Also notice that this code was change to be upper-exclusive, which is generally what you want for range comparisons like this.
public static boolean inWindow(ZonedDateTime dateTime, OffsetTime windowStart, OffsetTime windowEnd) {
if (! windowStart.getOffset().equals(windowEnd.getOffset()))
throw new IllegalArgumentException("windowEnd must have same offset as windowStart");
OffsetTime time = dateTime.toOffsetDateTime()
.withOffsetSameInstant(windowStart.getOffset())
.toOffsetTime();
return (! time.isBefore(windowStart) && time.isBefore(windowEnd));
}
Is there a good way to get the date of the coming Wednesday?
That is, if today is Tuesday, I want to get the date of Wednesday in this week; if today is Wednesday, I want to get the date of next Wednesday; if today is Thursday, I want to get the date of Wednesday in the following week.
Thanks.
The basic algorithm is the following:
Get the current date
Get its day of week
Find its difference with Wednesday
If the difference is not positive, add 7 (i.e. insist on next coming/future date)
Add the difference
Here's a snippet to show how to do this with java.util.Calendar:
import java.util.Calendar;
public class NextWednesday {
public static Calendar nextDayOfWeek(int dow) {
Calendar date = Calendar.getInstance();
int diff = dow - date.get(Calendar.DAY_OF_WEEK);
if (diff <= 0) {
diff += 7;
}
date.add(Calendar.DAY_OF_MONTH, diff);
return date;
}
public static void main(String[] args) {
System.out.printf(
"%ta, %<tb %<te, %<tY",
nextDayOfWeek(Calendar.WEDNESDAY)
);
}
}
Relative to my here and now, the output of the above snippet is "Wed, Aug 18, 2010".
API links
java.util.Calendar
java.util.Formatter - for the formatting string syntax
tl;dr
LocalDate // Represent a date-only value, without time-of-day and without time zone.
.now() // Capture the current date as seen in the wall-clock time used by the people of a specific region (a time zone). The JVM’s current default time zone is used here. Better to specify explicitly your desired/expected time zone by passing a `ZoneId` argument. Returns a `LocalDate` object.
.with( // Generate a new `LocalDate` object based on values of the original but with some adjustment.
TemporalAdjusters // A class that provides some handy pre-defined implementations of `TemporalAdjuster` (note the singular) interface.
.next( // An implementation of `TemporalAdjuster` that jumps to another date on the specified day-of-week.
DayOfWeek.WEDNESDAY // Pass one of the seven predefined enum objects, Monday-Sunday.
) // Returns an object implementing `TemporalAdjuster` interface.
) // Returns a `LocalDate` object.
Details
Using Java8 Date time API you can easily find the coming Wednesday.
LocalDate nextWed = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
next(DayOfWeek dayOfWeek) - Returns the next day-of-week adjuster, which adjusts the date
to the first occurrence of the specified day-of-week after the date
being adjusted.
Suppose If you want to get previous Wednesday then,
LocalDate prevWed = LocalDate.now().with(TemporalAdjusters.previous(DayOfWeek.WEDNESDAY));
previous(DayOfWeek dayOfWeek) - Returns the previous day-of-week adjuster, which adjusts
the date to the first occurrence of the specified day-of-week before
the date being adjusted.
Suppose If you want to get next or current Wednesday then
LocalDate nextOrSameWed = LocalDate.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.WEDNESDAY));
nextOrSame(DayOfWeek dayOfWeek) - Returns the next-or-same day-of-week
adjuster, which adjusts the date to the first occurrence of the
specified day-of-week after the date being adjusted unless it is
already on that day in which case the same object is returned.
Edit:
You can also pass ZoneId to get the current date from the system clock in the specified time-zone.
ZoneId zoneId = ZoneId.of("UTC");
LocalDate nextWed = LocalDate.now(zoneId).with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
For more information refer TemporalAdjusters
Using JodaTime:
LocalDate date = new LocalDate(System.currentTimeMillis());
Period period = Period.fieldDifference(date, date.withDayOfWeek(DateTimeConstants.WEDNESDAY));
int days = period.getDays();
if (days < 1) {
days = days + 7;
}
System.out.println(date.plusDays(days));
Calendar c= Calendar.getInstance();
c.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
c.add(Calendar.DAY_OF_MONTH, 7);
c.getTime();
Use java.util.Calendar. You get the current date/time like this:
Calendar date = Calendar.getInstance();
From there, get date.get(Calendar.DAY_OF_WEEK) to get the current day of week and get the difference to Calendar.WEDNESDAY and add it.
public static void nextWednesday() throws ParseException
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
int weekday = calendar.get(Calendar.DAY_OF_WEEK);
int days = Calendar.WEDNESDAY - weekday;
if (days < 0)
{
days += 7;
}
calendar.add(Calendar.DAY_OF_YEAR, days);
System.out.println(sdf.format(calendar.getTime()));
}