【问题标题】:Calculating total days minus weekend计算总天数减去周末
【发布时间】:2013-07-04 15:48:33
【问题描述】:

我需要获取自创建日期以来经过的天数。这个数字需要减去周末。我只有一些函数:JulianDay、JulianWeek、JulianYear 来获取 Julian 日期值,我还有 Today 返回今天的日期,时间戳返回日期和时间。我已经设法通过使用:JulianDay(today)-JulianDay(creation date) 来获得今天创建日期的差异,但我仍然无法绕过减去周末

【问题讨论】:

  • 您正在使用哪种框架/语言?它可能会变得无关紧要,但它可以帮助其他人指出已经存在的日期 API,并可能在这方面对您有所帮助。
  • 我没有说明的原因是因为我正在研究 Siebel 上的计算字段,但我也认为这样的算法会很有用
  • 哦,现在我明白了。我的回答是基于你在哪里使用 java 的想法。您基本上需要遍历所有天并询问当前日期是星期日还是星期六,如果是,则增加一个计数器。
  • JulianDay 究竟返回了什么?如果它返回一个从 1 到 31 的数字,那么如果日期发生在两个不同的月份(或年份)中,JulianDay(today) - JulianDay(creation date) 的计算就会遇到麻烦......
  • 另见问题1234567链接在右侧边栏中

标签: algorithm date


【解决方案1】:

不完全确定您在问题中引用的功能是做什么的,但是,您似乎对 做基本的日期算术来确定两个给定日期之间的天数。困难的部分似乎 弄清楚周末要减去多少天。

我认为您可以通过两个功能来完成此操作:

  1. 给定两个日期,返回它们之间的天数。打电话给DAYS(date-1, date-2)
  2. 给定一个日期,返回星期几(其中 1 = 星期一 ... 7 = 星期日)。打电话给DAY-OF-WEEK(date)

拥有这些功能后,您可以执行以下操作:

  • 计算日期范围内的完整周数:WEEKS = DAYS(date-1, date2) mod 7
  • 计算天数而不是整周的一部分:DAYS-LEFT = DAYS(date-1, date-2) - (WEEKS * 7)
  • 确定最后一天是一周中的哪一天:LAST-DAY = DAY-OF-WEEK(date-2)

从部分周调整DAYS-LEFT的数量如下:

if DAYS-LEFT > 0 then
  case LAST-DAY
    when 6 then /* Saturday */
      DAYS-LEFT = DAYS-LEFT - 1
    when 7 then /* Sunday */
      if DAYS-LEFT = 1 then
         DAYS-LEFT = 0
      else
         DAYS-LEFT = DAYS-LEFT - 2
      end-if
    when other /* Monday through Friday */
      case DAYS-LEFT - LAST-DAY
        when > 1 then
          DAYS-LEFT = DAYS-LEFT - 2
        when = 1 then
          DAYS-LEFT = DAYS-LEFT - 1
        when other
          DAYS-LEFT = DAYS-LEFT /* no adjustment */
       end-case
  end-case
end-if

DAYS-EXCLUDING-WEEKENDS = DAYS(date-1, date-2) - (WEEKS * 2) + DAYS-LEFT

我假设您拥有或可以构建 DAYS(date-1, date-2) 函数。下一位是确定一周中的哪一天 一个给定的日期。执行此操作的算法称为Zeller's congruence。我不会 在这里重复该算法,因为 Wikipedia 很好地描述了它。

希望这能让你顺利上路……

【讨论】:

  • 这似乎是一个很好的算法,但我刚刚在我的上下文中发现,我不能使用 % :( 限制太多!
【解决方案2】:

您的JulianDay(y,m,d) 函数返回每个日期的序列号;假设为了讨论,JulianDay(2013,7,4) 返回 2456478。第二天将是 2456479,然后是 2456480,依此类推。假设两天之差是diff

diff 中的完整周数为diff // 7(这是整数除法,因此向下取整),每个包含 5 个工作日。因此,如果 diff 为 25,则将有 25 // 7 = 3 整周加上额外的 diff % 7 = 4 天。整整 3 周包含 15 个工作日;从一周中的哪一天开始并不重要。因此,您只需要考虑额外的 4 天,就可以了解工作日的情况。

JulianDay函数返回的数字可以取模7来计算星期几;在我的JulianDay 函数中,模 5 代表星期六,模 6 代表星期日。您可以将额外的 4 天作为周期开始的 4 天或结束的 4 天;没关系,因为所有其他日子都是连续整周的一部分,每个周都有 5 个工作日。假设您选择前 4 天。然后取第一天的JulianDay模7,然后第一天的JulianDay加1模7,然后第一天的JulianDay加2模7,然后第一天的JulianDay加上 3 模 7,确定其中有多少是工作日,并将其添加到整周的工作日数中。

您只需要一个JulianDay 函数。

【讨论】:

    【解决方案3】:

    这段代码应该做你想做的:

    Date fromDate = new Date(System.currentTimeMillis()-(30L*24*60*60*1000)); // 30 days ago
    Date toDate = new Date(System.currentTimeMillis()); // now
    Calendar cal = Calendar.getInstance();
    cal.setTime(fromDate);
    int countDays = 0;
    while (toDate.compareTo(cal.getTime()) > 0) { 
        if (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY)
            countDays++;
        cal.add(Calendar.DATE, 1);      
    }
    System.out.println(countDays);
    

    【讨论】:

    • 感谢您的回答,但 Siebel 的问题在于,在需要此功能的地方我能做的事情非常有限,因此我没有这些功能的奢侈。只有提到的功能可用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多