calendarium-romanum 0.4.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +4 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +47 -0
  5. data/.travis.yml +22 -0
  6. data/.yardopts +3 -0
  7. data/CHANGELOG.md +431 -0
  8. data/Gemfile +25 -0
  9. data/Gemfile.lock +86 -0
  10. data/README.md +598 -0
  11. data/Rakefile +16 -0
  12. data/bin/calendariumrom +4 -1
  13. data/calendarium-romanum.gemspec +31 -0
  14. data/config/locales/cs.yml +5 -0
  15. data/config/locales/en.yml +21 -14
  16. data/config/locales/es.yml +94 -0
  17. data/config/locales/fr.yml +7 -0
  18. data/config/locales/it.yml +7 -0
  19. data/config/locales/la.yml +7 -0
  20. data/data/README.md +70 -24
  21. data/data/czech-brno-cs.txt +4 -6
  22. data/data/czech-budejovice-cs.txt +4 -6
  23. data/data/czech-cechy-cs.txt +4 -5
  24. data/data/czech-cs.txt +236 -234
  25. data/data/czech-hradec-cs.txt +3 -5
  26. data/data/czech-litomerice-cs.txt +5 -7
  27. data/data/czech-morava-cs.txt +4 -5
  28. data/data/czech-olomouc-cs.txt +2 -4
  29. data/data/czech-ostrava-cs.txt +3 -5
  30. data/data/czech-plzen-cs.txt +3 -5
  31. data/data/czech-praha-cs.txt +3 -4
  32. data/data/easter_dates.txt +67 -0
  33. data/data/universal-1969-la.txt +234 -0
  34. data/data/universal-en.txt +214 -211
  35. data/data/universal-es.txt +243 -0
  36. data/data/universal-fr.txt +214 -210
  37. data/data/universal-it.txt +214 -211
  38. data/data/universal-la.txt +214 -210
  39. data/doc/data_readme.md +2 -0
  40. data/doc/images/class_diagram.png +0 -0
  41. data/doc/images/class_diagram.puml +44 -0
  42. data/doc/yard_readme.rdoc +76 -0
  43. data/lib/calendarium-romanum.rb +35 -22
  44. data/lib/calendarium-romanum/abstract_date.rb +15 -0
  45. data/lib/calendarium-romanum/calendar.rb +207 -42
  46. data/lib/calendarium-romanum/cli.rb +63 -80
  47. data/lib/calendarium-romanum/cli/comparator.rb +63 -0
  48. data/lib/calendarium-romanum/cli/date_parser.rb +30 -0
  49. data/lib/calendarium-romanum/cli/dumper.rb +68 -0
  50. data/lib/calendarium-romanum/cli/helper.rb +23 -0
  51. data/lib/calendarium-romanum/cli/querier.rb +73 -0
  52. data/lib/calendarium-romanum/cr.rb +16 -0
  53. data/lib/calendarium-romanum/data.rb +50 -20
  54. data/lib/calendarium-romanum/day.rb +208 -32
  55. data/lib/calendarium-romanum/enum.rb +42 -25
  56. data/lib/calendarium-romanum/enums.rb +124 -44
  57. data/lib/calendarium-romanum/errors.rb +4 -0
  58. data/lib/calendarium-romanum/ordinalizer.rb +23 -2
  59. data/lib/calendarium-romanum/perpetual_calendar.rb +58 -7
  60. data/lib/calendarium-romanum/rank.rb +43 -12
  61. data/lib/calendarium-romanum/rank_predicates.rb +43 -0
  62. data/lib/calendarium-romanum/sanctorale.rb +164 -24
  63. data/lib/calendarium-romanum/sanctorale_factory.rb +74 -3
  64. data/lib/calendarium-romanum/sanctorale_loader.rb +180 -0
  65. data/lib/calendarium-romanum/sanctorale_writer.rb +119 -0
  66. data/lib/calendarium-romanum/temporale.rb +226 -94
  67. data/lib/calendarium-romanum/temporale/celebration_factory.rb +107 -0
  68. data/lib/calendarium-romanum/temporale/dates.rb +84 -16
  69. data/lib/calendarium-romanum/temporale/easter_table.rb +27 -0
  70. data/lib/calendarium-romanum/temporale/extensions.rb +15 -0
  71. data/lib/calendarium-romanum/temporale/extensions/christ_eternal_priest.rb +16 -3
  72. data/lib/calendarium-romanum/temporale/extensions/dedication_before_all_saints.rb +73 -0
  73. data/lib/calendarium-romanum/transfers.rb +60 -15
  74. data/lib/calendarium-romanum/util.rb +22 -3
  75. data/lib/calendarium-romanum/version.rb +5 -1
  76. data/liturgical_law/1969_normae_universales.md +568 -0
  77. data/liturgical_law/1977_decretum_de_celebratione_baptismatis_domini.md +58 -0
  78. data/liturgical_law/1990_decretum_de_variatione_inducenda.md +67 -0
  79. data/liturgical_law/1998_notificatio_de_occurrentia.md +57 -0
  80. data/liturgical_law/2002_normae_universales.md +946 -0
  81. data/liturgical_law/2006_notification.md +37 -0
  82. data/liturgical_law/2012_declarationes.md +38 -0
  83. data/liturgical_law/README.md +74 -0
  84. metadata +50 -28
  85. data/lib/calendarium-romanum/sanctoraleloader.rb +0 -115
  86. data/spec/abstract_date_spec.rb +0 -62
  87. data/spec/calendar_spec.rb +0 -330
  88. data/spec/celebration_spec.rb +0 -23
  89. data/spec/cli_spec.rb +0 -26
  90. data/spec/colour_spec.rb +0 -17
  91. data/spec/data_spec.rb +0 -23
  92. data/spec/date_spec.rb +0 -61
  93. data/spec/dates_spec.rb +0 -45
  94. data/spec/day_spec.rb +0 -59
  95. data/spec/enum_spec.rb +0 -51
  96. data/spec/i18n_spec.rb +0 -59
  97. data/spec/ordinalizer_spec.rb +0 -22
  98. data/spec/perpetual_calendar_spec.rb +0 -91
  99. data/spec/rank_spec.rb +0 -57
  100. data/spec/readme_spec.rb +0 -52
  101. data/spec/sanctorale_factory_spec.rb +0 -42
  102. data/spec/sanctorale_spec.rb +0 -191
  103. data/spec/sanctoraleloader_spec.rb +0 -171
  104. data/spec/season_spec.rb +0 -17
  105. data/spec/spec_helper.rb +0 -35
  106. data/spec/temporale_spec.rb +0 -519
