Open1

Rubyで学校年度を扱う

__

学校年度のクラスを用意すると便利

require 'date'

SchoolYear = Data.define(:year, :begin_month, :begin_day)

class SchoolYear
  include Comparable
  include Enumerable

  DEFAULT_BEGIN_DAY = 1
  DEFAULT_BEGIN_MONTH = 4
  private_constant :DEFAULT_BEGIN_DAY, :DEFAULT_BEGIN_MONTH

  def self.now(begin_day: DEFAULT_BEGIN_DAY, begin_month: DEFAULT_BEGIN_MONTH)
    of(Time.now, begin_day:, begin_month:)
  end

  def self.of(date, begin_day: DEFAULT_BEGIN_DAY, begin_month: DEFAULT_BEGIN_MONTH)
    if begin_month > date.month || begin_day > date.day
      new(begin_day:, begin_month:, year: date.year - 1)
    else
      new(begin_day:, begin_month:, year: date.year)
    end
  end

  def initialize(begin_day: DEFAULT_BEGIN_DAY, begin_month: DEFAULT_BEGIN_MONTH, **) = super(begin_day:, begin_month:, **)
  def +(n) = self.class.new(begin_day:, begin_month:, year: year + n)
  def -(n) = self.class.new(begin_day:, begin_month:, year: year - n)
  def <=>(other) = begin_on <=> other.begin_on
  def begin_on = Date.new(year, begin_month, begin_day)
  def date_range = begin_on..end_on
  def each(...) = date_range.each(...)
  def end_on = self.next.begin_on.prev_day
  def next = self.class.new(begin_day:, begin_month:, year: next_year)
  def next_year = year + 1
  def prev = self.class.new(begin_day:, begin_month:, year: prev_year)
  def prev_year = year - 1
  def to_i = year
  def to_s = "#{year}年度"
end