计算两个日期(不包括周末)的日期

时间:2011-11-17 17:57:15

标签: java datetime jodatime

我在Spring 3.0项目中使用Joda time api来计算日期。现在我有一个开始和结束日期,我希望在这两个日期之间每天周末或周六或周日。我怎样才能做到这一点?

我查看了这篇文章Joda time - all mondays between two dates。 它提供了一些指导,但仍然含糊不清,如何排除两个日期。

7 个答案:

答案 0 :(得分:12)

我认为你的问题是如何

  

每天除了周末或周六或周日两个日期之外。

解决方案

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

答案 1 :(得分:2)

我是新来的。 我一直在寻找这个问题的解决方案,并没有使用循环,但没有找到合适的算法。所以我决定创建这个解决方案不使用循环,非常高效并且代码已经过测试。

public int betweenDaysIgnoreWeekends(DateTime startDate, DateTime endDate) {
    //Um numero que representa o dia da semana para a data final, exemplo segunda=1, terça=2, quarta=3...
    int dayOfWeekEndDateNumber = Integer.valueOf(endDate.dayOfWeek()
            .getAsString());
    //Um numero que representa o dia da semana para a data inicial, exemplo segunda=1, terça=2, quarta=3...
    int dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek()
            .getAsString());
    //Se a data final for sabado ou domingo, finja ser sexta-feira
    if (dayOfWeekEndDateNumber == 6 || dayOfWeekEndDateNumber == 7) {
        int DaysToAdd = 8 - dayOfWeekEndDateNumber;
        endDate = endDate.plusDays(DaysToAdd);
        dayOfWeekEndDateNumber = Integer.valueOf(endDate.dayOfWeek()
                .getAsString());
    }

    //Se a data inicial for sabado ou domingo, finja ser segunda-feira
    if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
        int DaysToAdd = 8 - dayOfWeekStartDateNumber;
        startDate = startDate.plusDays(DaysToAdd);
        dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek()
                .getAsString());
    }

    //Quantos dias se passaram contando os fins de semana
    int days = Days.daysBetween(startDate, endDate).getDays();
    //Quantas semanas se passaram exatamente
    int weeks = days / 7;
    //O excesso de dias que sobrou, exemplo: 1 semana e 3 dias o excess=3 e weeks=1
    int excess = days % 7;

    //Se a data inicial for igual a data final, passou 0 dia
    if (startDate.equals(endDate)) {
        return 0;
    } else {
        //O excesso de dias passou pelo fim de semana, então deve-se retirar 2 dias
        //da quantidade final de dias
        if (excess + dayOfWeekStartDateNumber >= 6) {
            //Quantidade de semanas * 5 dias uteis + o excesso de dias - o final de semana que o excesso atravessou
            return weeks * 5 + excess - 2;
        }
        //Quantidade de semanas * 5 dias uteis + o excesso de dias
        return weeks * 5 + excess;
    }
}

答案 2 :(得分:1)

为了改进@ samir-machado-de-oliveira发布的内容,这里有一个函数可以在不使用循环的情况下计算周末。我没有对循环版本进行基准测试,但看起来好像会更快:

/**
 * Gets number of days between two dates. Ignoring weekends.
 * @param startDate
 * @param endDate
 * @return
 */
public static int getDaysBetweenIgnoreWeekends(DateTime startDate, DateTime endDate) {
    // If the start date is equal to the closing date, spent 0 days
    if (startDate.equals(endDate))
        return 0;

    // A number that represents the day for the start date, Monday = 1 , Tuesday = 2 , Wednesday = 3 ...
    int dayOfWeekStartDateNumber = startDate.getDayOfWeek();

    // If the starting date is Saturday or Sunday , pretend to be Monday
    if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
        int DaysToAdd = 8 - dayOfWeekStartDateNumber;
        startDate = startDate.plusDays(DaysToAdd);
        dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek().getAsString());
    }

    // How many days have passed counting weekends
    int days = Days.daysBetween(startDate, endDate).getDays();

    // How many weeks have passed
    int weeks = days / 7;
    // Excess days left. E.g. one week and three days the excess will be 3
    int excess = days % 7;

    // Excess of days spent for the weekend , then it must be removed two days
    // the final number of days
    if (excess + dayOfWeekStartDateNumber >= 6) {
        // Week count * 5 working days + excess days - the weekend that excess crossed
        return weeks * 5 + excess - 2;
    }
    // Weeks count * 5 working days + excess days
    return weeks * 5 + excess;
}

此外,这里有一个允许你忽略当天时间的版本,因此,如果开始日期是开始时间的上午11点,结束时间是上午10点的第二天,它将显示为1天而不是0天。

/**
 * Gets number of days between two dates. Ignoring weekends. Ignores Hours.
 * @param startDate
 * @param endDate
 * @return
 */
public static int getDaysBetweenIgnoreWeekends(DateTime startDate, DateTime endDate) {
    return getDaysBetweenIgnoreWeekends(startDate,endDate,true);
}



/**
 * Gets number of days between two dates. Ignoring weekends.
 * @param startDate
 * @param endDate
 * @param ignoreTimeOfDay
 * @return
 */