@@ -0,0 +1,119 @@
1
+ require 'yaml'
2
+
3
+ module CalendariumRomanum
4
+
5
+ # Understands a custom plaintext calendar format
6
+ # and knows how to transform the {Celebration}s in a
7
+ # {Sanctorale} to this format.
8
+ #
9
+ # For specification of the data format see {file:data/README.md}
10
+ # of the data directory, For a complete example see e.g.
11
+ # {file:universal-en.txt the file describing General Roman Calendar}.
12
+ #
13
+ # @since 0.8.0
14
+ class SanctoraleWriter
15
+
16
+ # @api private
17
+ RANK_CODES = {
18
+ Ranks::TRIDUUM => 's1.1',
19
+ Ranks::PRIMARY => 's1.2',
20
+ Ranks::SOLEMNITY_GENERAL => 's',
21
+ Ranks::SOLEMNITY_PROPER => 's1.4',
22
+
23
+ Ranks::FEAST_LORD_GENERAL => 'f2.5',
24
+ Ranks::SUNDAY_UNPRIVILEGED => 'f2.6',
25
+ Ranks::FEAST_GENERAL => 'f',
26
+ Ranks::FEAST_PROPER => 'f2.8',
27
+ Ranks::FERIAL_PRIVILEGED => 'f2.9',
28
+
29
+ Ranks::MEMORIAL_GENERAL => 'm',
30
+ Ranks::MEMORIAL_PROPER => 'm3.11',
31
+ Ranks::MEMORIAL_OPTIONAL => 'm3.12',
32
+ Ranks::FERIAL => 'm3.13',
33
+
34
+ Ranks::COMMEMORATION => '4.0'
35
+ }.freeze
36
+
37
+ # @api private
38
+ COLOUR_CODES = {
39
+ Colours::WHITE => 'W',
40
+ Colours::VIOLET => 'V',
41
+ Colours::GREEN => 'G',
42
+ Colours::RED => 'R'
43
+ }.freeze
44
+
45
+ # Write to an object which understands +#<<+
46
+ #
47
+ # @param src [Sanctorale]
48
+ # source of the loaded data
49
+ # @param dest [String, File, #<<]
50
+ # object to populate. If not provided, a new {String}
51
+ # instance will be created and returned
52
+ # @return [String]
53
+ def write(src, dest = nil)
54
+ dest ||= String.new
55
+
56
+ # Write metadata to YAML if present
57
+ unless src.metadata.nil? || src.metadata.empty?
58
+ dest << src.metadata.to_yaml
59
+ dest << "---\n"
60
+ end
61
+
62
+ # Write each celebration, grouped by month with headings
63
+ current_month = 0
64
+ src.each_day.sort_by{ |date, _| date }.each do |date, celebrations|
65
+ if date.month > current_month
66
+ current_month = date.month
67
+ dest << "\n= #{current_month}\n"
68
+ end
69
+
70
+ celebrations.each do |c|
71
+ dest << celebration_line(date, c)
72
+ dest << "\n"
73
+ end
74
+ end
75
+
76
+ dest
77
+ end
78
+
79
+ alias write_to_string write
80
+
81
+ # Write to a filesystem path
82
+ #
83
+ # @param sanctorale [Sanctorale]
84
+ # @param filename [String]
85
+ # @param encoding [String]
86
+ # @return [void]
87
+ def write_to_file(sanctorale, filename, encoding = 'utf-8')
88
+ File.open(filename, 'w', encoding: encoding) do |f|
89
+ write(sanctorale, f)
90
+ end
91
+ end
92
+
93
+ private
94
+
95
+ # Convert a {Celebration} to a {String} for writing
96
+ def celebration_line(date, celebration)
97
+ line = "#{date.day} "
98
+
99
+ unless celebration.rank == Ranks::MEMORIAL_OPTIONAL
100
+ code = RANK_CODES[celebration.rank]
101
+ line << "#{code} "
102
+ end
103
+
104
+ unless celebration.colour == Colours::WHITE
105
+ code = COLOUR_CODES[celebration.colour]
106
+ line << "#{code} "
107
+ end
108
+
109
+ unless celebration.symbol.nil?
110
+ line << "#{celebration.symbol} "
111
+ end
112
+
113
+ line << ': '
114
+ line << celebration.title
115
+
116
+ line
117
+ end
118
+ end
119
+ end
@@ -2,29 +2,44 @@ require 'date'
2
2
 
