calendarium-romanum 0.5.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +5 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +50 -0
  5. data/.travis.yml +23 -0
  6. data/.yardopts +3 -0
  7. data/Appraisals +67 -0
  8. data/CHANGELOG.md +488 -0
  9. data/Gemfile +26 -0
  10. data/Gemfile.lock +95 -0
  11. data/README.md +601 -0
  12. data/Rakefile +27 -0
  13. data/bin/calendariumrom +3 -0
  14. data/calendarium-romanum.gemspec +31 -0
  15. data/config/locales/cs.yml +4 -0
  16. data/config/locales/en.yml +20 -14
  17. data/config/locales/es.yml +94 -0
  18. data/config/locales/fr.yml +6 -0
  19. data/config/locales/it.yml +6 -0
  20. data/config/locales/la.yml +6 -0
  21. data/config/locales/pt.yml +94 -0
  22. data/data/README.md +70 -24
  23. data/data/czech-brno-cs.txt +4 -6
  24. data/data/czech-budejovice-cs.txt +4 -6
  25. data/data/czech-cechy-cs.txt +4 -5
  26. data/data/czech-cs.txt +239 -235
  27. data/data/czech-hradec-cs.txt +3 -5
  28. data/data/czech-litomerice-cs.txt +5 -7
  29. data/data/czech-morava-cs.txt +4 -5
  30. data/data/czech-olomouc-cs.txt +2 -4
  31. data/data/czech-ostrava-cs.txt +3 -5
  32. data/data/czech-plzen-cs.txt +3 -5
  33. data/data/czech-praha-cs.txt +3 -4
  34. data/data/easter_dates.txt +67 -0
  35. data/data/universal-1969-la.txt +234 -0
  36. data/data/universal-en.txt +217 -211
  37. data/data/universal-es.txt +246 -0
  38. data/data/universal-fr.txt +217 -210
  39. data/data/universal-it.txt +217 -211
  40. data/data/universal-la.txt +217 -212
  41. data/data/universal-pt.txt +248 -0
  42. data/doc/data_readme.md +2 -0
  43. data/doc/images/class_diagram.png +0 -0
  44. data/doc/images/class_diagram.puml +44 -0
  45. data/doc/yard_readme.rdoc +76 -0
  46. data/lib/calendarium-romanum.rb +16 -2
  47. data/lib/calendarium-romanum/abstract_date.rb +15 -0
  48. data/lib/calendarium-romanum/calendar.rb +150 -33
  49. data/lib/calendarium-romanum/cli.rb +80 -100
  50. data/lib/calendarium-romanum/cli/comparator.rb +83 -0
  51. data/lib/calendarium-romanum/cli/date_parser.rb +30 -0
  52. data/lib/calendarium-romanum/cli/dumper.rb +68 -0
  53. data/lib/calendarium-romanum/cli/helper.rb +23 -0
  54. data/lib/calendarium-romanum/cli/querier.rb +73 -0
  55. data/lib/calendarium-romanum/cr.rb +16 -0
  56. data/lib/calendarium-romanum/data.rb +40 -8
  57. data/lib/calendarium-romanum/day.rb +187 -32
  58. data/lib/calendarium-romanum/enum.rb +41 -24
  59. data/lib/calendarium-romanum/enums.rb +127 -43
  60. data/lib/calendarium-romanum/errors.rb +1 -1
  61. data/lib/calendarium-romanum/ordinalizer.rb +10 -1
  62. data/lib/calendarium-romanum/perpetual_calendar.rb +58 -7
  63. data/lib/calendarium-romanum/rank.rb +39 -8
  64. data/lib/calendarium-romanum/rank_predicates.rb +43 -0
  65. data/lib/calendarium-romanum/sanctorale.rb +213 -23
  66. data/lib/calendarium-romanum/sanctorale_factory.rb +74 -3
  67. data/lib/calendarium-romanum/sanctorale_loader.rb +180 -0
  68. data/lib/calendarium-romanum/sanctorale_writer.rb +124 -0
  69. data/lib/calendarium-romanum/temporale.rb +222 -42
  70. data/lib/calendarium-romanum/temporale/celebration_factory.rb +68 -9
  71. data/lib/calendarium-romanum/temporale/date_helper.rb +85 -0
  72. data/lib/calendarium-romanum/temporale/dates.rb +52 -59
  73. data/lib/calendarium-romanum/temporale/easter_table.rb +27 -0
  74. data/lib/calendarium-romanum/temporale/extensions.rb +15 -0
  75. data/lib/calendarium-romanum/temporale/extensions/christ_eternal_priest.rb +16 -3
  76. data/lib/calendarium-romanum/temporale/extensions/dedication_before_all_saints.rb +73 -0
  77. data/lib/calendarium-romanum/transfers.rb +84 -24
  78. data/lib/calendarium-romanum/util.rb +21 -23
  79. data/lib/calendarium-romanum/version.rb +3 -2
  80. data/liturgical_law/1969_normae_universales.md +568 -0
  81. data/liturgical_law/1977_decretum_de_celebratione_baptismatis_domini.md +58 -0
  82. data/liturgical_law/1990_decretum_de_variatione_inducenda.md +67 -0
  83. data/liturgical_law/1998_notificatio_de_occurrentia.md +57 -0
  84. data/liturgical_law/2002_normae_universales.md +946 -0
  85. data/liturgical_law/2006_notification.md +37 -0
  86. data/liturgical_law/2012_declarationes.md +38 -0
  87. data/liturgical_law/2020_dubia_de_calendario_2022.md +100 -0
  88. data/liturgical_law/README.md +74 -0
  89. metadata +61 -38
  90. data/lib/calendarium-romanum/sanctoraleloader.rb +0 -122
  91. data/spec/abstract_date_spec.rb +0 -62
  92. data/spec/calendar_spec.rb +0 -559
  93. data/spec/celebration_factory_spec.rb +0 -16
  94. data/spec/celebration_spec.rb +0 -43
  95. data/spec/cli_spec.rb +0 -155
  96. data/spec/colour_spec.rb +0 -17
  97. data/spec/data_spec.rb +0 -23
  98. data/spec/date_parser_spec.rb +0 -68
  99. data/spec/date_spec.rb +0 -61
  100. data/spec/dates_spec.rb +0 -45
  101. data/spec/day_spec.rb +0 -108
  102. data/spec/enum_spec.rb +0 -51
  103. data/spec/i18n_spec.rb +0 -58
  104. data/spec/ordinalizer_spec.rb +0 -36
  105. data/spec/perpetual_calendar_spec.rb +0 -91
  106. data/spec/rank_spec.rb +0 -57
  107. data/spec/readme_spec.rb +0 -56
  108. data/spec/sanctorale_factory_spec.rb +0 -42
  109. data/spec/sanctorale_spec.rb +0 -191
  110. data/spec/sanctoraleloader_spec.rb +0 -176
  111. data/spec/season_spec.rb +0 -17
  112. data/spec/spec_helper.rb +0 -46
  113. data/spec/temporale_spec.rb +0 -572
