Java Questions
Java Questions

Reputation: 7953

how to get number of days in given date range?

I try to find number of days using following method,

public static int findNoOfDays(int year, int month, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, day);
        int days = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        return days;
    }

likewise I want to get the number of days by giving start date and end date and get the number of days excluding Saturday and Sunday.

Upvotes: 3

Views: 8530

Answers (5)

Basil Bourque
Basil Bourque

Reputation: 338614

tl;dr

java.time.LocalDate.of( 2018 , Month.JANUARY , 23 )    // A date-only class, built into Java 8 and later.
    .with( 
        org.threeten.extra.Temporals.NextWorkingDay()  // An implementation of `TemporalAdjuster` available in the ThreeTen-Extra library.
    )                                                  // Returns a new distinct `LocalDate` object, per the Immutable Objects pattern.

java.time

The modern approach uses the java.time classes.

Define your start and stop dates. The LocalDate class represents a date-only value without time-of-day and without time zone.

LocalDate start = LocalDate.of( 2018 , Month.JANUARY , 23 ) ;
LocalDate stop = start.plusMonths( 1 ) ;

Define the weekend specifically, using an EnumSet of DayOfWeek enum objects.

Set< DayOfWeek > weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY ) ;

Collect the dates matching our criteria. If you desire, you can optimize a bit by pre-sizing your List of hits (don’t bother for a small number).

int days = (int)ChronoUnit.DAYS.between( start , stop ) ;
int weekendDaysEstimate = (int)  ( ChronoUnit.WEEKS.between( start , stop ) * 2 )  ; // Approximate.
int initialCapacity = (days - weekendDaysEstimate + 7 ) ;  // Adding seven arbitrarily for good measure so I don’t strain my brain worrying about exact number.
List< LocalDate > dates = new ArrayList<>( initialCapacity ) ;

Loop the days of your date range, incrementing a day at a time. Ask if each date’s day-of-week is found in our definition of weekend.

LocalDate ld = start ;
while( ld.isBefore( stop ) ) {
    DayOfeek dow = ld.getDayOfWeek() ;
    if( weekend.contains( dow ) ) {
        // Just ignore it.
    } else {  // If not weekend, we care about this date. Collect it.
        dates.add( ld ) ;
    }
    // Setup the next loop.
    ld = ld.plusDays( 1 ) ;
}

[2018-01-23, 2018-01-24, 2018-01-25, 2018-01-26, 2018-01-29, 2018-01-30, 2018-01-31, 2018-02-01, 2018-02-02, 2018-02-05, 2018-02-06, 2018-02-07, 2018-02-08, 2018-02-09, 2018-02-12, 2018-02-13, 2018-02-14, 2018-02-15, 2018-02-16, 2018-02-19, 2018-02-20, 2018-02-21, 2018-02-22]

You could simplify this syntax, and make it easy for re-use, by writing your own implementation of a TemporalAdjuster.

LocalDate ldNextWorkingDay = ld.with( myNextWorkingDayTemporalAdjuster ) ;

Oh, wait… Somebody already wrote such an adjuster. Available with the ThreeTen-Extra library that extends the functionality of the java.time classes.

Example. Much less code, and your intention in more clear. Note that we subtract a day from the start, to first consider the start date itself.

LocalDate ld = start.minusDays(1).with( org.threeten.extra.Temporals.NextWorkingDay() ) ;  // Subtract one day to consider the start date itself.
while( ld.isBefore( stop ) ) {
    dates.add( ld ) ;
    // Setup the next loop.
    ld = ld.with( org.threeten.extra.Temporals.NextWorkingDay() ) ;
}  ;

Note that our logic here uses the Half-Open approach to defining a span of time. In this approach, the beginning is inclusive while the ending is exclusive. This approach is generally the best practice for date-time handling.

Finally, to get your count of days, Get the size of the collection of LocalDate hits.

int countDays = dates.size() ;

If you were doing this chore an enormous number of times, you could optimize by calculating the partial weeks at the beginning and the ending, then calculate the number of whole weeks to be multiplied by two as an adjustment in total number of days. But for most apps I would guess such an optimization would not be material.


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: 1

dimas
dimas

Reputation: 6073

Here is a method that calculates the number of days between two dates:

private int calculateNumberOfDaysBetween(Date startDate, Date endDate) {
    if (startDate.after(endDate)) {
        throw new IllegalArgumentException("End date should be grater or equals to start date");
    }

    long startDateTime = startDate.getTime();
    long endDateTime = endDate.getTime();
    long milPerDay = 1000*60*60*24; 

    int numOfDays = (int) ((endDateTime - startDateTime) / milPerDay); // calculate vacation duration in days

    return ( numOfDays + 1); // add one day to include start date in interval
}

And here is a method that calculates the number of weekent days in the specified time period:

private static int calculateNumberOfWeekendsInRange(Date startDate, Date endDate) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(startDate);

    int counter = 0;
    while(!calendar.getTime().after(endDate)) {
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek==1 || dayOfWeek==7) {
            counter++;
        }
        calendar.add(Calendar.DAY_OF_MONTH, 1);
    }

    return counter;
}

EDIT:

I changed last method, now it calculates the number of days exclude weekend days:

private int calculateNumberOfDaysExcludeWeekends(Date startDate, Date endDate) {
    if (startDate.after(endDate)) {
        throw new IllegalArgumentException("End date should be grater or equals to start date");
    }

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

    int numOfDays = 0;
    while(!calendar.getTime().after(endDate)) {
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if ( (dayOfWeek>1) && (dayOfWeek<7) ) {
            numOfDays++;
        }
        calendar.add(Calendar.DAY_OF_MONTH, 1);
    }

    return numOfDays;
}

Upvotes: 6

ema
ema

Reputation: 30

If You want to get number of days excluding Saturday and Sunday You can count number of weeks between two dates lets call it num_of_weeks which will also be number of weekends between two dates. And then subtract (num_of_weeks * 2) from number of days between two dates.

Upvotes: 1

Java Questions
Java Questions

Reputation: 7953

get every day except weekend or Saturday or Sunday between two dates.

Solution :

Use joda time

public static void main(String[] args) {
    final LocalDate start = LocalDate.now();
    final LocalDate end = new LocalDate(2012, 1, 14);

    LocalDate weekday = start;

    if (start.getDayOfWeek() == DateTimeConstants.SATURDAY ||
            start.getDayOfWeek() == DateTimeConstants.SUNDAY) {
        weekday = weekday.plusWeeks(1).withDayOfWeek(DateTimeConstants.MONDAY);
    }

    while (weekday.isBefore(end)) {
        System.out.println(weekday);

        if (weekday.getDayOfWeek() == DateTimeConstants.FRIDAY)
            weekday = weekday.plusDays(3);
        else
            weekday = weekday.plusDays(1);
    }
}

Upvotes: 0

Related Questions