null pointer
null pointer

Reputation: 5914

Number of days between two dates (excluding these two dates)

I searched for this is SO there are so many post asking this question but all the answers is difference In Milliseconds / (24* 1000 * 60 * 60) that gives the number of 24 Hrs between two dates . but i need the number of days between 2 dates.

I.e. if date1 is 09/09/13 09:00 and date2 is 10/09/13 22:00 I need the difference as 0 and not 1 because date1 and date2 are consecutive days (even if there is more than 24 hour gap between them).

Note: I know the removing the time part and using the difference In Milliseconds / (24* 1000 * 60 * 60) method. I am looking for a better solution.

update: the app is first used on 09/09/13 09:00 its a Wednesday then the app was used on 10/09/13 22:00` its Thursday. now the user has used the app both Wednesday and Thursday even though there is more than 24 hour gap. now if i calculate the number of 24 hours between the 2 dates it gives one. as there is a day gap between 2 dates. i need it to give zero as the user used it Wednesday and Thursday there is NO DAY BETWEEN WEDNESDAY AND THURSDAY. hope you understood my question. if you still didn't just leave it, i tried by best explaining.

Upvotes: 2

Views: 1756

Answers (5)

Richard Le Mesurier
Richard Le Mesurier

Reputation: 29724

I have avoided using Joda Time for ages, but this past week I got round to using it for exactly this issue. And it was well worth it!

It is very easy to introduce some strange date handling bugs when dealing with plain Java - for example what happens when daylight savings time changes. Joda Time builds all these exceptions in already.

Check related question here:


Update

As of Java 8, the time & date functionality has been improved, and the Joda Time team suggests using that instead of their library. Here's what they say on the landing page:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Thanks to Basil Bourque for the comment.

Upvotes: 1

Basil Bourque
Basil Bourque

Reputation: 338634

tl;dr

ChronoUnit.DAYS.between(
    earlierInstant.atZone( ZoneId.of( "Africa/Tunis" ) ).toLocalDate() ,
    Instant.now().atZone( ZoneId.of( "Africa/Tunis" ) ).toLocalDate()
)

java.time

The modern approach uses the java.time classes that supplanted the troublesome old date-time classes such as Date & Calendar.

If you want to calculate the number of elapsed days as the number of calendar dates rather than the number of 24-hour chunks of time, use a date-only class rather than a date-time class.

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.

If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.

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" ) ;  

Generally best to think, work, log, serialize, and exchange values in UTC. For that, use Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant earlier = Instant.now() ;
…
Instant later = Instant.now() ;

Serialize to text in standard ISO 8601 format by calling Instant::toString and Instant::parse.

To get your elapsed dates, apply a time zone (ZoneId) to get ZonedDateTime objects.

ZonedDateTime zdtEarlier = earlier.atZone( z ) ;
ZonedDateTime zdtLater = later.atZone( z ) ;

Extract the date-only values.

LocalDate ldEarlier = zdtEarlier.toLocalDate() ;
LocalDate ldLater = zdtLater.toLocalDate() ;

Now we can get the elapsed days between the dates.

long daysElapsed = ChronoUnit.DAYS.between( ldEarlier , ldLater ) ;

This calculation is done per the Half-Open approach where the beginning is inclusive while the ending is exclusive. So, for example, a month starts with the first day of the month and runs up to, but does not include, the first day of the following month. Using this approach consistently throughout your business logic, database queries, and so on will make your codebase less error-prone and easier to read/debug/maintain.

I understand you want to use a fully-Open approach where both beginning and ending is exclusive. I strongly suggest you reconsider that position. But if you insist, simply subtract 1 from our calculation above.

long daysElapsedFullyOpen = ( ChronoUnit.DAYS.between( ldEarlier , ldLater ) - 1 ) ;  // Subtract 1 to get a fully-Open answer. NOT recommended.

By the way, you may want to consider the Period class in your work. Similarly, you may find useful the LocalDateRange class found in the ThreeTen-Extra project.


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?

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.

Upvotes: 0

Pshemo
Pshemo

Reputation: 124225

You can use this trick: if date1 is before date2 you can set hour in date1 to 1 and in date2 to 0. This way hour part in entire time difference will never be greater than 24h, so will not affect calculations so only days/months/years will matter.

Here is code example

public static long daysBetween(Date date1, Date date2) {
    Calendar c1 = Calendar.getInstance();
    c1.setTime(date1);

    Calendar c2 = Calendar.getInstance();
    c2.setTime(date2);
    if (date1.before(date2)) {
        c1.set(Calendar.HOUR_OF_DAY, 1);
        c2.set(Calendar.HOUR_OF_DAY, 0);
    } else {
        c2.set(Calendar.HOUR_OF_DAY, 1);
        c1.set(Calendar.HOUR_OF_DAY, 0);
    }

    return (c2.getTimeInMillis() - c1.getTimeInMillis())
            / (24 * 60 * 60 * 1000);
}

//DEMO
public static void main(String[] args) throws Exception {
    DateFormat df = new SimpleDateFormat("dd/MM/yy hh:mm");
    Date date1 = df.parse("09/09/13 09:00");
    Date date2 = df.parse("11/09/13 22:00");

    System.out.println(daysBetween(date1, date2));
}

Output: 1


For dates 11/09/13 09:00 09/09/13 22:00 result will be -1 since date1 is after date2

Upvotes: 0

Husman
Husman

Reputation: 6909

import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class test {

    public static void main(String[] args) throws ParseException {

        String dateStart = "09/09/13 09:00";
        String dateStop = "10/09/13 22:00";

        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");

        Date date1 = format.parse(dateStart);
        Date date2 = format.parse(dateStop);

            // calculate difference in milliseconds
        long diff = (date2.getTime() - date1.getTime()) - 86400000;
        diff = (diff <= 0 ? 0 : diff);

        System.out.println(TimeUnit.MILLISECONDS.toDays(diff));
    }

}

This will give the difference between 2 dates. And subtract a day (if its negative, it sets the difference to 0 day). This will work as long as dateStop is greater than dateStart, otherwise it will just print 0;

Upvotes: 1

Anup Cowkur
Anup Cowkur

Reputation: 20563

Here's a simple solution:

Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);

while(calendar.getTime().before(endDate))
 {
    noOfDays++;
    calendar.add(Calendar.DAY_OF_MONTH,1);
 }

Where startDate and endDate are instances of the Date class.

Note: You need to initialize the date objects so that they have the same time but only differ in their dates. Setting them both to 12 AM should do the trick:

date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);

Upvotes: 1

Related Questions