3
3
  module CalendariumRomanum
4
4
 
5
- # determine seasons and dates of the Temporale feasts of the given year
5
+ # One of the two main {Calendar} components.
6
+ # Handles seasons and celebrations of the temporale cycle
7
+ # for a given liturgical year.
6
8
  class Temporale
7
9
 
10
+ # How many days in a week
8
11
  WEEK = 7
9
12
 
13
+ # Which solemnities can be transferred to Sunday
10
14
  SUNDAY_TRANSFERABLE_SOLEMNITIES =
11
15
  %i(epiphany ascension corpus_christi).freeze
12
16
 
13
- # year is Integer - the civil year when the liturgical year begins
17
+ # @param year [Integer]
18
+ # the civil year when the liturgical year _begins_
19
+ # @param extensions [Array<#each_celebration>]
20
+ # extensions implementing custom temporale celebrations
21
+ # @param transfer_to_sunday [Array<Symbol>]
22
+ # which solemnities should be transferred to a nearby
23
+ # Sunday - see {SUNDAY_TRANSFERABLE_SOLEMNITIES}
24
+ # for possible values
14
25
  def initialize(year, extensions: [], transfer_to_sunday: [])
15
26
  @year = year
16
27
 
17
28
  @extensions = extensions
18
- @transfer_to_sunday = transfer_to_sunday
29
+ @transfer_to_sunday = transfer_to_sunday.sort
19
30
  validate_sunday_transfer!
20
31
 
21
32
  prepare_solemnities
22
33
  end
23
34
 
35
+ # @return [Integer]
24
36
  attr_reader :year
25
37
 
26
38
  class << self
27
39
  # Determines liturgical year for the given date
40
+ #
41
+ # @param date [Date]
42
+ # @return [Integer]
28
43
  def liturgical_year(date)
29
44
  year = date.year
30
45
  temporale = Temporale.new year
@@ -33,77 +48,111 @@ module CalendariumRomanum
33
48
  return year - 1
