Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inclusive Date Range check in Joda Time

Tags:

I am using Joda Time 2.1 library.

I have written a method to compare if a given date is between a date range of not. I want it to be inclusive to the start date and end date.I have used LocalDate as I don't want to consider the time part only date part.

Below is the code for it.

isDateBetweenRange(LocalDate start,LocalDate end,LocalDate target){         System.out.println("Start Date : "               +start.toDateTimeAtStartOfDay(DateTimeZone.forID("EST"));         System.out.println("Target Date : "               +targettoDateTimeAtStartOfDay(DateTimeZone.forID("EST"));         System.out.println("End Date : "               +end.toDateTimeAtStartOfDay(DateTimeZone.forID("EST"));         System.out.println(target.isAfter(start));         System.out.println(target.isBefore(end)); } 

The output of above method is :

Start Date: 2012-11-20T00:00:00.000-05:00 Target Date: 2012-11-20T00:00:00.000-05:00 End Date : 2012-11-21T00:00:00.000-05:00 target.isAfter(start) : false target.isBefore(end) : true 

My problem is target.isAfter(start) is false even if the target date and start are having the same values.

I want that target >= start but here it considers only target > start.
I want it inclusive.

Does it mean that isAfter method finds a match exclusively ?

I have gone through the javadoc for Joda Time, but didn't found anything about it.

like image 298
Abubakkar Avatar asked Nov 27 '12 12:11

Abubakkar


People also ask

How do you check if a date falls within a range in Java?

The idea is quite simple, just use Calendar class to roll the month back and forward to create a “date range”, and use the Date. before() and Date. after() to check if the Date is within the range.

How do I change the date format in Joda-time?

How to change the SimpleDateFormat to jodatime? String s = "2014-01-15T14:23:50.026"; DateTimeFormatter dtf = DateTimeFormat. forPattern("yyyy-MM-dd'T'HH:mm:ss. SSSS"); DateTime instant = dtf.

Is Joda-time deprecated?

So the short answer to your question is: YES (deprecated).


2 Answers

Yes, isAfter is exclusive, otherwise it should probably have been named isEqualOrAfter or something similar.

Solution: Use "not before" instead of "after", and "not after" instead of "before".

boolean isBetweenInclusive(LocalDate start, LocalDate end, LocalDate target) {     return !target.isBefore(start) && !target.isAfter(end); } 
like image 129
Jesper Avatar answered Sep 20 '22 15:09

Jesper


tl;dr

Joda-Time has been supplanted by the java.time classes and the ThreeTen-Extra project.

The LocalDateRange and Interval classes representing a span-of-time use the Half-Open definition. So, asking if the beginning is contained returns true.

LocalDateRange.of(                     // `org.threeten.extra.LocalDateRange` class represents a pair of `LocalDate` objects as a date range.     LocalDate.of( 2018, 8 , 2 ) ,      // `java.time.LocalDate` class represents a date-only value, without time-of-day and without time zone.     LocalDate.of( 2018 , 8 , 20 )  )                                      // Returns a `LocalDateRange` object. .contains(     LocalDate.now()                    // Capture the current date as seen in the wall-clock time used by the people of the JVM’s current default time zone. ) 

true

java.time

FYI, the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. See Tutorial by Oracle.

Date-only

Apparently you may care about the date and not the time-of-day. If so, use LocalDate class.

For managing a date range, add the ThreeTen-Extra library to your project. This gives you access to the LocalDateRange class.

That class offers several methods for comparison: abuts, contains, encloses, equals, intersection, isBefore, isAfter, isConnected, overlaps, span, and union.

LocalDateRange r =      LocalDateRange.of(          LocalDate.of( 2018, 8 , 2 ) ,          LocalDate.of( 2018 , 8 , 20 )      )  ;  LocalDate target = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ) ;  // Capture the current date as seen in the wall-clock time used by the people of a particular time zone. boolean contains = r.contains( target ) ; 

Date-time

If you care about the date and the time-of-day in a particular time zone, use ZonedDateTime class.

Start with your LocalDate, and let that class determine the first moment of the day. The day does not always start at 00:00:00 because of anomalies such as Daylight Saving Time (DST).

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" ) ;  // Or "America/New_York", etc. ZonedDateTime zdtStart = LocalDate.of( 2018, 8 , 2 ).atStartOfDay( z ) ; ZonedDateTime zdtStop = LocalDate.of( 2018, 8 , 20 ).atStartOfDay( z ) ; ZonedDateTime zdtTarget = ZonedDateTime.now( z ) ; 

Represent a range with the Interval from ThreeTen-Extra. This class represents a pair of Instant objects. An Instant is a moment in UTC, always in UTC. We can easily adjust from our zoned moment to UTC by simply extracting an Instant. Same moment, same point on the timeline, different wall-clock time.

Instant instantStart = zdtStart.toInstant() ; Instant instantStop = zdtStop.toInstant() ; Instant instantTarget = zdtTarget.toInstant() ;  Interval interval = Interval.of( instantStart , intervalStop ) ; boolean contains = interval.contains( instantTarget ) ; 

Half-Open

The best approach to defining a span-of-time is generally the Half-Open approach. This means the beginning is inclusive while the ending is exclusive.

The comparisons in the ThreeTen-Extra range classes seen above (LocalDateRange & Interval) both use Half-Open approach. So asking if the starting date or starting moment is contained in the range results in a true.


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.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, Java SE 10, 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 Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). 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.

like image 42
Basil Bourque Avatar answered Sep 20 '22 15:09

Basil Bourque