class CalendariumRomanum::Transfers
{Calendar} component. Resolves transfers of conflicting solemnities.
For any day {Temporale} has a {Celebration}. Often {Sanctorale} has one (or more), too. {Calendar} handles these conflicts, in most cases by throwing away all the proposed {Celebration}s except of the one of highest rank. But when there are two conflicting solemnities, one is celebrated on the given day and the less lucky one must be transferred to another day. However, not all days are valid as targets of solemnity transfer. This class handles the logic of transferring impeded solemnities to suitable dates.
Public Class Methods
Resolves any conflict between temporale and sanctorale solemnities by deciding which of the conflicting solemnities is to take the original date, which is to be transferred, and specifying a date for both of them in the resulting Hash.
@param temporale [Temporale] @param sanctorale [Sanctorale] @return [Hash<Date=>Celebration>]
# File lib/calendarium-romanum/transfers.rb, line 34 def self.call(temporale, sanctorale) new(temporale, sanctorale).call end
@param temporale [Temporale] @param sanctorale [Sanctorale] @api private
# File lib/calendarium-romanum/transfers.rb, line 21 def initialize(temporale, sanctorale) @temporale = temporale @sanctorale = sanctorale end
Public Instance Methods
@return [Hash<Date=>Celebration>] @api private
# File lib/calendarium-romanum/transfers.rb, line 40 def call @transferred = {} dates = @sanctorale.solemnities.keys.collect do |abstract_date| concretize_abstract_date abstract_date end.sort dates.each do |date| tc = @temporale[date] next unless tc.solemnity? sc = @sanctorale[date].first next unless sc && sc.solemnity? loser, winner = [sc, tc].sort_by(&:rank) transfer_to = if loser.symbol == :annunciation && in_holy_week?(date) monday_easter2 = @temporale.easter_sunday + 8 valid_destination?(monday_easter2) ? monday_easter2 : free_day_closest_to(monday_easter2) else free_day_closest_to(date) end @transferred[transfer_to] = loser # primary celebrations have noone to be beaten by, no need to harden their dates @transferred[date] = winner unless winner.rank == Ranks::PRIMARY end @transferred end
Private Instance Methods
Converts an AbstractDate
to a Date in the given liturgical year.
# File lib/calendarium-romanum/transfers.rb, line 85 def concretize_abstract_date(abstract_date) year = @temporale.year d = abstract_date.concretize(year + 1) d_prev = abstract_date.concretize(year) if @temporale.date_range.include? d if @temporale.date_range.include?(d_prev) raise RuntimeError.new("Ambiguous case, #{abstract_date} twice in liturgical year #{year}") end d else d_prev end end
# File lib/calendarium-romanum/transfers.rb, line 105 def dates_around(date) return to_enum(__method__, date) unless block_given? 1.upto(100) do |i| yield date + i yield date - i end raise 'this point should never be reached' end
# File lib/calendarium-romanum/transfers.rb, line 101 def free_day_closest_to(date) dates_around(date).find {|d| valid_destination?(d) } end
# File lib/calendarium-romanum/transfers.rb, line 116 def in_holy_week?(date) holy_week = (@temporale.palm_sunday .. @temporale.easter_sunday) holy_week.include? date end
# File lib/calendarium-romanum/transfers.rb, line 73 def valid_destination?(date) return false if @transferred.has_key? date return false if @temporale[date].rank >= Ranks::FEAST_PROPER sc = @sanctorale[date] return false if sc.size > 0 && sc.first.rank >= Ranks::FEAST_PROPER true end