34
49
  end
35
50
 
36
- return year
51
+ year
37
52
  end
38
53
 
39
- # creates a Calendar for the liturgical year including given
54
+ # Creates an instance for the liturgical year including given
40
55
  # date
56
+ #
57
+ # @param date [Date]
58
+ # @return [Temporale]
41
59
  def for_day(date)
42
- return new(liturgical_year(date))
60
+ new(liturgical_year(date))
61
+ end
62
+
63
+ # Factory method creating temporale {Celebration}s
64
+ # with sensible defaults
65
+ #
66
+ # See {Celebration#initialize} for argument description.
67
+ def create_celebration(title, rank, colour, symbol: nil, date: nil, sunday: nil)
68
+ Celebration.new(
69
+ title: title,
70
+ rank: rank,
71
+ colour: colour,
72
+ symbol: symbol,
73
+ date: date,
74
+ cycle: :temporale,
75
+ sunday: sunday
76
+ )
43
77
  end
44
78
 
45
79
  C = Struct.new(:date_method, :celebration)
46
80
  private_constant :C
47
81
 
48
- # implementation detail, not to be touched by client code
82
+ # @api private
49
83
  def celebrations
50
84
  @celebrations ||=
51
85
  begin
52
- [
53
- c(:nativity, Ranks::PRIMARY),
54
- c(:holy_family, Ranks::FEAST_LORD_GENERAL),
55
- c(:mother_of_god, Ranks::SOLEMNITY_GENERAL),
56
- c(:epiphany, Ranks::PRIMARY),
57
- c(:baptism_of_lord, Ranks::FEAST_LORD_GENERAL),
58
- c(:ash_wednesday, Ranks::PRIMARY, Colours::VIOLET),
59
- c(:good_friday, Ranks::TRIDUUM, Colours::RED),
60
- c(:holy_saturday, Ranks::TRIDUUM, Colours::VIOLET),
61
- c(:palm_sunday, Ranks::PRIMARY, Colours::RED),
62
- c(:easter_sunday, Ranks::TRIDUUM),
63
- c(:ascension, Ranks::PRIMARY),
64
- c(:pentecost, Ranks::PRIMARY, Colours::RED),
65
- c(:holy_trinity, Ranks::SOLEMNITY_GENERAL),
66
- c(:corpus_christi, Ranks::SOLEMNITY_GENERAL),
67
- c(:sacred_heart, Ranks::SOLEMNITY_GENERAL),
68
- c(:christ_king, Ranks::SOLEMNITY_GENERAL),
69
-
70
- # Immaculate Heart of Mary is actually (currently the only one)
71
- # movable *sanctorale* feast, but as it would make little sense
72
- # to add support for movable sanctorale feasts because of
73
- # a single one, we cheat a bit and handle it in temporale.
74
- c(:immaculate_heart, Ranks::MEMORIAL_GENERAL),
75
- ]
86
+ %i(
87
+ nativity
88
+ holy_family
89
+ mother_of_god
90
+ epiphany
91
+ baptism_of_lord
92
+ ash_wednesday
93
+ good_friday
94
+ holy_saturday
95
+ palm_sunday
96
+ easter_sunday
97
+ ascension
98
+ pentecost
99
+ holy_trinity
100
+ corpus_christi
101
+ mother_of_church
102
+ sacred_heart
103
+ christ_king
104
+ immaculate_heart
105
+ ).collect do |symbol|
106
+ date_method = symbol
107
+ C.new(
108
+ date_method,
109
+ CelebrationFactory.public_send(symbol)
110
+ )
111
+ end
112
+ # Immaculate Heart of Mary and Mary, Mother of the Church
113
+ # are actually movable *sanctorale* feasts,
114
+ # but as it would make little sense
115
+ # to add support for movable sanctorale feasts because of
116
+ # two, we cheat a bit and handle them in temporale.
76
117
  end
77
118
  end
78
-
79
- private
80
-
81
- def c(date_method, rank, colour=Colours::WHITE)
82
- title = proc { I18n.t("temporale.solemnity.#{date_method}") }
83
-
84
- C.new(
85
- date_method,
86
- Celebration.new(title, rank, colour)
87
- )
88
- end
89
119
  end
90
120
 
