calendarium-romanum 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/config/locales/cs.yml +37 -1
  3. data/config/locales/en.yml +37 -1
  4. data/config/locales/it.yml +36 -2
  5. data/config/locales/la.yml +35 -1
  6. data/data/README.md +62 -4
  7. data/data/czech-brno-cs.txt +10 -2
  8. data/data/czech-budejovice-cs.txt +10 -2
  9. data/data/czech-cechy-cs.txt +9 -2
  10. data/data/czech-cs.txt +7 -1
  11. data/data/czech-hradec-cs.txt +10 -2
  12. data/data/czech-litomerice-cs.txt +10 -2
  13. data/data/czech-morava-cs.txt +9 -2
  14. data/data/czech-olomouc-cs.txt +10 -2
  15. data/data/czech-ostrava-cs.txt +10 -2
  16. data/data/czech-plzen-cs.txt +10 -2
  17. data/data/czech-praha-cs.txt +10 -2
  18. data/data/universal-en.txt +4 -1
  19. data/data/universal-it.txt +4 -1
  20. data/data/universal-la.txt +4 -1
  21. data/lib/calendarium-romanum.rb +3 -0
  22. data/lib/calendarium-romanum/calendar.rb +13 -6
  23. data/lib/calendarium-romanum/data.rb +1 -1
  24. data/lib/calendarium-romanum/day.rb +0 -3
  25. data/lib/calendarium-romanum/enums.rb +41 -21
  26. data/lib/calendarium-romanum/ordinalizer.rb +37 -0
  27. data/lib/calendarium-romanum/sanctoraleloader.rb +13 -2
  28. data/lib/calendarium-romanum/temporale.rb +145 -232
  29. data/lib/calendarium-romanum/temporale/dates.rb +151 -0
  30. data/lib/calendarium-romanum/temporale/extensions/christ_eternal_priest.rb +25 -0
  31. data/lib/calendarium-romanum/transfers.rb +23 -5
  32. data/lib/calendarium-romanum/version.rb +1 -1
  33. data/spec/calendar_spec.rb +72 -19
  34. data/spec/dates_spec.rb +45 -0
  35. data/spec/rank_spec.rb +2 -2
  36. data/spec/readme_spec.rb +11 -9
  37. data/spec/spec_helper.rb +16 -1
  38. data/spec/temporale_spec.rb +252 -126
  39. metadata +19 -1
@@ -1,5 +1,13 @@
1
- # Czech Republic
2
- # diocese of Plzeň
1
+ ---
2
+ title: kalendář plzeňské diecéze
3
+ description: Calendar for diocese of Plzeň, Czech Republic
4
+ locale: cs
5
+ country: cz
6
+ diocese: Plzeň
7
+ extends:
8
+ - czech-cs.txt
9
+ - czech-cechy-cs.txt
10
+ ---
3
11
 
4
12
  7/14 f2.8 R : Bl. Hroznaty, mučedníka, hlavního patrona diecéze
5
13
 
@@ -1,4 +1,12 @@
1
- # Czech Republic
2
- # archdiocese of Prague
1
+ ---
2
+ title: kalendář pražské arcidiecéze
3
+ description: Calendar for archdiocese of Prague, Czech Republic
4
+ locale: cs
5
+ country: cz
6
+ diocese: Praha
7
+ extends:
8
+ - czech-cs.txt
9
+ - czech-cechy-cs.txt
10
+ ---
3
11
 
4
12
  5/12 f2.8 : Výročí posvěcení katedrály sv. Víta, Václava a Vojtěcha
@@ -1,5 +1,8 @@
1
- # General Roman Calendar in English
1
+ ---
2
+ title: General Roman Calendar
3
+ locale: en
2
4
  # source: https://en.wikipedia.org/wiki/General_Roman_Calendar
5
+ ---
3
6
 
4
7
  = 1
5
8
  2 m : Saints Basil the Great and Gregory Nazianzen, bishops and doctors
