simanのブログ

ゆるふわプログラマー。競技プログラミングやってます。Ruby好き

Rubyで日本の祝日を表示してくれるgem「holiday_jp」

Rubyで日本の休日を表示してくれるものを探していたら「holiday_jp」を見つけました。

http://docs.komagata.org/tags/holiday_jp/

使い方はこんな感じです(githubのUSAGE参照)

holidays = HolidayJp.between(Date.new(2010, 9, 14), Date.new(2010, 9, 21))
holidays.first.name # 敬老の日

holidaysには「HolidayJp.between」で指定した日付の範囲にある祝日のリストが返ってきます。

すごく便利です。

holiday_jpの中身をみる

内部の動作としては「holidays.rb」に下記のように祝日の名前と日付のデータが用意されています。(なんと2050年まで!)

    ["2013-07-15","海の日"],
    ["2013-09-16","敬老の日"],
    ["2013-09-23","秋分の日"],
               .
               .
               .
    ["2050-11-03","文化の日"],
    ["2050-11-23","勤労感謝の日"],
    ["2050-12-23","天皇誕生日"],

このデータをハッシュ化したものをHOLIDAYSに入れています。(keyはDate, valueはHolidayのインスタンス)

 HOLIDAYS = Hash[base_holidays.map {|e| [(h = Holiday.new(*e)).date, h]}]

そしてこのHOLIDAYSに入っている情報をholiday_jp.rb内でゴニョゴニョすることで色々なことができるようになります。

初期のholiday_jpではbetweenとholiday?メソッドが用意されていました。

  def self.between(start, last)
    HOLIDAYS.find_all do |date, holiday|
      start <= date && date <= last
    end.map(&:last)
  end

  def self.holiday?(date)
    !HOLIDAYS[date].nil?
  end

holiday?メソッドは引数で与えた日付が祝日かどうかをチェックするメソッドです。


色々メソッドを追加してみる。

このholiday_jpに自分で思いついたメソッドを3つぐらい追加してみました。


holiday_countメソッド

引数で与えた年の祝日の数を返してくれるメソッド。

  # その年の祝日の数を返してくれる
  def self.holiday_count(year)
    HOLIDAYS.count do |date, holiday|
      Date.new(year, 1, 1) <= date && date <= Date.new(year, 12, 31)
    end
  end

Array.countを使えば簡単でした。

使用例

puts "2013年の祝日の数は#{HolidayJp.holiday_count(2013)}個です。"
2013年の祝日の数は17個です。



next_holidayメソッド

引数で与えた日付から一番近い祝日を返してくれるメソッドです。

  def self.next_holiday(day)
    HOLIDAYS.find do |date, holiday|
      day < date
    end.last
  end

RubyのArray.findでは一番最初に条件に一致した要素を返すのでこういった書き方ができます。

使用例

next_holiday = HolidayJp.next_holiday(Date.today)
puts "次の祝日は「#{next_holiday.name}」で、日付は「#{next_holiday.date}」となっています。"
次の祝日は「海の日」で、日付は「2013-07-15」となっています。



after_holidaysメソッド

与えた引数の日付以降の祝日リストをlazyで返しています。

  def self.after_holidays(day)
    HOLIDAYS.find_all do |date, holiday|
      day < date
    end.map(&:last).lazy
  end

特に使い道は決めていないです。

使用例

after_holidays = HolidayJp.after_holidays(Date.today)

3.times do
  holiday = after_holidays.next
  puts "#{holiday.name}」「#{holiday.date}"
end
「海の日」「2013-07-15」
「敬老の日」「2013-09-16」
「秋分の日」「2013-09-23」