【问题标题】:Calculating dates given two dates excluding weekend计算给定两个日期的日期,不包括周末
【发布时间】:2011-11-17 17:57:15
【问题描述】:

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

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

【问题讨论】:

  • Calculate number of daysget all dates?

标签: java datetime jodatime


【解决方案1】:

我认为你的问题是如何

在两个日期之间获取除周末或周六或周日以外的每一天。

解决方案

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

【讨论】:

  • 我实际上是在按照这些思路做一些事情,但正在考虑测试当天是否是周六/周日,然后排除...这个逻辑非常有效...谢谢分配。
  • 假设周末由周六+周日组成,但并非在所有国家/地区都如此
【解决方案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;
    }
}

【讨论】:

    【解决方案3】:

    我已经使用@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;
    }
    

    在早期版本中 - 在 sn-p 之后减去了额外的一天。无论 endDate 是星期六还是星期日,都减去 -2。

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

    希望有帮助!

    【讨论】:

      【解决方案4】:

      为了改进@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;
      }
      

      【讨论】:

        【解决方案5】:

        巧妙地使用 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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

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

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

            【讨论】:

              猜你喜欢
              • 2019-04-15
              • 1970-01-01
              • 1970-01-01
              • 2022-12-12
              • 2016-01-17
              • 1970-01-01
              • 2015-04-25
              • 1970-01-01
              相关资源
              最近更新 更多