@@ -1,4 +1,7 @@
1
- # Calendario Romano Generale
1
+ ---
2
+ title: Calendario Romano Generale
3
+ locale: it
4
+ ---
2
5
 
3
6
  = 1
4
7
  2 m : Santi Basilio Magno e Gregorio Nazianzeno, vescovi e dottori della Chiesa
@@ -1,5 +1,8 @@
1
- # General Roman Calendar in Latin
1
+ ---
2
+ title: Calendarium Romanum Generale
3
+ locale: la
2
4
  # source: http://www.binetti.ru/collectio/liturgia/missale_files/crg.htm
5
+ ---
3
6
 
4
7
  = 1
5
8
  2 m : Ss. Basilii et Gregorii Nazianzeni, episcoporum et Ecclesiae doctorum
@@ -7,6 +7,8 @@ enums
7
7
  data
8
8
  calendar
9
9
  temporale
10
+ temporale/dates
11
+ temporale/extensions/christ_eternal_priest
10
12
  sanctorale
11
13
  sanctoraleloader
12
14
  sanctorale_factory
@@ -14,6 +16,7 @@ transfers
14
16
  day
15
17
  abstract_date
16
18
  util
19
+ ordinalizer
17
20
  }.each do |f|
18
21
  require_relative File.join('calendarium-romanum', f)
19
22
  end
@@ -12,10 +12,11 @@ module CalendariumRomanum
12
12
  # year: Integer
13
13
  # returns a calendar for the liturgical year beginning with
14
14
  # Advent of the specified civil year.
15
- def initialize(year, sanctorale=nil)
15
+ def initialize(year, sanctorale=nil, temporale_class=nil)
16
16
  @year = year
17
- @temporale = Temporale.new(year)
18
17
  @sanctorale = sanctorale || Sanctorale.new
18
+ @temporale_class = temporale_class || Temporale
19
+ @temporale = @temporale_class.new(year)
19
20
  @transferred = Transfers.new(@temporale, @sanctorale)
20
21
  end
21
22
 
@@ -45,8 +46,8 @@ module CalendariumRomanum
45
46
 
46
47
  # creates a Calendar for the liturgical year including given
47
48
  # date
48
- def for_day(date, sanctorale=nil)
49
- return new(Temporale.liturgical_year(date), sanctorale)
49
+ def for_day(date, *constructor_args)
50
+ return new(Temporale.liturgical_year(date), *constructor_args)
50
51
  end
51
52
  end # class << self
52
53
 
@@ -57,13 +58,13 @@ module CalendariumRomanum
57
58
 
58
59
  # returns a Calendar for the subsequent year
59
60
  def succ
60
- c = Calendar.new @year + 1, @sanctorale
61
+ c = Calendar.new @year + 1, @sanctorale, @temporale_class
61
62
  return c
62
63
  end
63
64
 
64
65
  # returns a Calendar for the previous year
65
66
  def pred
66
- c = Calendar.new @year - 1, @sanctorale
67
+ c = Calendar.new @year - 1, @sanctorale, @temporale_class
67
68
  return c
68
69
  end
69
70
 
@@ -124,6 +125,12 @@ module CalendariumRomanum
124
125
  else
125
126
  return st
126
127
  end
128
+ elsif t.rank == Ranks::FERIAL_PRIVILEGED && st.first.rank.memorial?
129
+ st = st.collect do |c|
130
+ Celebration.new(c.title, Ranks::COMMEMORATION, t.colour)
131
+ end
132
+ st.unshift t
133
+ return st
127
134
  end
128
135
  end
129
136
 
@@ -1,5 +1,5 @@
1
1
  module CalendariumRomanum
2
- # allows easy access to the bundled data files
2
+ # allows easy access to bundled data files
3
3
  class Data < Enum
4
4
 
5
5
  class SanctoraleFile
@@ -30,9 +30,6 @@ module CalendariumRomanum
30
30
 
31
31
  # an Array of Celebrations, possibly empty
32
32
  attr_reader :celebrations