121
+ # Does this instance transfer the specified solemnity to Sunday?
122
+ #
123
+ # @param solemnity [Symbol]
124
+ # @return [Boolean]
91
125
  def transferred_to_sunday?(solemnity)
92
126
  @transfer_to_sunday.include?(solemnity)
93
127
  end
94
128
 
129
+ # First day of the liturgical year
130
+ #
131
+ # @return [Date]
95
132
  def start_date
96
133
  first_advent_sunday
97
134
  end
98
135
 
136
+ # Last day of the liturgical year
137
+ #
138
+ # @return [Date]
99
139
  def end_date
100
- Dates.first_advent_sunday(year+1) - 1
140
+ Dates.first_advent_sunday(year + 1) - 1
101
141
  end
102
142
 
143
+ # Date range of the liturgical year
144
+ #
145
+ # @return [Range<Date>]
103
146
  def date_range
104
147
  start_date .. end_date
105
148
  end
106
149
 
150
+ # Check that the date belongs to the liturgical year.
151
+ # If it does not, throw exception.
152
+ #
153
+ # @param date [Date]
154
+ # @return [void]
155
+ # @raise [RangeError]
107
156
  def range_check(date)
108
157
  # necessary in order to handle Date correctly
109
158
  date = date.to_date if date.class != Date
@@ -113,26 +162,46 @@ module CalendariumRomanum
113
162
  end
114
163
  end
115
164
 
116
- %i(
117
- first_advent_sunday
118
- nativity
119
- holy_family
120
- mother_of_god
121
- epiphany
122
- baptism_of_lord
123
- ash_wednesday
124
- palm_sunday
125
- good_friday
126
- holy_saturday
127
- easter_sunday
128
- ascension
129
- pentecost
130
- holy_trinity
131
- corpus_christi
132
- sacred_heart
133
- immaculate_heart
134
- christ_king
135
- ).each do |feast|
165
+ # @!method nativity
166
+ # @return [Date]
167
+ # @!method holy_family
168
+ # @return [Date]
169
+ # @!method mother_of_god
170
+ # @return [Date]
171
+ # @!method epiphany
172
+ # @return [Date]
173
+ # @!method baptism_of_lord
174
+ # @return [Date]
175
+ # @!method ash_wednesday
176
+ # @return [Date]
177
+ # @!method good_friday
178
+ # @return [Date]
179
+ # @!method holy_saturday
180
+ # @return [Date]
181
+ # @!method palm_sunday
182
+ # @return [Date]
183
+ # @!method easter_sunday
184
+ # @return [Date]
185
+ # @!method ascension
186
+ # @return [Date]
187
+ # @!method pentecost
188
+ # @return [Date]
189
+ # @!method holy_trinity
190
+ # @return [Date]
191
+ # @!method corpus_christi
192
+ # @return [Date]
193
+ # @!method mother_of_church
194
+ # @return [Date]
195
+ # @!method sacred_heart
196
+ # @return [Date]
197
+ # @!method christ_king
198
+ # @return [Date]
199
+ # @!method immaculate_heart
200
+ # @return [Date]
201
+ # @!method first_advent_sunday
202
+ # @return [Date]
203
+ (celebrations.collect(&:date_method) + [:first_advent_sunday])
204
+ .each do |feast|
136
205
  if SUNDAY_TRANSFERABLE_SOLEMNITIES.include? feast
137
206
  define_method feast do
138
207
  Dates.public_send feast, year, sunday: transferred_to_sunday?(feast)
@@ -148,24 +217,33 @@ module CalendariumRomanum
148
217
  end
149
218
  end
150
219
 
151
- # which liturgical season is it?
220
+ # Determine liturgical season for a given date
221
+ #
222
+ # @param date [Date]
223
+ # @return [Season]
224
+ # @raise [RangeError]
225
+ # if the given date doesn't belong to the liturgical year
152
226
  def season(date)
153
227
  range_check date
154
228
 
155
- if first_advent_sunday <= date and
156
- nativity > date then
229
+ if first_advent_sunday <= date &&
230
+ nativity > date
157
231
  Seasons::ADVENT
158
232
 
159
- elsif nativity <= date and
160
- baptism_of_lord >= date then
233
+ elsif nativity <= date &&
234
+ baptism_of_lord >= date
161
235
  Seasons::CHRISTMAS
162
236
 
163
- elsif ash_wednesday <= date and
164
- easter_sunday > date then
237
+ elsif ash_wednesday <= date &&
238
+ good_friday > date
165
239
  Seasons::LENT
