きり丸の技術日記

技術検証したり、資格等をここに残していきます。

Rubyで法律に従った暦による期間計算(日割りにならない1ヵ月を求める)

以前、法律に従った暦上の計算方法を記事にし、Javaでも同様の記事を作成しました。

当記事ではRubyで法律に従った暦による期間の計算を求める方法を記します。

環境

  • Ruby
    • 3.0.2p107
  • Rails
    • 6.0.3.7
  • RSpec

対応

テストデータとロジックに関してはJavaと同じです。

Rubyらしい書き方をしているだけで、新規の内容はありません。テストコードもParameterizedTestを使用していますが、あまり面白いことはしていないので特に記載しません。

beginning_of_month?のような、月初、月末であることがわかるメソッドがあればもうちょっと綺麗に書けるとは思うのですが…。そういうメソッドが生えていない以上、泥臭い書き方なのは仕方ないです。

# contractDate(契約日):datetime
# expireDate(解約日):datetime
class Contract
  attr_reader :contractDate
  attr_reader :expireDate

  def initialize(contractDate, expireDate)
    @contractDate = contractDate
    @expireDate = expireDate
  end

  ##
  # 解約可能か
  # 日割とはならない契約日と解約日の関係であること
  #
  # @see https://nainaistar.hatenablog.com/entry/2021/05/02/120000
  def canExpire?
    return true if canExpireByStartOfMonth?
    return true if canExpireByHasEndOfMonth?
    canExpireByHasNotEndOfMonth?
  end

  private

  ##
  # 月の初日から起算する場合は、最終月の末日
  #
  def canExpireByStartOfMonth?
    return expireDate.next_day(1).day == 1 if contractDate.day == 1

    false
  end

  ##
  # 月の途中から起算し,最終月に応当日のある場合は、最終月の応当日の前日
  # -1日すると、月を跨ぐ可能性があるのでNG
  #
  def canExpireByHasEndOfMonth?
    contractDate.day == expireDate.next_day(1).day
  end

  ##
  # 月の途中から起算し,最終月に応当日のない場合は、最終月の末日
  #
  def canExpireByHasNotEndOfMonth?
    return expireDate.next_day(1).day == 1 if contractDate.day > expireDate.day

    false
  end
end

ソースコード

終わりに

Javaよりも書きやすいですね。ただ、後置ifを多用してしまっているので、ちょっとわかりづらくなっている気もします。

Publicメソッドの後置ifはともかく、Privateメソッドの後置ifはやめておいた方がいいかもしれません。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考情報

関連情報