【问题标题】:How to create a Bank Calendar with 30 days each month如何创建每月 30 天的银行日历
【发布时间】:2015-04-01 09:42:36
【问题描述】:

为了用德语计算年金贷款,我需要一个每个月正好有 30 天的日历。一年有360天。没有闰年。

利息一律按30天计算(德国利息法)

我正在使用 Java 8。新的 java.time API 有哪些可能性来满足我的要求?

【问题讨论】:

  • 在网上搜索“360 天日历 java”会得到很多结果,虽然不是 java.time 特定的结果
  • 您能否详细说明您的需求。乍一看,您可以使用当月的第一天,然后在 Joda-Time 中调用 plusMonths() 方法(在 java.time 中类似)。将贷款视为一系列月份。两年期贷款只是一个包含 24 个元素的数组。忽略计算中的日期。当您需要第 7 个月的日期时,通过获取原始日期生成一个日期并致电addMonths(7)

标签: calendar java-8 java-time


【解决方案1】:

对于 Java-8,原则上有两个选项可以实现任何日历:

  • 使用接口ChronoLocalDateChronology作为起点
  • 使用接口Temporal

老实说,在您的用例中,这两种选择都是不可行的。使用java.time.chrono-package 的第一个选项会迫使您打扰时代、时代等,这与 360 天日历完全无关。与从头开始实施日历相比,第二个选项过于抽象和简单,无法提供任何剩余价值。

首先要研究文献和互联网,例如极短的Wikipedia。同样重要的是要认识到并考虑到您的设计考虑,这样 360 天的“日历”并不是严格意义上的日历,因为它没有定义从日历日期到儒略日的唯一且双射的映射(几个相同的日期可能属于不同的真实日期!-拒绝使用 chrono-package 的另一个重要原因)。实际结果将仅定义转换/工厂方法,如

Financial360DayCalendar f360 = Financial360DayCalendar.of(LocalDate date);

但不是相反的方向。除了映射/转换问题之外,计算两个此类日期之间的天数是此“日历”中的主要问题。如果你解决了这两个方面,那么你的任务就完成了。除非您需要格式化,否则可能不需要更多的东西。出于格式化目的,您可以考虑实现 Java-8 接口 TemporalAccessor

一个(不完整的)想法:

class Financial360DayCalendar {
  private final int year;
  private final int month;
  private final int dayOfMonth;

  private Financial360DayCalendar(int year, int month, int dayOfMonth) {
    this.year = year;
    this.month = month;
    this.dayOfMonth = dayOfMonth;
  }

  public static Financial360DayCalendar of(LocalDate date) {
    int year = date.getYear();
    int month = date.getMonthValue();
    int dayOfMonth = date.getDayOfMonth();

    if (dayOfMonth == 31) {
      dayOfMonth = 30;
    }

    return new Financial360DayCalendar(year, month, dayOfMonth);
  }

  public int durationInDaysUntil(Financial360DayCalendar other) {
    // check also if other is not before this instance
    // ...
    // special algorithm (handling all intervening months as 30 days long)
    int interestDays = 30 - this.dayOfMonth(); // current day excluded
    int monthDelta = other.getMonthCount() - this.getMonthCount();
    if (monthDelta > 0) {
      monthDelta--;
    }
    interestDays += (30 * monthDelta + other.dayOfMonth);
    return interestDays;
  }

  public double getYearFraction(Financial360DayCalendar other) {
    return durationInDaysUntil(other) / 360.0;
  }

  private int getMonthCount() {
    return this.year * 12 + this.month;
  }
}

所以它是一种计算利息的方法,而不是真正的日历系统。也可以参考this website (in German)了解如何计算时长。

【讨论】:

    【解决方案2】:

    您描述的是day count,而不是日历系统。天数是一种将两个日期之间的时间段转换为年份分数的机制。

    OpenGamma 的 Strata 包括 implementations of many day counts,包括 30E/360,这可能是您需要的方法。

    【讨论】:

      【解决方案3】:

      您应该使用标准日历,无需自定义。如果您需要根据每月 30 天计算两个日期之间的天数,请使用以下方法:

      public int calculateDays(Date d1, Date d2) {
      
          int months = 0;
          int days = 0;
      
          months = Months.monthsBetween(new DateTime(d1), new DateTime(d2)).getMonths();
      
          int endOfMonth = d1.getDate() == 31 ? 31 : 30;
      
          if(d1.getDate() > d2.getDate()){
              days = endOfMonth - d1.getDate() + d2.getDate();
          }else{
              days = d2.getDate() - d1.getDate();
          }
          months = months * 30;
          days = months + days;
      
          return days;
      }
      

      我使用 JodaTime 来简化实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-11
        • 2015-03-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多