166
240
 
167
- elsif easter_sunday <= date and
168
- pentecost >= date then
241
+ elsif good_friday <= date &&
242
+ easter_sunday >= date
243
+ Seasons::TRIDUUM
244
+
245
+ elsif easter_sunday < date &&
246
+ pentecost >= date
169
247
  Seasons::EASTER
170
248
 
171
249
  else
@@ -173,6 +251,10 @@ module CalendariumRomanum
173
251
  end
174
252
  end
175
253
 
254
+ # When the specified liturgical season begins
255
+ #
256
+ # @param s [Season]
257
+ # @return [Date]
176
258
  def season_beginning(s)
177
259
  case s
178
260
  when Seasons::ADVENT
@@ -181,13 +263,21 @@ module CalendariumRomanum
181
263
  nativity
182
264
  when Seasons::LENT
183
265
  ash_wednesday
266
+ when Seasons::TRIDUUM
267
+ good_friday
184
268
  when Seasons::EASTER
185
- easter_sunday
186
- else # ordinary time
187
- Dates.monday_after(baptism_of_lord)
269
+ easter_sunday + 1
270
+ when Seasons::ORDINARY # ordinary time
271
+ baptism_of_lord + 1
272
+ else
273
+ raise ArgumentError.new('unsupported season')
188
274
  end
189
275
  end
190
276
 
277
+ # Determine week of a season for a given date
278
+ #
279
+ # @param seasonn [Season]
280
+ # @param date [Date]
191
281
  def season_week(seasonn, date)
192
282
  week1_beginning = season_beginning = season_beginning(seasonn)
193
283
  unless season_beginning.sunday?
@@ -196,25 +286,40 @@ module CalendariumRomanum
196
286
 
197
287
  week = date_difference(date, week1_beginning) / WEEK + 1
198
288
 
199
- if seasonn == Seasons::ORDINARY
289
+ if seasonn == Seasons::ORDINARY || seasonn == Seasons::EASTER
200
290
  # ordinary time does not begin with Sunday, but the first week
201
291
  # is week 1, not 0
202
292
  week += 1
293
+ end
203
294
 
295
+ if seasonn == Seasons::ORDINARY
204
296
  if date > pentecost
205
- weeks_after_date = date_difference(Dates.first_advent_sunday(@year + 1), date) / 7
297
+ weeks_after_date = date_difference(Dates.first_advent_sunday(@year + 1), date) / WEEK
206
298
  week = 34 - weeks_after_date
207
299
  week += 1 if date.sunday?
208
300
  end
209
301
  end
210
302
 
211
- return week
303
+ week
212
304
  end
213
305
 
214
- # returns a Celebration
215
- # scheduled for the given day
306
+ # Retrieve temporale celebration for the given day
216
307
  #
217
- # expected arguments: Date or two Integers (month, day)
308
+ # @param date [Date]
309
+ # @return [Celebration]
310
+ # @since 0.6.0
311
+ def [](date)
312
+ @solemnities[date] || @feasts[date] || sunday(date) || @memorials[date] || ferial(date)
313
+ end
314
+
315
+ # Retrieve temporale celebration for the given day
316
+ #
317
+ # @overload get(date)
318
+ # @param date [Date]
319
+ # @overload get(month, day)
320
+ # @param month [Integer]
321
+ # @param day [Integer]
322
+ # @return (see #[])
218
323
  def get(*args)
219
324
  if args.size == 1 && args[0].is_a?(Date)
220
325
  date = args[0]
@@ -226,9 +331,33 @@ module CalendariumRomanum
226
331
  end
227
332
  end
228
333
 
229
- return @solemnities[date] || @feasts[date] || sunday(date) || @memorials[date] || ferial(date)
334
+ self[date]
335
+ end
336
+
337
+ # Enumerates dates and celebrations
338
+ #
339
+ # @yield [Date, Celebration]
340
+ # @return [void, Enumerator] if called without a block, returns +Enumerator+
341
+ # @since 0.8.0
342
+ def each_day
343
+ return to_enum(__method__) unless block_given?
344
+
345
+ date_range.each {|date| yield date, self[date] }
346
+ end
347
+
348
+ # @return [Boolean]
349
+ # @since 0.6.0
350
+ def ==(b)
351
+ self.class == b.class &&
352
+ year == b.year &&
353
+ transfer_to_sunday == b.transfer_to_sunday &&
354
+ Set.new(extensions) == Set.new(b.extensions)
230
355
  end