33
-
34
- # Celebration of the following day if it has first vespers
35
- attr_reader :vespers
36
33
  end
37
34
 
38
35
  # information on one particular celebration of the liturgical year
@@ -1,15 +1,45 @@
1
1
  module CalendariumRomanum
2
2
 
3
+ class Colour
4
+ def initialize(symbol)
5
+ @symbol = symbol
6
+ end
7
+
8
+ attr_reader :symbol
9
+ alias to_sym symbol
10
+ end
11
+
12
+ class Colours < Enum
13
+ values do
14
+ [
15
+ GREEN = Colour.new(:green),
16
+ VIOLET = Colour.new(:violet),
17
+ WHITE = Colour.new(:white),
18
+ RED = Colour.new(:red)
19
+ ]
20
+ end
21
+ end
22
+
23
+ Colors = Colours
24
+
25
+ class Season
26
+ def initialize(symbol, colour)
27
+ @symbol = symbol
28
+ @colour = colour
29
+ end
30
+
31
+ attr_reader :symbol, :colour
32
+ alias to_sym symbol
33
+ end
34
+
3
35
  class Seasons < Enum
4
36
  values do
5
37
  [
6
- ADVENT = :advent,
7
- CHRISTMAS = :christmas,
8
- LENT = :lent,
9
- EASTER = :easter,
10
- ORDINARY = :ordinary,
11
- # is Triduum Sacrum a special season? For now I count Friday and Saturday
12
- # to the Lent, Sunday to the Easter time
38
+ ADVENT = Season.new(:advent, Colours::VIOLET),
39
+ CHRISTMAS = Season.new(:christmas, Colours::WHITE),
40
+ LENT = Season.new(:lent, Colours::VIOLET),
41
+ EASTER = Season.new(:easter, Colours::WHITE),
42
+ ORDINARY = Season.new(:ordinary, Colours::GREEN)
13
43
  ]
14
44
  end
15
45
  end
@@ -37,21 +67,11 @@ module CalendariumRomanum
37
67
  MEMORIAL_GENERAL = Rank.new(3.10, 'rank.3_10', 'rank.short.memorial'),
38
68
  MEMORIAL_PROPER = Rank.new(3.11, 'rank.3_11', 'rank.short.memorial'),
39
69
  MEMORIAL_OPTIONAL = Rank.new(3.12, 'rank.3_12', 'rank.short.memorial_opt'),
40
- FERIAL = Rank.new(3.13, 'rank.3_13', 'rank.short.ferial')
70
+ FERIAL = Rank.new(3.13, 'rank.3_13', 'rank.short.ferial'),
71
+ # not included as a celebration rank on it's own
72
+ # in the Table of Liturgical Days
73
+ COMMEMORATION = Rank.new(4.0, 'rank.4_0', 'rank.short.commemoration')
41
74
  ]
42
75
  end
43
76
  end
44
-
45
- class Colours < Enum
46
- values do
47
- [
48
- GREEN = :green,
49
- VIOLET = :violet,
50
- WHITE = :white,
51
- RED = :red
52
- ]
53
- end
54
- end
55
-
56
- Colors = Colours
57
77
  end
@@ -0,0 +1,37 @@
1
+ require 'roman-numerals'
2
+
3
+ module CalendariumRomanum
4
+ # Knows how to produce localized ordinals
5
+ class Ordinalizer
6
+ class << self
7
+ def ordinal(number, locale: nil)
8
+ locale ||= I18n.locale
9
+
10
+ case locale
11
+ when :cs
12
+ "#{number}."
13
+ when :en
14
+ english_ordinal(number)
15
+ # when :it # TODO
16
+ when :la, :it
17
+ RomanNumerals.to_roman number
18
+ else
19
+ number
20
+ end
21
+ end
22
+
23
+ def english_ordinal(number)
24
+ case number
25
+ when 1
26
+ '1st'
27
+ when 2
28
+ '2nd'
29
+ when 3
30
+ '3rd'
31
+ else
32
+ "#{number}th"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -30,9 +30,20 @@ module CalendariumRomanum
30
30
  def load(src, dest=nil)