public static int getDaysBetweenIgnoreWeekends(DateTime startDate, DateTime endDate, boolean ignoreTimeOfDay) {
    // If the start date is equal to the closing date, spent 0 days
    if (startDate.equals(endDate))
        return 0;
    if (ignoreTimeOfDay && startDate.toLocalDate().equals(endDate.toLocalDate()))
        return 0;

    // A number that represents the day for the start date, Monday = 1 , Tuesday = 2 , Wednesday = 3 ...
    int dayOfWeekStartDateNumber = startDate.getDayOfWeek();

    // If the starting date is Saturday or Sunday , pretend to be Monday
    if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
        int DaysToAdd = 8 - dayOfWeekStartDateNumber;
        startDate = startDate.plusDays(DaysToAdd);
        dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek().getAsString());
    }

    // How many days have passed counting weekends
    int days;
    if(ignoreTimeOfDay) {
        days = Days.daysBetween(startDate.toLocalDate(), endDate.toLocalDate()).getDays();
    } else {
        days = Days.daysBetween(startDate, endDate).getDays();
    }

    // How many weeks have passed
    int weeks = days / 7;
    // Excess days left. E.g. one week and three days the excess will be 3
    int excess = days % 7;

    // Excess of days spent for the weekend , then it must be removed two days
    // the final number of days
    if (excess + dayOfWeekStartDateNumber >= 6) {
        // Week count * 5 working days + excess days - the weekend that excess crossed
        return weeks * 5 + excess - 2;
    }
    // Weeks count * 5 working days + excess days
    return weeks * 5 + excess;
}

答案 3 :(得分:1)

我一直在使用@Josh Maag的逻辑差不多一年了,但是最近发现当endDate恰好落在星期六时它会返回错误的值。

这是我想要分享的版本,它考虑从endDate中减去几天或周日时的天数。

public static int getDaysBetweenIgnoreWeekends(org.joda.time.DateTime startDate, org.joda.time.DateTime endDate, boolean ignoreTimeOfDay) {

    // If the start date is equal to the closing date, spent 0 days
    if (startDate.equals(endDate))
        return 0;
    if (ignoreTimeOfDay && startDate.toLocalDate().equals(endDate.toLocalDate()))
        return 0;

    // A number that represents the day for the start date, Monday = 1 , Tuesday = 2 , Wednesday = 3 ...
    int dayOfWeekStartDateNumber = startDate.getDayOfWeek();
    int dayOfWeekEndDateNumber = endDate.getDayOfWeek();

    // If the starting date is Saturday or Sunday , pretend to be Monday
    if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
        int DaysToAdd = 8 - dayOfWeekStartDateNumber;
        startDate = startDate.plusDays(DaysToAdd);
        dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek().getAsString());
    }

    org.joda.time.DateTime effectiveEndDate = endDate; 

    if (dayOfWeekEndDateNumber == 6 || dayOfWeekEndDateNumber == 7) {
        effectiveEndDate = endDate.minusDays(Math.abs(5 - dayOfWeekEndDateNumber)); 
    }

    // How many days have passed counting weekends
    int days;
    if(ignoreTimeOfDay) {
        days = org.joda.time.Days.daysBetween(startDate.toLocalDate(), effectiveEndDate.toLocalDate()).getDays();
    } else {
        days = org.joda.time.Days.daysBetween(startDate, effectiveEndDate).getDays();
    }

    // How many weeks have passed
    int weeks = days / 7;
    // Excess days left. E.g. one week and three days the excess will be 3

    int excess = days % 7;

    // Excess of days spent for the weekend , then it must be removed two days
    // the final number of days
    if (excess + dayOfWeekStartDateNumber >= 6) {
        // Week count * 5 working days + excess days - the weekend that excess crossed
        return weeks * 5 + excess - 2;
    }
    // Weeks count * 5 working days + excess days
    return weeks * 5 + excess;
}

在早期版本中 - 以下代码段减去了额外的一天。无论endDate是星期六还是星期日,都减去-2。

if (excess + dayOfWeekStartDateNumber >= 6) {
    // Week count * 5 working days + excess days - the weekend that excess crossed
    return weeks * 5 + excess - 2;
} 

希望有所帮助!

答案 4 :(得分:0)

您可以使用格里历日历来检索特定日期的日期。如果字符串是星期六或星期日,你可以忽略它。

答案 5 :(得分:0)

这将通过排除周末来返回结束日期

public static Date addDaysBySkipWeekend(Date startDate, int numDays) {
        Calendar dateCal = Calendar.getInstance();
        dateCal.setTime(startDate);
        for (int i = 0; i < numDays-1; i++) {
            dateCal.add(dateCal.DATE, 1);
            if(dateCal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY 
                    || dateCal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY  ){
                dateCal.add(dateCal.DATE, 1);
                i--;
            }
        }
        return dateCal.getTime();
    }

答案 6 :(得分:0)

巧妙地使用Java 8 Streams:

  public LocalDate[] filterWeekdaysForRange(final LocalDate start,final LocalDate end) {
    return Stream.iterate(start, date -> date.plusDays(1))
            .limit(ChronoUnit.DAYS.between(start, end)+1)
            .filter(d->d.getDayOfWeek() != SATURDAY)
            .filter(d->d.getDayOfWeek() != SUNDAY)
            .toArray(LocalDate[]::new);
  }

这是对此处提供的解决方案的改编:https://stackoverflow.com/a/38220748/744133