231
356
 
357
+ protected
358
+
359
+ attr_reader :transfer_to_sunday, :extensions
360
+
232
361
  private
233
362
 
234
363
  # seasons when Sundays have higher rank
@@ -246,7 +375,7 @@ module CalendariumRomanum
246
375
  week = Ordinalizer.ordinal season_week(seas, date)
247
376
  title = I18n.t "temporale.#{seas.to_sym}.sunday", week: week
248
377
 
249
- return Celebration.new title, rank, seas.colour
378
+ self.class.create_celebration title, rank, seas.colour, sunday: true
250
379
  end
251
380
 
252
381
  def ferial(date)
@@ -258,6 +387,8 @@ module CalendariumRomanum
258
387
  when Seasons::ADVENT
259
388
  if date >= Date.new(@year, 12, 17)
260
389
  rank = Ranks::FERIAL_PRIVILEGED
390
+ nth = Ordinalizer.ordinal(date.day)
391
+ title = I18n.t 'temporale.advent.before_christmas', day: nth
261
392
  end
262
393
  when Seasons::CHRISTMAS
263
394
  if date < mother_of_god
@@ -266,32 +397,32 @@ module CalendariumRomanum
266
397
  nth = Ordinalizer.ordinal(date.day - nativity.day + 1) # 1-based counting
267
398
  title = I18n.t 'temporale.christmas.nativity_octave.ferial', day: nth
268
399
  elsif date > epiphany
269
- title = I18n.t "temporale.christmas.after_epiphany.ferial", weekday: I18n.t("weekday.#{date.wday}")
400
+ title = I18n.t 'temporale.christmas.after_epiphany.ferial', weekday: I18n.t("weekday.#{date.wday}")
270
401
  end
271
402
  when Seasons::LENT
272
403
  if week == 0
273
- title = I18n.t "temporale.lent.after_ashes.ferial", weekday: I18n.t("weekday.#{date.wday}")
404
+ title = I18n.t 'temporale.lent.after_ashes.ferial', weekday: I18n.t("weekday.#{date.wday}")
274
405
  elsif date > palm_sunday
275
406
  rank = Ranks::PRIMARY
276
- title = I18n.t "temporale.lent.holy_week.ferial", weekday: I18n.t("weekday.#{date.wday}")
407
+ title = I18n.t 'temporale.lent.holy_week.ferial', weekday: I18n.t("weekday.#{date.wday}")
277
408
  end
278
409
  rank = Ranks::FERIAL_PRIVILEGED unless rank > Ranks::FERIAL_PRIVILEGED
279
410
  when Seasons::EASTER
280
411
  if week == 1
281
412
  rank = Ranks::PRIMARY
282
- title = I18n.t "temporale.easter.octave.ferial", weekday: I18n.t("weekday.#{date.wday}")
413
+ title = I18n.t 'temporale.easter.octave.ferial', weekday: I18n.t("weekday.#{date.wday}")
283
414
  end
284
415
  end
285
416
 
286
417
  week_ord = Ordinalizer.ordinal week
287
418
  title ||= I18n.t "temporale.#{seas.to_sym}.ferial", week: week_ord, weekday: I18n.t("weekday.#{date.wday}")
288
419
 
289
- return Celebration.new title, rank, seas.colour
420
+ self.class.create_celebration title, rank, seas.colour
290
421
  end
291
422
 
292
423
  # helper: difference between two Dates in days
293
424
  def date_difference(d1, d2)
294
- return (d1 - d2).numerator
425
+ (d1 - d2).numerator
295
426
  end
296
427
 
297
428
  # prepare dates of temporale solemnities
@@ -317,11 +448,12 @@ module CalendariumRomanum
317
448
  end
318
449
 
319
450
  def prepare_celebration_date(date_method, celebration)
320
- if date_method.respond_to? :call
321
- date = date_method.call(year)
322
- else
323
- date = public_send(date_method)
324
- end
451
+ date =
452
+ if date_method.respond_to? :call
453
+ date_method.call(year)
454
+ else
455
+ public_send(date_method)
456
+ end
325
457
 
326
458
  add_to =
327
459
  if celebration.feast?