@@ -1,122 +0,0 @@
1
- module CalendariumRomanum
2
-
3
- # understands a plaintext calendar format
4
- # and knows how to transform it to Celebrations
5
- # and fill them in a Sanctorale
6
- #
7
- # Format of the file:
8
- # 1/31 m : S. Ioannis Bosco, presbyteri
9
- #
10
- # <month>/<day> <rank shortcut> : <title>
11
- # rank shortcut is optional, default value is optional memorial
12
- class SanctoraleLoader
13
-
14
- RANK_CODES = {
15
- nil => Ranks::MEMORIAL_OPTIONAL,
16
- 'm' => Ranks::MEMORIAL_GENERAL,
17
- 'f' => Ranks::FEAST_GENERAL,
18
- 's' => Ranks::SOLEMNITY_GENERAL
19
- }.freeze
20
- COLOUR_CODES = {
21
- nil => Colours::WHITE,
22
- 'w' => Colours::WHITE,
23
- 'v' => Colours::VIOLET,
24
- 'g' => Colours::GREEN,
25
- 'r' => Colours::RED
26
- }.freeze
27
-
28
- # dest should be a Sanctorale,
29
- # src anything with #each_line
30
- def load(src, dest = nil)
31
- dest ||= Sanctorale.new
32
-
33
- in_front_matter = false
34
- month_section = nil
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
47
-
48
- # strip whitespace and comments
49
- l.sub!(/#.*/, '')
50
- l.strip!
51
- next if l.empty?
52
-
53
- # month section heading
54
- n = l.match(/^=\s*(\d+)\s*$/)
55
- unless n.nil?
56
- month_section = n[1].to_i
57
- unless month_section >= 1 && month_section <= 12
58
- raise error("Invalid month #{month_section}", line_num)
59
- end
60
- next
61
- end
62
-
63
- # celebration record
64
- m = l.match(/^((\d+)\/)?(\d+)\s*(([mfs])?(\d\.\d{1,2})?)?\s*([WVRG])?\s*:(.*)$/i)
65
- if m.nil?
66
- raise error("Syntax error, line skipped '#{l}'", line_num)
67
- end
68
-
69
- month, day, rank_char, rank_num, colour, title = m.values_at(2, 3, 5, 6, 7, 8)
70
- month ||= month_section
71
- day = day.to_i
72
- month = month.to_i
73
-
74
- rank = RANK_CODES[rank_char && rank_char.downcase]
75
- if rank.nil?
76
- raise error("Invalid celebration rank code #{rank_char}", line_num)
77
- end
78
-
79
- if rank_num
80
- rank_num = rank_num.to_f
81
- rank_by_num = Ranks[rank_num]
82
-
83
- if rank_by_num.nil?
84
- raise error("Invalid celebration rank code #{rank_num}", line_num)
85
- elsif rank_char && (rank.priority.to_i != rank_by_num.priority.to_i)
86
- raise error("Invalid combination of rank letter #{rank_char.inspect} and number #{rank_num}.", line_num)
87
- end
88
-
89
- rank = rank_by_num
90
- end
91
-
92
- begin
93
- dest.add(
94
- month,
95
- day,
96
- Celebration.new(
97
- title.strip,
98
- rank,
99
- COLOUR_CODES[colour && colour.downcase]
100
- )
101
- )
102
- rescue RangeError => err
103
- raise error(err.message, line_num)
104
- end
105
- end
106
-
107
- dest
108
- end
109
-
110
- alias load_from_string load
111
-
112
- def load_from_file(filename, dest = nil, encoding = 'utf-8')
113
- load File.open(filename, 'r', encoding: encoding), dest
114
- end
115
-
116
- private
117
-
118
- def error(message, line_number)
119
- InvalidDataError.new("L#{line_number}: #{message}")
120
- end
121
- end
122
- end
@@ -1,62 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
- describe CR::AbstractDate do
4
- AD = CR::AbstractDate
5
-
6
- describe '.new' do
7
- describe 'fails on invalid' do
8
- it 'month' do
9
- expect do
10
- AD.new(13, 1)
11
- end.to raise_exception /Invalid month/
12
- end
13
-
14
- it 'day' do
15
- expect do
16
- AD.new(1, 32)
17
- end.to raise_exception /Invalid day/
18
- end
19
-
20
- it 'day of month' do
21
- expect do
22
- AD.new(2, 30)
23
- end.to raise_exception /Invalid day/
24
- end
25
- end
26
- end
27
-
28
- # test .new through .from_date on a complete leap year
29
- describe '.from_date' do
30
- YEAR = 2000
31
-
32
- it 'the test year is leap' do
33
- expect(Date.new(YEAR)).to be_leap
34
- end
35
-
36
- CR::Util::Year.new(YEAR).each do |date|
37
- it date.to_s do
38
- expect do
39
- AD.from_date date
40
- end.not_to raise_exception
41
- end
42
- end
43
- end
44
-
45
- describe '#<' do
46
- it { expect(AD.new(1, 1)).to be < AD.new(1, 2) }
47
- it { expect(AD.new(1, 1)).to be < AD.new(2, 1) }
48
- it { expect(AD.new(1, 1)).not_to be < AD.new(1, 1) }
49
- end
50
-
51
- describe '#==' do
52
- it { expect(AD.new(1, 1)).to be == AD.new(1, 1) }
53
- it { expect(AD.new(1, 1)).not_to be == AD.new(1, 2) }
54
- end
55
-
56
- describe 'as a Hash key' do
57
- it 'different objects with the same values are considered same key' do
58
- h = {AD.new(1, 1) => 1}
59
- expect(h).to have_key AD.new(1, 1)
60
- end
61
- end
62
- end
@@ -1,559 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
- describe CR::Calendar do
4
- before :all do
5
- @c = described_class.new(2013).freeze
6
- end
7
-
8
- let(:celfactory) { CR::Temporale::CelebrationFactory }
9
-
10
- describe '.new' do
11
- it 'throws RangeError on invalid year' do
12
- expect do
13
- described_class.new(1968)
14
- end.to raise_exception(RangeError, /in use only since 1st January 1970/)
15
- end
16
-
17
- it 'throws ArgumentError when Temporale year does not match' do
18
- year = 2000
19
- temporale = CR::Temporale.new year
20
- expect do
21
- CR::Calendar.new(year + 1, nil, temporale)
22
- end.to raise_exception ArgumentError
23
- end
24
- end
25
-
26
- describe '.for_day' do
27
- it 'continues the previous year\'s calendar in summer' do
28
- expect(described_class.for_day(Date.new(2014, 6, 9))).to eq described_class.new(2013)
29
- end
30
-
31
- it 'provides the current year\'s calendar in December' do
32
- expect(described_class.for_day(Date.new(2014, 12, 20))).to eq described_class.new(2014)
33
- end
34
- end
35
-
36
- describe '#==' do
37
- it 'considers calendars with the same year same' do
38
- expect(described_class.new(2014) == described_class.new(2014)).to be true
39
- end
40
-
41
- it 'considers calendars with different year different' do
42
- expect(described_class.new(2014) == described_class.new(2010)).to be false
43
- end
44
- end
45
-
46
- describe '#lectionary' do
47
- it 'detects correctly' do
48
- expect(described_class.new(2014).lectionary).to eq :B
49
- expect(described_class.new(2013).lectionary).to eq :A
50
- expect(described_class.new(2012).lectionary).to eq :C
51
- end
52
- end
53
-
54
- describe '#ferial_lectionary' do
55
- it 'detects correctly' do
56
- expect(described_class.new(2014).ferial_lectionary).to eq 1
57
- expect(described_class.new(2013).ferial_lectionary).to eq 2
58
- end
59
- end
60
-
61
- describe '#[]' do
62
- describe 'received arguments' do
63
- describe 'Date' do
64
- it 'returns a Day' do
65
- expect(@c[Date.new(2013, 12, 10)]).to be_a CR::Day
66
- end
67
- end
68
-
69
- describe 'Date range' do
70
- it 'returns an array of Days' do
71
- array = @c[Date.new(2013, 12, 10)..Date.new(2014, 4, 10)]
72
- expect(array).to be_a Array
73
- array.each{|day| expect(day).to be_a CR::Day}
74
- end
75
- end
76
- end
77
- end
78
-
79
- describe '#day' do
80
- describe 'received arguments' do
81
- describe 'Date' do
82
- it 'returns a Day' do
83
- expect(@c.day(Date.new(2013, 12, 10))).to be_a CR::Day
84
- end
85
- end
86
-
87
- describe 'DateTime' do
88
- it 'returns a Day' do
89
- expect(@c.day(DateTime.new(2013, 12, 10, 12, 10, 0))).to be_a CR::Day
90
- end
91
- end
92
-
93
- describe 'three Integers' do
94
- it 'returns a Day' do
95
- expect(@c.day(2013, 12, 10)).to be_a CR::Day
96
- end
97
- end
98
-
99
- describe 'two integers' do
100
- describe 'autumn' do
101
- it 'supplies year' do
102
- day = @c.day(12, 10)
103
- expect(day).to be_a CR::Day
104
- expect(day.date).to eq Date.new(2013, 12, 10)
105
- end
106
- end
107
-
108
- describe 'spring' do
109
- it 'supplies year' do
110
- day = @c.day(4, 10)
111
- expect(day).to be_a CR::Day
112
- expect(day.date).to eq Date.new(2014, 4, 10)
113
- end
114
- end
115
-
116
- describe 'invalid' do
117
- describe 'absolutely' do
118
- it 'fails' do
119
- expect do
120
- day = @c.day(0, 34)
121
- end.to raise_exception(ArgumentError, 'invalid date')
122
- end
123
- end
124
-
125
- describe 'for the given year' do
126
- it 'fails' do
127
- expect do
128
- day = @c.day(2, 29)
129
- end.to raise_exception(ArgumentError, 'invalid date')
130
- end
131
- end
132
- end
133
- end
134
- end
135
-
136
- describe "date not included in the calendar's year" do
137
- it 'throws RangeError' do
138
- expect { @c.day(2000, 1, 1) }.to raise_exception RangeError
139
- end
140
- end
141
-
142
- describe 'date before system effectiveness' do
143
- it 'throws RangeError' do
144
- c = described_class.new 1969
145
- expect { c.day(1969, 12, 20) }.to raise_exception RangeError
146
- end
147
- end
148
-
149
- describe 'temporale features' do
150
- describe 'season' do
151
- it 'detects Advent correctly' do
152
- expect(@c.day(2013, 12, 10).season).to eq CR::Seasons::ADVENT
153
- end
154
- end
155
-
156
- describe 'week of the season' do
157
- describe 'Advent' do
158
- it 'sets Advent week correctly' do
159
- expect(@c.day(2013, 12, 10).season_week).to eq 2
160
- expect(@c.day(2013, 12, 15).season_week).to eq 3
161
- end
162
- end
163
-
164
- describe 'Christmas' do
165
- it 'days before the first Sunday are week 0' do
166
- expect(@c.day(2013, 12, 25).season_week).to eq 0
167
- end
168
-
169
- it 'first Sunday starts week 1' do
170
- expect(@c.day(2013, 12, 29).season_week).to eq 1
171
- end
172
- end
173
-
174
- describe 'Lent' do
175
- it 'Ash Wednesday is week 0' do
176
- expect(@c.day(2014, 3, 5).season_week).to eq 0
177
- end
178
- end
179
-
180
- describe 'Easter' do
181
- it 'Easter Sunday opens week 1' do
182
- expect(@c.day(2014, 4, 20).season_week).to eq 1
183
- end
184
- end
185
-
186
- describe 'Ordinary time' do
187
- it 'Monday after Baptism of the Lord is week 1' do
188
- expect(@c.day(2014, 1, 13).season_week).to eq 1
189
- end
190
-
191
- describe 'after Pentecost' do
192
- it '2014' do
193
- c = described_class.new(2013)
194
- expect(c.day(2014, 6, 9).season_week).to eq 10
195
- end
196
-
197
- it '2015' do
198
- c = described_class.new(2014)
199
- expect(c.day(2015, 5, 25).season_week).to eq 8
200
- end
201
-
202
- it '2016' do
203
- c = described_class.new(2015)
204
- expect(c.day(2016, 5, 16).season_week).to eq 7
205
- end
206
-
207
- it '2017' do
208
- c = described_class.new(2016)
209
- expect(c.day(2017, 6, 5).season_week).to eq 9
210
- end
211
-
212
- describe 'works correctly for the whole week' do
213
- describe 'first' do
214
- Date.new(2014, 6, 9).upto(Date.new(2014, 6, 14)) do |date|
215
- it date do
216
- expect(@c.day(date).season_week).to eq 10
217
- end
218
- end
219
- end
220
-
221
- describe 'second' do
222
- Date.new(2014, 6, 15).upto(Date.new(2014, 6, 21)) do |date|
223
- it date do
224
- expect(@c.day(date).season_week).to eq 11
225
- end
226
- end
227
- end
228
-
229
- describe 'second last' do
230
- Date.new(2014, 11, 16).upto(Date.new(2014, 11, 22)) do |date|
231
- it date do
232
- expect(@c.day(date).season_week).to eq 33
233
- end
234
- end
235
- end
236
-
237
- describe 'last' do
238
- Date.new(2014, 11, 23).upto(Date.new(2014, 11, 29)) do |date|
239
- it date do
240
- expect(@c.day(date).season_week).to eq 34
241
- end
242
- end
243
- end
244
- end
245
- end
246
- end
247
- end
248
- end
249
-
250
- describe 'Temporale x Sanctorale resolution' do
251
- before :all do
252
- @s = CR::Data::GENERAL_ROMAN_ENGLISH.load
253
- @c = described_class.new(2013, @s).freeze
254
- end
255
-
256
- it '"empty" day results in a ferial' do
257
- d = @c.day(7, 2)
258
- expect(d.celebrations.size).to eq 1
259
- expect(d.celebrations[0].rank).to eq CR::Ranks::FERIAL
260
- end
261
-
262
- it 'sanctorale feast' do
263
- d = @c.day(7, 3)
264
- expect(d.celebrations.size).to eq 1
265
- expect(d.celebrations[0].rank).to eq CR::Ranks::FEAST_GENERAL
266
- expect(d.celebrations[0].title).to include 'Thomas'
267
- end
268
-
269
- it 'optional memorial does not suppress ferial' do
270
- d = @c.day(7, 14)
271
- expect(d.celebrations.size).to eq 2
272
-
273
- expect(d.celebrations[0].rank).to eq CR::Ranks::FERIAL
274
-
275
- expect(d.celebrations[1].rank).to eq CR::Ranks::MEMORIAL_OPTIONAL
276
- expect(d.celebrations[1].title).to include 'Lellis'
277
- end
278
-
279
- it 'obligatory memorial does suppress ferial' do
280
- d = @c.day(1, 17)
281
- expect(d.celebrations.size).to eq 1
282
-
283
- expect(d.celebrations[0].rank).to eq CR::Ranks::MEMORIAL_GENERAL
284
- end
285
-
286
- it 'memorial in Lent becomes mere commemoration' do
287
- d = @c.day(4, 2)
288
- expect(d.celebrations.size).to eq 2
289
-
290
- comm = d.celebrations[1]
291
- expect(comm.rank).to eq CR::Ranks::COMMEMORATION
292
- expect(comm.title).to eq 'Saint Francis of Paola, hermit'
293
- end
294
-
295
- it 'Sunday suppresses feast' do
296
- san = CR::Sanctorale.new
297
-
298
- d = Date.new 2015, 6, 28
299
- expect(d).to be_sunday # ensure
300
- san.add d.month, d.day, CR::Celebration.new('St. None, programmer', CR::Ranks::FEAST_GENERAL)
301
-
302
- c = described_class.new 2014, san
303
-
304
- celebs = c.day(d).celebrations
305
- expect(celebs.size).to eq 1
306
- expect(celebs[0].rank).to eq CR::Ranks::SUNDAY_UNPRIVILEGED
307
- end
308
-
309
- it 'suppressed fictive solemnity is transferred' do
310
- san = CR::Sanctorale.new
311
-
312
- d = CR::Temporale.new(2014).good_friday
313
- st_none = CR::Celebration.new('St. None, abbot, founder of the Order of Programmers (OProg)', CR::Ranks::SOLEMNITY_PROPER)
314
- san.add d.month, d.day, st_none
315
-
316
- c = described_class.new 2014, san
317
-
318
- # Good Friday suppresses the solemnity
319
- celebs = c.day(d).celebrations
320
- expect(celebs.size).to eq 1
321
- expect(celebs[0].rank).to eq CR::Ranks::TRIDUUM
322
- expect(celebs[0].title).to have_translation 'Friday of the Passion of the Lord'
323
-
324
- # it is transferred on a day after the Easter octave
325
- d = c.temporale.easter_sunday + 8
326
- celebs = c.day(d).celebrations
327
- expect(celebs.size).to eq 1
328
- expect(celebs[0]).to eq st_none
329
- end
330
-
331
- it 'transfer of suppressed Annunciation (real world example)' do
332
- c = described_class.new 2015, @s
333
-
334
- d = Date.new(2016, 3, 25)
335
-
336
- # Good Friday suppresses the solemnity
337
- celebs = c.day(d).celebrations
338
- expect(celebs.size).to eq 1
339
- expect(celebs[0]).to eq celfactory.good_friday
340
-
341
- # it is transferred on a day after the Easter octave
342
- d = c.temporale.easter_sunday + 8
343
- celebs = c.day(d).celebrations
344
- expect(celebs.size).to eq 1
345
- expect(celebs[0].title).to eq 'Annunciation of the Lord'
346
- end
347
-
348
- describe 'collision of Immaculate Heart with another obligatory memorial' do
349
- let(:year) { 2002 }
350
- let(:c) { described_class.new year, @s }
351
- let(:date) { Date.new(2003, 6, 28) }
352
-
353
- it 'makes both optional memorials' do
354
- # make sure
355
- expect(c.sanctorale.get(date).first.rank).to eq CR::Ranks::MEMORIAL_GENERAL
356
- expect(c.temporale.get(date).rank).to eq CR::Ranks::MEMORIAL_GENERAL
357
-
358
- celebrations = c.day(date).celebrations
359
- expect(celebrations.size).to eq 3
360
-
361
- expect(celebrations[0].rank).to eq CR::Ranks::FERIAL
362
- expect(celebrations[1..-1].collect(&:rank).uniq)
363
- .to eq([CR::Ranks::MEMORIAL_OPTIONAL])
364
- end
365
- end
366
- end
367
-
368
- describe 'Vespers' do
369
- let(:saturday) { Date.new(2014, 1, 4) }
370
- let(:year) { 2013 }
371
- let(:calendar) { described_class.new(year) }
372
-
373
- describe 'not opted in' do
374
- it 'does not fill Vespers' do
375
- day = calendar.day saturday
376
- expect(day.vespers).to be nil
377
- end
378
- end
379
-
380
- describe 'opted in by constructor argument' do
381
- let(:calendar) { described_class.new(year, nil, nil, vespers: true) }
382
-
383
- it 'fills Vespers' do
384
- day = calendar.day saturday
385
- expect(day.vespers).to be_a CR::Celebration
386
- end
387
-
388
- describe 'but the day has not Vespers from following' do
389
- it 'does not fill Vespers' do
390
- friday = saturday - 1
391
- day = calendar.day friday
392
- expect(day.vespers).to be nil
393
- end
394
- end
395
- end
396
-
397
- describe 'opted in by argument' do
398
- it 'fills Vespers' do
399
- day = calendar.day saturday, vespers: true
400
- expect(day.vespers).to be_a CR::Celebration
401
- end
402
- end
403
-
404
- describe 'first Vespers of' do
405
- let(:sanctorale) { CR::Data::GENERAL_ROMAN_ENGLISH.load }
406
- let(:calendar) { described_class.new(year, sanctorale, nil, vespers: true) }
407
-
408
- describe 'a Sunday' do
409
- it 'has first Vespers' do
410
- day = calendar.day saturday
411
- expect(day.vespers.rank).to eq CR::Ranks::SUNDAY_UNPRIVILEGED
412
- end
413
- end
414
-
415
- describe 'a solemnity' do
416
- let(:testing_solemnity) do
417
- CR::Celebration.new(
418
- 'Testing solemnity',
419
- CR::Ranks::SOLEMNITY_GENERAL,
420
- CR::Colours::WHITE,
421
- :test
422
- )
423
- end
424
-
425
- it 'has first Vespers' do
426
- day = calendar.day(Date.new(2014, 11, 1) - 1)
427
- expect(day.vespers.rank).to be CR::Ranks::SOLEMNITY_GENERAL
428
- end
429
-
430
- describe 'clash with Sunday Vespers' do
431
- it 'wins over Sunday' do
432
- sunday = Date.new(2014, 8, 17)
433
- expect(sunday).to be_sunday # make sure
434
- sanctorale.replace(8, 17, [testing_solemnity])
435
-
436
- day = calendar.day(sunday - 1)
437
- expect(day.vespers.symbol).to eq :test
438
- end
439
- end
440
-
441
- describe 'clash with second Vespers of another solemnity' do
442
- it "the day's Vespers win" do
443
- assumption = Date.new(2014, 8, 15)
444
- sanctorale.replace(8, 16, [testing_solemnity])
445
-
446
- day = calendar.day(assumption)
447
- expect(day.celebrations.first.rank).to be CR::Ranks::SOLEMNITY_GENERAL
448
- expect(day.vespers).to be nil
449
-
450
- # make sure
451
- next_day = calendar.day(assumption + 1)
452
- expect(next_day.celebrations.first).to be testing_solemnity
453
- end
454
- end
455
- end
456
-
457
- describe 'feast of the Lord' do
458
- describe 'not falling on a Sunday' do
459
- it 'does not have first Vespers' do
460
- calendar = described_class.new(2015, sanctorale, nil, vespers: true)
461
- presentation = Date.new(2016, 2, 2)
462
- expect(presentation).not_to be_sunday # make sure
463
-
464
- day = calendar.day(presentation - 1)
465
- expect(day.vespers).to be nil
466
- end
467
- end
468
-
469
- describe 'falling on a Sunday' do
470
- it 'has first Vespers' do
471
- presentation = Date.new(2014, 2, 2)
472
- expect(presentation).to be_sunday # make sure
473
-
474
- day = calendar.day(presentation - 1)
475
- expect(day.vespers.rank).to be CR::Ranks::FEAST_LORD_GENERAL
476
- end
477
- end
478
- end
479
-
480
- # this group contains both days having and days not having
481
- # first Vespers: special care must be taken
482
- describe 'primary liturgical days' do
483
- describe 'Ash Wednesday' do
484
- it 'does not have first Vespers' do
485
- aw = CR::Temporale::Dates.ash_wednesday year
486
- day = calendar.day(aw - 1)
487
- expect(day.vespers).to be nil
488
- end
489
- end
490
-
491
- describe 'Nativity' do
492
- it 'has first Vespers' do
493
- day = calendar.day Date.new(2013, 12, 24)
494
- expect(day.vespers).to eq celfactory.nativity
495
- end
496
- end
497
-
498
- describe 'Epiphany' do
499
- it 'has first Vespers' do
500
- day = calendar.day Date.new(2014, 1, 5)
501
- expect(day.vespers.rank).to be CR::Ranks::PRIMARY
502
- expect(day.vespers.symbol).to be :epiphany
503
- end
504
- end
505
-
506
- describe 'Palm Sunday' do
507
- it 'has first Vespers' do
508
- ps = CR::Temporale::Dates.palm_sunday year
509
- day = calendar.day(ps - 1)
510
- expect(day.vespers).to eq celfactory.palm_sunday
511
- end
512
- end
513
-
514
- describe 'day in the Holy week' do
515
- it 'does not have first Vespers' do
516
- tuesday = CR::Temporale::Dates.palm_sunday(year) + 2
517
- day = calendar.day(tuesday - 1)
518
- expect(day.vespers).to be nil
519
- end
520
- end
521
-
522
- describe 'Good Friday' do
523
- it 'does not have first Vespers' do
524
- gf = CR::Temporale::Dates.good_friday(year)
525
- day = calendar.day(gf - 1)
526
- expect(day.vespers).to be nil
527
- end
528
- end
529
-
530
- describe 'Easter' do
531
- it 'has first Vespers' do
532
- es = CR::Temporale::Dates.easter_sunday year
533
- day = calendar.day(es - 1)
534
- expect(day.vespers).to eq celfactory.easter_sunday
535
- end
536
- end
537
-
538
- describe 'day in Easter octave' do
539
- it 'does not have first Vespers' do
540
- tuesday = CR::Temporale::Dates.easter_sunday(year) + 2
541
- day = calendar.day(tuesday - 1)
542
- expect(day.vespers).to be nil
543
- end
544
- end
545
- end
546
-
547
- describe 'edge cases' do
548
- describe 'First Sunday of Advent' do
549
- it 'has first Vespers (and does not cause an exception)' do
550
- sunday = CR::Temporale::Dates.first_advent_sunday(year + 1)
551
- day = calendar.day(sunday - 1)
552
- expect(day.vespers).to eq celfactory.first_advent_sunday
553
- end
554
- end
555
- end
556
- end
557
- end
558
- end
559
- end