【问题标题】:Exclude 29 February from time interval从时间间隔中排除 2 月 29 日
【发布时间】:2012-09-18 10:34:09
【问题描述】:

我想从计算两个日期之间的完整天数中排除 2 月 29 日。排除区间的角值。

测试场景:

1 March 2012 - 28th February 2012  = should give 0 days.
1 March 2012 - 26th February 2012  = should give 2 days.
1 March 2013 - 28th February 2012  = should give 365 days and not 366 days.
1 March 2017 - 28th February 2012  = should give 365*5 =1825 days and not 1827 days.

目前我解析年份并检查日期之间是否有闰年,然后检查间隔是否为 2 月 29 日。如果间隔跨越多年,有没有办法计算任何特定间隔是否有特定的日期和发生次数。

【问题讨论】:

  • 出于兴趣,为什么要排除 2 月 29 日?
  • @peter-lawrey 我正在为一家保险公司编写代码,他们的政策是在 2 月 29 日不收取保费,以防退保或按比例分配。

标签: java date jodatime


【解决方案1】:

以下 Java 风格的伪代码应该可以工作。如果您愿意,它还允许您添加其他过滤器:

int daysExcludingLeapYearDay(Date start, Date end)
{
    if(end.isBefore(start))
    {
        return filterOutLeapYearDays(daysBetween(end, start)).size();
    }

    return filterOutLeapYearDays(daysBetween(start, end)).size();
}

List<Date> filterOutLeapYearDays(List<Date> days)
{
    List<Date> daysExcludingLeapYearDays = 
             days
             .filter(d -> !isFeb29(d))
             .toList());

    return daysExcludingLeapYearDays;
}

List<Date> daysBetween(Date start, Date end) 
{
    List<Date> days = new List();

    for (Date day = start; day.isBefore(end); day = day.plusOneDay()) 
    {
        days.add(day);
    }

    return days
}

boolean isFeb29(Date date) 
{
    return date.month == FEBRUARY && date.day == 29;
}

【讨论】:

    【解决方案2】:

    但这不是 2 月 29 日引起的,是的。

    如果您比较 2012 年 3 月 1 日和 2012 年 2 月 28 日将返回 1 天,而 29th 将返回 2 天。这两个日期之间的差异是一天。

    要返回 0 天,您应该比较两个相同的日期,例如 2012 年 3 月 1 日和 2012 年 3 月 1 日。

    我认为你误会了^^。

    【讨论】:

    • 我说的是两个日期之间的完整天数,不包括结束日期。为了更清楚,我会更新问题。
    • 嗯,我不知道这是否可能,但是如果您将年份更改为 1900,例如只是为了比较两个日期?
    【解决方案3】:

    我听说过 360 天年,但这是我第一次遇到 365 天年。

    最好的办法是以天为单位计算日期之间的差异,然后减去您遇到的所有 2 月 29 日。

    这意味着您需要一个例程来遍历您的日期范围并返回您遇到的 2 月 29 日的计数。

    我不知道如何在 JodaTime 中做到这一点,但基本算法是

    • 将开始日期转换为自 1970 年 1 月 1 日以来的天数。
    • 将结束日期转换为自 1970 年 1 月 1 日以来的天数。
    • 从开始日循环到结束日,一次一天。
    • 将循环日转换回日期。
    • 如果日期是 2 月 29 日,则计数器加 1
    • 完成循环后,返回计数器。

    【讨论】:

      【解决方案4】:

      使用 javascript,您可以按如下方式实现,其中 startDateendDate 是 javascript Date 对象。

      function calculateDays(startDate,endDate){
          var oneDay = 86400000; //ms per day
          var difference = Math.ceil((endDate.getTime() - startDate.getTime()) / oneDay); 
          var totFeb29s = findTotalFeb29s(startDate,endDate);
          return  parseInt(difference)+parseInt(1)-parseInt(totFeb29s);    
      }    
      function findTotalFeb29s(startDate,endDate){
          var totalFeb29s = 0;
          var startYear = startDate.getFullYear();
          var endYear = endDate.getFullYear();
          for(var year=startYear;year<=endYear;year++){
              var dt = new Date(year, 1, 29);
              var isLeap = dt.getMonth() == 1;
              if(isLeap==true && startDate<=dt && dt<=endDate){
                 totalFeb29s = parseInt(totalFeb29s)+parseInt(1);
              }
          }
          return totalFeb29s;
      }    
      

      【讨论】:

      • 为什么要提供 javascript 答案?这个问题不问这个。
      猜你喜欢
      • 2023-02-15
      • 2022-09-22
      • 1970-01-01
      • 1970-01-01
      • 2012-03-21
      • 2020-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多