【问题标题】:Calculate month difference in Joda Time计算 Joda Time 的月差
【发布时间】:2011-10-14 05:11:59
【问题描述】:

在第 4 行代码(忽略空格和 cmets)及之后,我正在计算 2 个日期之间的月差。这可行,但看起来有点hacky。有没有更好的办法?

int handleAllowance(LocalDate today) {

    int allowance = membership.allowance();
    if (allowance == 0) return 0;

    // if update was last month (or earlier)
    int months = today.monthOfYear().getMaximumValue() - today.monthOfYear().getMinimumValue(); // yeah, 12, but just to be 100% correct :-)
    int curMonth = (today.getYear()               * months) + today.              getMonthOfYear();
    int updMonth = (lastAllowanceUpdate.getYear() * months) + lastAllowanceUpdate.getMonthOfYear();
    if (curMonth > updMonth) {

        // ...and if today is on or past update day
        int updateDay = Math.min(allowanceDay, today.dayOfMonth().getMaximumValue());
        if (today.getDayOfMonth() >= updateDay) {

            // number of months to give allowance (in the rare case this process fails to run for 2 months or more)
            int allowanceMonths = curMonth - updMonth;

            // give credits
            final int totalAllowance = allowance * allowanceMonths;
            giveCredits(totalAllowance);

            // update day
            lastAllowanceUpdate = lastAllowanceUpdate.plusMonths(allowanceMonths);

            // return the allowance given
            return totalAllowance;

        }

    }

    return 0;
}

【问题讨论】:

  • 一个问题,虽然题外话:allowance 是常量吗?如果没有,final int totalAllowance = allowance * allowanceMonths; 可能会为 allowanceMonths > 1 产生不同的结果,而不是运行整个部分 allowanceMonths 次。
  • 定义常量。它的值取决于用户的订阅类型,在这 2 个月的时间里可能会发生变化。但它不会以任何其他方式改变。因此,我想如果该过程未能运行 2 个月并且用户决定在它再次运行的前一天升级订阅,他会获得比预期更多的津贴。不过没关系,这不是致命错误,allowanceMonths 不太可能真的大于 1
  • 对于常量,我的意思是“两次运行之间的值是否会发生变化,结果是否取决于学分或类似情况”?由于您似乎有固定的津贴(除非用户更改订阅类型),这可能没问题。您也可以每个月都这样做,并让每个月的订阅类型更准确。
  • @Thomas:我可以,但目前无法找到用户过去的订阅,也不值得为此付出努力。

标签: java date jodatime datediff


【解决方案1】:
Months.monthsBetween(
     start.withDayOfMonth(1),
     end.withDayOfMonth(1)).getMonths()

【讨论】:

  • 如果 date1 是 1 月 31 日并且 date2 是 2 月 1 日,那不会返回 0 吗?我基本上需要丢弃日期信息,然后计算差异......哦,等等,我就是这样做的。 :p
  • 我将我的解决方案发布为答案
  • 我用这个得到了这个org.joda.time.IllegalFieldValueException: Value 0 for dayOfMonth must be in the range [1,28]
  • @zeddarn 是的。在 Yoda Time 中,月份从 1(天数)开始,而不是 Calendar 0。如果您从 Calendar 传递到 Yoda,请记住添加 +1
【解决方案2】:

这是我在评论博卓时想到的解决方案

int handleAllowance(LocalDate today) {

    int allowance = membership.allowance();
    if (allowance == 0) return 0;

    // calculate month difference
    int allowanceMonths = Months.monthsBetween(lastAllowanceUpdate.withDayOfMonth(1), today.withDayOfMonth(1)).getMonths();

    // if update was last month or earlier
    if (allowanceMonths > 0) {

        // ...and if today is on or past update day
        int updateDay = Math.min(allowanceDay, today.dayOfMonth().getMaximumValue());
        if (today.getDayOfMonth() >= updateDay) {

            // give credits (multiply with months in the rare case this process consecutively fails to run for 2 months or more)
            final int totalAllowance = allowance * allowanceMonths;
            giveCredits(totalAllowance);

            // update day
            lastAllowanceUpdate = lastAllowanceUpdate.plusMonths(allowanceMonths);

            // return the allowance given
            return totalAllowance;

        }

    }

    return 0;
}

【讨论】:

    【解决方案3】:

    这与 Bozho 的解决方案非常相似:

      public static YearMonth toYearMonth(LocalDate localDate) {
        return new YearMonth(localDate.getYear(), localDate.getMonthOfYear());
      }
    
      public static int monthSwitches(LocalDate date1,LocalDate date2) {
        return Months.monthsBetween(toYearMonth(date1),toYearMonth(date2)).getMonths();
      }
    

    【讨论】:

    • 此解决方案适用于“29/01/2016”和“01/02/2016”等场景!
    猜你喜欢
    • 1970-01-01
    • 2016-04-18
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 2021-04-08
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多