31
31
  dest ||= Sanctorale.new
32
32
 
33
+ in_front_matter = false
33
34
  month_section = nil
34
- src.each_line.each_with_index do |l, li|
35
- line_num = li + 1
35
+ src.each_line.with_index(1) do |l, line_num|
36
+ # skip YAML front matter
37
+ if line_num == 1 && l.start_with?('---')
38
+ in_front_matter = true
39
+ next
40
+ elsif in_front_matter
41
+ if l.start_with?('---')
42
+ in_front_matter = false
43
+ end
44
+
45
+ next
46
+ end
36
47
 
37
48
  # strip whitespace and comments
38
49
  l.sub!(/#.*/, '')
@@ -7,21 +7,22 @@ module CalendariumRomanum
7
7
 
8
8
  WEEK = 7
9
9
 
10
- SEASON_COLOUR = {
11
- Seasons::ADVENT => Colours::VIOLET,
12
- Seasons::CHRISTMAS => Colours::WHITE,
13
- Seasons::ORDINARY => Colours::GREEN,
14
- Seasons::LENT => Colours::VIOLET,
15
- Seasons::EASTER => Colours::WHITE,
16
- }
17
-
18
10
  # year is Integer - the civil year when the liturgical year begins
19
- def initialize(year=nil)
11
+ def initialize(year)
20
12
  @year = year
21
- prepare_solemnities unless @year.nil?
13
+ prepare_solemnities
22
14
  end
23
15
 
16
+ attr_reader :year
17
+
24
18
  class << self
19
+ # Creates a subclass with specified extension modules included
20
+ def with_extensions(*extensions)
21
+ Class.new(self) do
22
+ extensions.each {|e| include e }
23
+ end
24
+ end
25
+
25
26
  # Determines liturgical year for the given date
26
27
  def liturgical_year(date)
27
28
  year = date.year
@@ -39,197 +40,106 @@ module CalendariumRomanum
39
40
  def for_day(date)
40
41
  return new(liturgical_year(date))
41
42
  end
42
- end
43
-
44
- def start_date(year=nil)
45
- first_advent_sunday(year)
46
- end
47
-
48
- def end_date(year=nil)
49
- year ||= @year
50
- first_advent_sunday(year+1) - 1
51
- end
52
-
53
- def date_range(year=nil)
54
- start_date(year) .. end_date(year)
55
- end
56
43
 
57
- def range_check(date)
58
- # necessary in order to handle Date correctly
59
- date = date.to_date if date.class != Date
60
-
61
- unless date_range.include? date
62
- raise RangeError.new "Date out of range #{date}"
44
+ C = Struct.new(:date_method, :celebration)
45
+ private_constant :C
46
+
47
+ # implementation detail, not to be touched by client code
48
+ def celebrations
49
+ @celebrations ||=
50
+ begin
51
+ [
52
+ c(:nativity, Ranks::PRIMARY),
53
+ c(:holy_family, Ranks::FEAST_LORD_GENERAL),
54
+ c(:mother_of_god, Ranks::SOLEMNITY_GENERAL),
55
+ c(:epiphany, Ranks::PRIMARY),
56
+ c(:baptism_of_lord, Ranks::FEAST_LORD_GENERAL),
57
+ c(:ash_wednesday, Ranks::PRIMARY, Colours::VIOLET),
58
+ c(:good_friday, Ranks::TRIDUUM, Colours::RED),
59
+ c(:holy_saturday, Ranks::TRIDUUM, Colours::VIOLET),
60
+ c(:palm_sunday, Ranks::PRIMARY, Colours::RED),
61
+ c(:easter_sunday, Ranks::TRIDUUM),
62
+ c(:ascension, Ranks::PRIMARY),
63
+ c(:pentecost, Ranks::PRIMARY, Colours::RED),
64
+ c(:holy_trinity, Ranks::SOLEMNITY_GENERAL),
65
+ c(:body_blood, Ranks::SOLEMNITY_GENERAL),
66
+ c(:sacred_heart, Ranks::SOLEMNITY_GENERAL),
67
+ c(:christ_king, Ranks::SOLEMNITY_GENERAL),
68
+
69
+ # Immaculate Heart of Mary is actually (currently the only one)
70
+ # movable *sanctorale* feast, but as it would make little sense
71
+ # to add support for movable sanctorale feasts because of
72
+ # a single one, we cheat a bit and handle it in temporale.
73
+ c(:immaculate_heart, Ranks::MEMORIAL_GENERAL),
74
+ ]
75
+ end
63
76
  end
64
- end
65
-
66
- # converts an AbstractDate to a Date in the given
67
- # liturgical year
68
- def concretize_abstract_date(abstract_date)
69
- d = abstract_date.concretize(@year + 1)
70
- if date_range.include? d
71
- d
72
- else
73
- abstract_date.concretize(@year)
74
- end
75
- end
76
77
 
77
- def weekday_before(weekday, date)
78
- if date.wday == weekday then
79
- return date - WEEK
80
- elsif weekday < date.wday
81
- return date - (date.wday - weekday)
82
- else
83
- return date - (date.wday + WEEK - weekday)
84
- end
85
- end
86
-
87
- def weekday_after(weekday, date)
88
- if date.wday == weekday then
89
- return date + WEEK
90
- elsif weekday > date.wday
91
- return date + (weekday - date.wday)
92
- else
93
- return date + (WEEK - date.wday + weekday)
94
- end
95
- end
96
-
97
- def octave_of(date)
98
- date + WEEK
99
- end
100
-
101
- WEEKDAYS = %w{sunday monday tuesday wednesday thursday friday saturday}
102
- WEEKDAYS.each_with_index do |weekday, weekday_i|
103
- define_method "#{weekday}_before" do |date|
104
- send('weekday_before', weekday_i, date)
105
- end
106
-
107
- define_method "#{weekday}_after" do |date|
108
- send('weekday_after', weekday_i, date)
109
- end
110
- end
111
-
112
- # first_advent_sunday -> advent_sunday(1)
113
- %w{first second third fourth}.each_with_index do |word,i|
114
- define_method "#{word}_advent_sunday" do |year=nil|
115
- send("advent_sunday", i + 1, year)
116
- end
117
- end
78
+ # Hook point for extensions to add new celebrations
79
+ def add_celebration(date_method, celebration)
80
+ if self == Temporale
81
+ raise RuntimeError.new("Don't add celebrations to Temporale itself, subclass it and modify the subclass.")
82
+ end
118
83
 
119
- def advent_sunday(num, year=nil)
120
- advent_sundays_total = 4
121
- unless (1..advent_sundays_total).include? num
122
- raise ArgumentError.new "Invalid Advent Sunday #{num}"
84
+ celebrations << C.new(date_method, celebration)
123
85
  end
124
86
 
125
- year ||= @year
126
- return sunday_before(nativity(year)) - ((advent_sundays_total - num) * WEEK)
127
- end
87
+ private
128
88
 
129
- def nativity(year=nil)
130
- year ||= @year
131
- return Date.new(year, 12, 25)
132
- end
89
+ def c(date_method, rank, colour=Colours::WHITE)
90
+ title = proc { I18n.t("temporale.solemnity.#{date_method}") }
133
91
 
134
- def holy_family(year=nil)
135
- year ||= @year
136
- xmas = nativity(year)
137
- if xmas.sunday?
138
- return Date.new(year, 12, 30)
139
- else
140
- sunday_after(xmas)
92
+ C.new(
93
+ date_method,
94
+ Celebration.new(title, rank, colour)
95
+ )
141
96
  end
142
97
  end
143
98
 
144
- def mother_of_god(year=nil)
145
- octave_of(nativity(year))
99
+ def start_date
100
+ first_advent_sunday
146
101
  end
147
102
 
148
- def epiphany(year=nil)
149
- year ||= @year
150
- return Date.new(year+1, 1, 6)
103
+ def end_date
104
+ Dates.first_advent_sunday(year+1) - 1
151
105
  end
152
106
 
153
- def baptism_of_lord(year=nil)
154
- year ||= @year
155
- return sunday_after epiphany(year)
107
+ def date_range
108
+ start_date .. end_date
156
109
  end
157
110
 
158
- def ash_wednesday(year=nil)
159
- year ||= @year
160
- return easter_sunday(year) - (6 * WEEK + 4)
161
- end
162
-
163
- def easter_sunday(year=nil)
164
- year ||= @year
165
- year += 1
166
-
167
- # algorithm below taken from the 'easter' gem:
168
- # https://github.com/jrobertson/easter
111
+ def range_check(date)
112
+ # necessary in order to handle Date correctly
113
+ date = date.to_date if date.class != Date
169
114
 
170
- golden_number = (year % 19) + 1
171
- if year <= 1752 then
172
- # Julian calendar
173
- dominical_number = (year + (year / 4) + 5) % 7
174
- paschal_full_moon = (3 - (11 * golden_number) - 7) % 30
175
- else
176
- # Gregorian calendar
177
- dominical_number = (year + (year / 4) - (year / 100) + (year / 400)) % 7
178
- solar_correction = (year - 1600) / 100 - (year - 1600) / 400
179
- lunar_correction = (((year - 1400) / 100) * 8) / 25
180
- paschal_full_moon = (3 - 11 * golden_number + solar_correction - lunar_correction) % 30
181
- end
182
- dominical_number += 7 until dominical_number > 0
183
- paschal_full_moon += 30 until paschal_full_moon > 0
184
- paschal_full_moon -= 1 if paschal_full_moon == 29 or (paschal_full_moon == 28 and golden_number > 11)
185
- difference = (4 - paschal_full_moon - dominical_number) % 7
186
- difference += 7 if difference < 0
187
- day_easter = paschal_full_moon + difference + 1
188
- if day_easter < 11 then
189
- # Easter occurs in March.
190
- return Date.new(y=year, m=3, d=day_easter + 21)
191
- else
192
- # Easter occurs in April.
193
- return Date.new(y=year, m=4, d=day_easter - 10)
115
+ unless date_range.include? date
116
+ raise RangeError.new "Date out of range #{date}"
194
117
  end
195
118
  end
196
119
 
197
- def palm_sunday(year=nil)
198
- return easter_sunday(year) - 7
199
- end
200
-
201
- def good_friday(year=nil)
202
- return easter_sunday(year) - 2
203
- end
204
-
205
- def holy_saturday(year=nil)
206
- return easter_sunday(year) - 1
207
- end
208
-
209
- def ascension(year=nil)
210
- return pentecost(year) - 10
211
- end
212
-
213
- def pentecost(year=nil)
214
- year ||= @year
215
- return easter_sunday(year) + 7 * WEEK
216
- end
217
-
218
- def holy_trinity(year=nil)
219
- sunday_after(pentecost(year))
220
- end
221
-
222
- def body_blood(year=nil)
223
- thursday_after(holy_trinity(year))
224
- end
225
-
226
- def sacred_heart(year=nil)
227
- friday_after(sunday_after(body_blood(year)))
228
- end
229
-
230
- def christ_king(year=nil)
231
- year ||= @year
232
- sunday_before(first_advent_sunday(year + 1))
120
+ %i(
121
+ first_advent_sunday
122
+ nativity
123
+ holy_family
124
+ mother_of_god
125
+ epiphany
126
+ baptism_of_lord
127
+ ash_wednesday
128
+ palm_sunday
129
+ good_friday
130
+ holy_saturday
131
+ easter_sunday
132
+ ascension
133
+ pentecost
134
+ holy_trinity
135
+ body_blood
136
+ sacred_heart
137
+ immaculate_heart
138
+ christ_king
139
+ ).each do |feast|
140
+ define_method feast do
141
+ Dates.public_send feast, year
142
+ end
233
143
  end
234
144
 
235
145
  # which liturgical season is it?
@@ -268,14 +178,14 @@ module CalendariumRomanum
268
178
  when Seasons::EASTER
269
179
  easter_sunday
270
180
  else # ordinary time
271
- monday_after(baptism_of_lord)
181
+ Dates.monday_after(baptism_of_lord)
272
182
  end
273
183
  end
274
184
 
275
185
  def season_week(seasonn, date)
276
186
  week1_beginning = season_beginning = season_beginning(seasonn)
277
187
  unless season_beginning.sunday?
278
- week1_beginning = sunday_after(season_beginning)
188
+ week1_beginning = Dates.sunday_after(season_beginning)
279
189
  end
280
190
 
281
191
  week = date_difference(date, week1_beginning) / Temporale::WEEK + 1
@@ -286,7 +196,7 @@ module CalendariumRomanum
286
196
  week += 1
287
197
 
288
198
  if date > pentecost
289
- weeks_after_date = date_difference(first_advent_sunday(@year + 1), date) / 7
199
+ weeks_after_date = date_difference(Dates.first_advent_sunday(@year + 1), date) / 7
290
200
  week = 34 - weeks_after_date
291
201
  week += 1 if date.sunday?
292
202
  end
@@ -310,44 +220,34 @@ module CalendariumRomanum
310
220
  end
311
221
  end
312
222
 
313
- return solemnity(date) || sunday(date) || ferial(date)
223
+ return @solemnities[date] || @feasts[date] || sunday(date) || @memorials[date] || ferial(date)
314
224
  end
315
225
 
316
226
  private
317
227
 
318
- # the celebration determination split in methods:
319
-
320
- def solemnity(date)
321
- if @solemnities.has_key?(date)
322
- return @solemnities[date]
323
- end
324
-
325
- seas = season(date)
326
- case seas
327
- when Seasons::EASTER
328
- if date <= sunday_after(easter_sunday)
329
- return Celebration.new '', Ranks::PRIMARY, SEASON_COLOUR[seas]
330
- end
331
- end
332
-
333
- return nil
334
- end
228
+ # seasons when Sundays have higher rank
229
+ SEASONS_SUNDAY_PRIMARY = [Seasons::ADVENT, Seasons::LENT, Seasons::EASTER].freeze
335
230
 
336
231
  def sunday(date)
337
232
  return nil unless date.sunday?
338
233
 
339
234
  seas = season date
340
235
  rank = Ranks::SUNDAY_UNPRIVILEGED
341
- if [Seasons::ADVENT, Seasons::LENT, Seasons::EASTER].include?(seas)
236
+ if SEASONS_SUNDAY_PRIMARY.include?(seas)
342
237
  rank = Ranks::PRIMARY
343
238
  end
344
239
 
345
- return Celebration.new '', rank, SEASON_COLOUR[seas]
240
+ week = Ordinalizer.ordinal season_week(seas, date)
241
+ title = I18n.t "temporale.#{seas.to_sym}.sunday", week: week
242
+
243
+ return Celebration.new title, rank, seas.colour
346
244
  end
347
245
 
348
246
  def ferial(date)
349
247
  seas = season date
248
+ week = season_week(seas, date)
350
249
  rank = Ranks::FERIAL
250
+ title = nil
351
251
  case seas
352
252
  when Seasons::ADVENT
353
253
  if date >= Date.new(@year, 12, 17)
@@ -356,12 +256,31 @@ module CalendariumRomanum
356
256
  when Seasons::CHRISTMAS
357
257
  if date < mother_of_god
358
258
  rank = Ranks::FERIAL_PRIVILEGED
259
+
260
+ nth = Ordinalizer.ordinal(date.day - nativity.day + 1) # 1-based counting
261
+ title = I18n.t 'temporale.christmas.nativity_octave.ferial', day: nth
262
+ elsif date > epiphany
263
+ title = I18n.t "temporale.christmas.after_epiphany.ferial", weekday: I18n.t("weekday.#{date.wday}")
359
264
  end
360
265
  when Seasons::LENT
361
- rank = Ranks::FERIAL_PRIVILEGED
266
+ if week == 0
267
+ title = I18n.t "temporale.lent.after_ashes.ferial", weekday: I18n.t("weekday.#{date.wday}")
268
+ elsif date > palm_sunday
269
+ rank = Ranks::PRIMARY
270
+ title = I18n.t "temporale.lent.holy_week.ferial", weekday: I18n.t("weekday.#{date.wday}")
271
+ end
272
+ rank = Ranks::FERIAL_PRIVILEGED unless rank > Ranks::FERIAL_PRIVILEGED
273
+ when Seasons::EASTER
274
+ if week == 1
275
+ rank = Ranks::PRIMARY
276
+ title = I18n.t "temporale.easter.octave.ferial", weekday: I18n.t("weekday.#{date.wday}")
277
+ end
362
278
  end
363
279
 
364
- return Celebration.new '', rank, SEASON_COLOUR[seas]
280
+ week_ord = Ordinalizer.ordinal week
281
+ title ||= I18n.t "temporale.#{seas.to_sym}.ferial", week: week_ord, weekday: I18n.t("weekday.#{date.wday}")
282
+
283
+ return Celebration.new title, rank, seas.colour
365
284
  end
366
285
 
367
286
  # helper: difference between two Dates in days
@@ -369,35 +288,29 @@ module CalendariumRomanum
369
288
  return (d1 - d2).numerator
370
289
  end
371
290
 
372
- # prepare dates of temporale solemnities and their octaves
291
+ # prepare dates of temporale solemnities
373
292
  def prepare_solemnities
374
293
  @solemnities = {}
375
-
376
- {
377
- nativity: [Ranks::PRIMARY, nil],
378
- holy_family: [Ranks::FEAST_LORD_GENERAL, nil],
379
- mother_of_god: [Ranks::SOLEMNITY_GENERAL],
380
- epiphany: [Ranks::PRIMARY, nil],
381
- baptism_of_lord: [Ranks::FEAST_LORD_GENERAL, nil],
382
- ash_wednesday: [Ranks::PRIMARY, nil],
383
- good_friday: [Ranks::TRIDUUM, Colours::RED],
384
- holy_saturday: [Ranks::TRIDUUM, nil],
385
- palm_sunday: [Ranks::PRIMARY, Colours::RED],
386
- easter_sunday: [Ranks::TRIDUUM, nil],
387
- ascension: [Ranks::PRIMARY, Colours::WHITE],
388
- pentecost: [Ranks::PRIMARY, Colours::RED],
389
- holy_trinity: [Ranks::SOLEMNITY_GENERAL, Colours::WHITE],
390
- body_blood: [Ranks::SOLEMNITY_GENERAL, Colours::WHITE],
391
- sacred_heart: [Ranks::SOLEMNITY_GENERAL, Colours::WHITE],
392
- christ_king: [Ranks::SOLEMNITY_GENERAL, Colours::WHITE],
393
- }.each_pair do |method_name, data|
394
- date = send(method_name)
395
- rank, colour = data
396
- @solemnities[date] = Celebration.new(
397
- proc { I18n.t("temporale.solemnity.#{method_name}") },
398
- rank,
399
- colour || SEASON_COLOUR[season(date)]
400
- )
294
+ @feasts = {}
295
+ @memorials = {}
296
+
297
+ self.class.celebrations.each do |c|
298
+ if c.date_method.is_a? Proc
299
+ date = instance_eval &c.date_method
300
+ else
301
+ date = public_send(c.date_method)
302
+ end
303
+ celebration = c.celebration
304
+
305
+ add_to =
306
+ if celebration.feast?
307
+ @feasts
308
+ elsif celebration.memorial?
309
+ @memorials
310
+ else
311
+ @solemnities
312
+ end
313
+ add_to[date] = celebration
401
314
  end
402
315
  end
403
316
  end