File Coverage

blib/lib/Date/Lectionary/Day.pm
Criterion Covered Total %
statement 476 498 95.5
branch 275 282 97.5
condition 94 96 97.9
subroutine 53 67 79.1
pod 1 1 100.0
total 899 944 95.2


line stmt bran cond sub pod time code
1             package Date::Lectionary::Day;
2              
3 10     10   141 use v5.22;
  10         36  
4 10     10   52 use strict;
  10         18  
  10         207  
5 10     10   46 use warnings;
  10         17  
  10         240  
6              
7 10     10   47 use Moose;
  10         19  
  10         53  
8 10     10   59178 use MooseX::StrictConstructor;
  10         21  
  10         68  
9 10     10   32170 use MooseX::Aliases;
  10         11174  
  10         32  
10 10     10   406362 use Carp;
  10         23  
  10         693  
11 10     10   75 use Try::Catch;
  10         21  
  10         478  
12 10     10   68 use Time::Piece;
  10         18  
  10         84  
13 10     10   915 use Time::Seconds;
  10         32  
  10         636  
14 10     10   59 use Date::Advent;
  10         20  
  10         225  
15 10     10   4801 use Date::Easter;
  10         6165  
  10         547  
16 10     10   65 use Date::Lectionary::Time qw(nextSunday prevSunday closestSunday);
  10         20  
  10         498  
17 10     10   54 use namespace::autoclean;
  10         16  
  10         96  
18 10     10   824 use Moose::Util::TypeConstraints;
  10         21  
  10         73  
19 10     10   20962 use File::Share ':all';
  10         21  
  10         1471  
20 10     10   66 use XML::LibXML;
  10         20  
  10         90  
21              
22             =head1 NAME
23              
24             Date::Lectionary::Day - Determines the Day in the Christian Liturgical Year
25              
26             =head1 VERSION
27              
28             Version 1.20190120
29              
30             =cut
31              
32 10     10   1411 use version; our $VERSION = version->declare("v1.20190120");
  10         19  
  10         73  
33              
34             =head1 SYNOPSIS
35              
36             A helper object for Date::Lectionary to determine the liturgical name(s) and type for the given day according to a given lectionary.
37              
38             =cut
39              
40             enum 'DayType', [qw(fixedFeast moveableFeast Sunday noLect)];
41             enum 'LectionaryType', [qw(acna rcl)];
42             enum 'MultiLect', [qw(yes no)];
43             enum 'IncludeFeasts', [qw(yes no)];
44             enum 'XianSeason', [qw(Advent Christmas Epiphany Ordinary Lent Easter Pentecost NaN)];
45 10     10   1508 no Moose::Util::TypeConstraints;
  10         21  
  10         45  
46              
47             =head1 SUBROUTINES/METHODS/ATTRIBUTES
48              
49             =head2 ATTRIBUTES
50              
51             =head3 date
52              
53             The Time::Piece object date given at object construction.
54              
55             =head3 lectionary
56              
57             An optional attribute given at object creation time. Valid values are 'acna' for the Anglican Church of North America lectionary and 'rcl' for the Revised Common Lectionary. This attribute defaults to 'acna' if no value is given.
58              
59             =head3 type
60              
61             Stores the type of liturgical day. 'fixedFeast' is returned for non-moveable feast days such as Christmas Day. 'moveableFeast' is returned for moveable feast days. Moveable feasts move to a Monday when they occure on a Sunday. 'Sunday' is returned for non-fixed feast Sundays of the liturgical year. 'noLect' is returned for days with no feast day or Sunday readings.
62              
63             =head3 name
64              
65             The name of the day in the lectionary. For noLect days a String representation of the day is returned as the name.
66              
67             =head3 alt
68              
69             The alternative name --- if one is given --- of the day in the lectionary. If there is no alternative name for the day, then the empty string will be returned.
70              
71             =head3 multiLect
72              
73             Returns 'yes' if the day has multiple services with readings associated with it. (E.g. Christmas Day, Easter, etc.) Returns 'no' if the day is a normal lectioanry day with only one service and one set of readings.
74              
75             =head3 subLects
76              
77             An ArrayRef of the names of the multiple services that occur on a multiLect day.
78              
79             =head3 includeFeasts
80              
81             If this is set to 'yes' --- the default value --- the module will include fixed and moveable feasts in its determination of which liturgical Sunday it is.
82              
83             If set to 'no', it will exclude fixed and moveable feasts. Excluding feasts is useful when using Date::Lectionary::Day in combination with a daily lectionary such as Date::Lectioary::Daily where a fixed feast such as The Transfiguration can conflict with determining the Sunday to use for the daily lectionary.
84              
85             =head3 season
86              
87             The liturgical season the day falls within.
88              
89             Valid values are 'Advent', 'Christmas', 'Epiphany', 'Ordinary', 'Lent', 'Easter', or 'Pentecost'.
90              
91             If a date is given that is not a Sunday nor a pricipal holy day 'NaN' will be given for the season.
92              
93             =cut
94              
95             has 'date' => (
96             is => 'ro',
97             isa => 'Time::Piece',
98             required => 1,
99             );
100              
101             has 'type' => (
102             is => 'ro',
103             isa => 'DayType',
104             writer => '_setType',
105             init_arg => undef,
106             );
107              
108             has 'lectionary' => (
109             is => 'ro',
110             isa => 'LectionaryType',
111             default => 'acna',
112             );
113              
114             has 'displayName' => (
115             is => 'ro',
116             isa => 'Str',
117             writer => '_setDisplayName',
118             init_arg => undef,
119             alias => 'name',
120             );
121              
122             has 'altName' => (
123             is => 'ro',
124             isa => 'Str',
125             writer => '_setAltName',
126             init_arg => undef,
127             alias => 'alt',
128             );
129              
130             has 'commonName' => (
131             is => 'ro',
132             isa => 'Str',
133             writer => '_setCommonName',
134             init_arg => undef,
135             );
136              
137             has 'multiLect' => (
138             is => 'ro',
139             isa => 'MultiLect',
140             writer => '_setMultiLect',
141             init_arg => undef,
142             );
143              
144             has 'subLects' => (
145             is => 'ro',
146             isa => 'ArrayRef',
147             writer => '_setSubLects',
148             init_arg => undef,
149             );
150              
151             has 'includeFeasts' => (
152             is => 'ro',
153             isa => 'IncludeFeasts',
154             default => 'yes',
155             );
156              
157             has 'season' => (
158             is => 'ro',
159             isa => 'XianSeason',
160             writer => '_setSeason',
161             init_arg => undef,
162             );
163              
164             =head2 BUILD
165              
166             Constructor for the Date::Lectionary object. Takes a Time::Piect object, C<date>, to create the object.
167              
168             =cut
169              
170             sub BUILD {
171 624     624 1 1081 my $self = shift;
172              
173 624         16000 my $advent = _determineAdvent( $self->date );
174 624         18957 my $easter = _determineEaster( $advent->firstSunday->year + 1 );
175              
176 624         24122 my %commonNameInfo = _determineDay( $self->date, $self->lectionary, $self->includeFeasts, $advent, $easter );
177 624         24569 $self->_setCommonName( $commonNameInfo{commonName} );
178 624         15904 $self->_setDisplayName( _determineDisplayName( $self->lectionary, $commonNameInfo{commonName} ) );
179 624         67941 $self->_setAltName( _determineAltName( $self->lectionary, $commonNameInfo{commonName} ) );
180              
181 624         69392 $self->_setType( $commonNameInfo{type} );
182 624         17677 $self->_setSeason( $commonNameInfo{season} );
183              
184 624         15016 my %multiLectInfo = _determineMultiLect( $self->lectionary, $commonNameInfo{commonName} );
185 624         80236 $self->_setMultiLect( $multiLectInfo{multiLect} );
186 624         17987 $self->_setSubLects( $multiLectInfo{multiNames} );
187             }
188              
189             =head2 _determineMultiLect
190              
191             Private method to determine if the day has multiple lectionary services and readings for the day.
192              
193             =cut
194              
195             sub _determineMultiLect {
196 624     624   1039 my $tradition = shift;
197 624         912 my $commonName = shift;
198              
199 624         1862 my $parser = XML::LibXML->new();
200 624         7193 my $data_location;
201             my $lectionary;
202              
203             try {
204 624     624   12125 $data_location = dist_file( 'Date-Lectionary', 'date_lectionary_xref.xml' );
205 624         112134 $lectionary = $parser->parse_file($data_location);
206             }
207             catch {
208 0     0   0 confess "The lectionary cross reference file could not be found or parsed.";
209 624         3564 };
210              
211 624         355936 my $compiled_xpath;
212              
213             try {
214 624     624   18902 $compiled_xpath = XML::LibXML::XPathExpression->new("/xref/day[\@multi=\"$commonName\"]/alt[\@type='$tradition']");
215             }
216             catch {
217 0     0   0 confess "The XPATH expression to to query the cross reference database could not be compiled.";
218 624         3883 };
219              
220 624         7131 my @multiNames;
221              
222             try {
223 624 100   624   11402 if ( $lectionary->exists($compiled_xpath) ) {
224 30         2383 my @nodes = $lectionary->findnodes($compiled_xpath);
225 30         2425 foreach my $node (@nodes) {
226 90         384 push( @multiNames, $node->textContent );
227             }
228 30         150 return ( multiLect => 'yes', multiNames => \@multiNames );
229             }
230             else {
231 594         48439 return ( multiLect => 'no', multiNames => \@multiNames );
232             }
233             }
234             catch {
235 0     0   0 confess "An unpected error occured while querying the cross reference database.";
236 624         2932 };
237             }
238              
239             =head2 _determineDisplayName
240              
241             Private method to determine the unique display name for the day.
242              
243             =cut
244              
245             sub _determineDisplayName {
246 624     624   1077 my $tradition = shift;
247 624         968 my $commonName = shift;
248              
249 624         2433 my $parser = XML::LibXML->new();
250 624         7836 my $data_location;
251             my $lectionary;
252              
253             try {
254 624     624   12347 $data_location = dist_file( 'Date-Lectionary', 'date_lectionary_xref.xml' );
255 624         126296 $lectionary = $parser->parse_file($data_location);
256             }
257             catch {
258 0     0   0 confess "The lectionary cross reference file could not be found or parsed.";
259 624         3653 };
260              
261 624         356538 my $compiled_xpath;
262             my $multi_xpath;
263              
264             try {
265 624     624   20307 $compiled_xpath = XML::LibXML::XPathExpression->new("/xref/day[\@name=\"$commonName\"]/alt[\@type='$tradition']");
266 624         4462 $multi_xpath = XML::LibXML::XPathExpression->new("/xref/day[\@multi=\"$commonName\"]");
267             }
268             catch {
269 0     0   0 confess "The XPATH expression to to query the cross reference database could not be compiled.";
270 624         4094 };
271              
272 624         6912 my $displayName;
273              
274             try {
275 624     624   11765 $displayName = $lectionary->findvalue($compiled_xpath);
276              
277 624 100       91271 if ( $lectionary->exists($multi_xpath) ) {
    100          
278 30         2215 return $commonName;
279             }
280             elsif ( $displayName eq '' ) {
281 82         6889 return $commonName;
282             }
283             else {
284 512         39436 return $displayName;
285             }
286             }
287             catch {
288 0     0   0 confess "An unpected error occured while querying the cross reference database.";
289 624         2859 };
290              
291             }
292              
293             =head2 _determineAltName
294              
295             Private method to determine if the day has any alternative names for the day.
296              
297             =cut
298              
299             sub _determineAltName {
300 624     624   1143 my $tradition = shift;
301 624         945 my $commonName = shift;
302              
303 624         1881 my $parser = XML::LibXML->new();
304 624         7303 my $data_location;
305             my $lectionary;
306              
307             try {
308 624     624   12128 $data_location = dist_file( 'Date-Lectionary', 'date_lectionary_xref.xml' );
309 624         113164 $lectionary = $parser->parse_file($data_location);
310             }
311             catch {
312 0     0   0 confess "The lectionary cross reference file could not be found or parsed.";
313 624         3517 };
314              
315 624         357590 my $compiled_xpath;
316             my $multi_xpath;
317              
318             try {
319 624     624   18735 $compiled_xpath = XML::LibXML::XPathExpression->new("/xref/day[\@name=\"$commonName\"]/alt[\@type='$tradition-alt']");
320             }
321             catch {
322 0     0   0 confess "The XPATH expression to to query the cross reference database could not be compiled.";
323 624         3934 };
324              
325 624         6769 my $altName;
326              
327             try {
328 624     624   11380 $altName = $lectionary->findvalue($compiled_xpath);
329 624         73988 return $altName;
330             }
331             catch {
332 0     0   0 confess "An unpected error occured while querying the cross reference database.";
333 624         2801 };
334              
335             }
336              
337             =head2 _determineAdvent
338              
339             Private method that takes a Time::Piece date object to returns a Date::Advent object containing the dates for Advent of the current liturgical year.
340              
341             =cut
342              
343             sub _determineAdvent {
344 624     624   1033 my $date = shift;
345              
346 624         1008 my $advent = undef;
347              
348             try {
349 624     624   23308 $advent = Date::Advent->new( date => $date );
350 624         527807 return $advent;
351             }
352             catch {
353 0     0   0 confess "Could not calculate Advent for the given date [" . $date->ymd . "].";
354 624         3735 };
355             }
356              
357             =head2 _determineEaster
358              
359             Private method that takes a four-digit representation of a Common Era year and calculates the date for Easter as a Time::Piece object.
360              
361             =cut
362              
363             sub _determineEaster {
364 624     624   6161 my $easterYear = shift;
365              
366 624         1092 my $easter = undef;
367              
368             try {
369 624     624   12618 my ( $easterMonth, $easterDay ) = easter($easterYear);
370 624         15161 $easter = Time::Piece->strptime( $easterYear . "-" . $easterMonth . "-" . $easterDay, "%Y-%m-%d" );
371 624         58578 return $easter;
372             }
373             catch {
374 0     0   0 confess "Could not calculate Easter for the year [" . $easterYear . "]";
375 624         3756 };
376             }
377              
378             =head2 _determineFeasts
379              
380             Private method that takes the Time::Piece date given at construction and determines if the date is one of many feasts in the liturgical calendar. Feasts are taken from the Anglican Church in North America's revision of the revised common lectionary.
381              
382             =cut
383              
384             sub _determineFeasts {
385 523     523   924 my $date = shift;
386 523         864 my $lectionary = shift;
387              
388 523         1077 my $yesterday = $date - ONE_DAY;
389              
390 523         20204 my $yesterdayName;
391 523 100       1558 if ( $yesterday->wday == 1 ) {
392 27         203 $yesterdayName = _buildMoveableDays( $yesterday, $lectionary );
393             }
394              
395 523 100       3105 if ($yesterdayName) {
396             return (
397 17         90 commonName => $yesterdayName,
398             type => 'moveableFeast',
399             season => 'NaN'
400             );
401             }
402              
403 506         1339 my $fixedDayName = _buildFixedDays( $date, $lectionary );
404 506 100       8317 if ($fixedDayName) {
405             return (
406             commonName => $fixedDayName->{commonName},
407             type => 'fixedFeast',
408             season => $fixedDayName->{season}
409 25         161 );
410             }
411              
412 481         1137 my $moveableDayName = _buildMoveableDays( $date, $lectionary );
413 481 100 100     3504 if ( $moveableDayName && $date->wday != 1 ) {
414             return (
415 28         308 commonName => $moveableDayName,
416             type => 'moveableFeast',
417             season => 'NaN'
418             );
419             }
420              
421 453         2369 return ( commonName => undef, type => undef, season => 'NaN' );
422             }
423              
424             =head2 _buildMoveableDays
425              
426             Private method that takes the Time::Piece date given at construction and determines if the date is one of many moveable feasts in the liturgical calendar. Feasts are taken from the Anglican Church in North America's revision of the revised common lectionary.
427              
428             =cut
429              
430             sub _buildMoveableDays {
431 508     508   811 my $date = shift;
432 508         753 my $lectionary = shift;
433              
434             #Moveable holidays in January
435 508 100       1052 if ( $date->mon == 1 ) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
436 57 100 100     293 if ( $date->mday == 18 && $lectionary eq 'acna' ) {
437 4         34 return "Confession of St. Peter";
438             }
439 53 100 100     297 if ( $date->mday == 25 && $lectionary eq 'acna' ) {
440 4         38 return "Conversion of St. Paul";
441             }
442             }
443              
444             #Moveable holidays in February
445             elsif ( $date->mon == 2 ) {
446 47 100       433 if ( $date->mday == 2 ) {
447 4         25 return "The Presentation of Christ in the Temple";
448             }
449 43 100 100     231 if ( $date->mday == 24 && $lectionary eq 'acna' ) {
450 2         22 return "St. Matthias";
451             }
452             }
453              
454             #Moveable holidays in March
455             elsif ( $date->mon == 3 ) {
456 36 100 100     444 if ( $date->mday == 19 && $lectionary eq 'acna' ) {
457 4         34 return "St. Joseph";
458             }
459 32 100       206 if ( $date->mday == 25 ) {
460 2         16 return "The Annunciation";
461             }
462             }
463              
464             #Moveable holidays in April
465             elsif ( $date->mon == 4 ) {
466 34 100 100     540 if ( $date->mday == 25 && $lectionary eq 'acna' ) {
467 1         14 return "St. Mark";
468             }
469             }
470              
471             #Moveable holidays in May
472             elsif ( $date->mon == 5 ) {
473 43 100 100     784 if ( $date->mday == 1 && $lectionary eq 'acna' ) {
474 4         37 return "St. Philip & St. James";
475             }
476 39 100       240 if ( $date->mday == 31 ) {
477 6         39 return "The Visitation";
478             }
479             }
480              
481             #Moveable holidays in June
482             elsif ( $date->mon == 6 ) {
483 41 100 100     863 if ( $date->mday == 11 && $lectionary eq 'acna' ) {
484 4         35 return "St. Barnabas";
485             }
486 37 100 100     257 if ( $date->mday == 24 && $lectionary eq 'acna' ) {
487 1         11 return "Nativity of St. John the Baptist";
488             }
489 36 100 100     188 if ( $date->mday == 29 && $lectionary eq 'acna' ) {
490 1         13 return "St. Peter & St. Paul";
491             }
492             }
493              
494             #Moveable holidays in July
495             elsif ( $date->mon == 7 ) {
496 49 100 100     1240 if ( $date->mday == 22 && $lectionary eq 'acna' ) {
497 2         24 return "St. Mary Magdalene";
498             }
499 47 100 100     293 if ( $date->mday == 25 && $lectionary eq 'acna' ) {
500 1         13 return "St. James";
501             }
502             }
503              
504             #Moveable holidays in August
505             elsif ( $date->mon == 8 ) {
506 41 100 100     1063 if ( $date->mday == 15 && $lectionary eq 'acna' ) {
507 1         14 return "St. Mary the Virgin";
508             }
509 40 100 100     216 if ( $date->mday == 24 && $lectionary eq 'acna' ) {
510 1         12 return "St. Bartholomew";
511             }
512             }
513              
514             #Moveable holidays in September
515             elsif ( $date->mon == 9 ) {
516 42 100       1316 if ( $date->mday == 14 ) {
517 2         14 return "Holy Cross Day";
518             }
519 40 100 100     220 if ( $date->mday == 21 && $lectionary eq 'acna' ) {
520 1         17 return "St. Matthew";
521             }
522 39 100 100     218 if ( $date->mday == 29 && $lectionary eq 'acna' ) {
523 1         12 return "Holy Michael & All Angels";
524             }
525             }
526              
527             #Moveable holidays in October
528             elsif ( $date->mon == 10 ) {
529 51 100 100     1784 if ( $date->mday == 18 && $lectionary eq 'acna' ) {
530 6         59 return "St. Luke";
531             }
532 45 100 100     262 if ( $date->mday == 28 && $lectionary eq 'acna' ) {
533 1         14 return "St. Simon & St. Jude";
534             }
535             }
536              
537             #Moveable holidays in November
538             elsif ( $date->mon == 11 ) {
539 46 100 100     1771 if ( $date->mday == 30 && $lectionary eq 'acna' ) {
540 1         12 return "St. Andrew";
541             }
542             }
543              
544             #Moveable holidays in December
545             elsif ( $date->mon == 12 ) {
546 21 100 100     969 if ( $date->mday == 21 && $lectionary eq 'acna' ) {
547 1         13 return "St. Thomas";
548             }
549 20 100 100     127 if ( $date->mday == 26 && $lectionary eq 'acna' ) {
550 2         20 return "St. Stephen";
551             }
552 18 100 100     122 if ( $date->mday == 27 && $lectionary eq 'acna' ) {
553 4         36 return "St. John";
554             }
555 14 100 100     91 if ( $date->mday == 28 && $lectionary eq 'acna' ) {
556 1         12 return "Holy Innocents";
557             }
558             }
559             else {
560 0         0 confess "Date [" . $date->ymd . "] is not a known or valid date.";
561             }
562             }
563              
564             =head2 _buildFixedDays
565              
566             Private method that takes the Time::Piece date given at construction and determines if the date is one of many fixed (non-moveable) feasts in the liturgical calendar. Fixed feasts are taken from the Anglican Church in North America's revision of the revised common lectionary.
567              
568             =cut
569              
570             sub _buildFixedDays {
571 506     506   833 my $date = shift;
572 506         1088 my $lectionary = shift;
573              
574             #Fixed holidays in January
575 506 100       1054 if ( $date->mon == 1 ) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
576 60 100       397 if ( $date->mday == 1 ) {
577             return {
578 6         49 commonName => "Holy Name",
579             season => 'Christmas'
580             };
581             }
582 54 100       291 if ( $date->mday == 6 ) {
583             return {
584 4         38 commonName => "The Epiphany",
585             season => 'Epiphany'
586             };
587             }
588             }
589              
590             #Fixed holidays in February
591             elsif ( $date->mon == 2 ) {
592             }
593              
594             #Fixed holidays in March
595             elsif ( $date->mon == 3 ) {
596             }
597              
598             #Fixed holidays in April
599             elsif ( $date->mon == 4 ) {
600             }
601              
602             #Fixed holidays in May
603             elsif ( $date->mon == 5 ) {
604             }
605              
606             #Fixed holidays in June
607             elsif ( $date->mon == 6 ) {
608             }
609              
610             #Fixed holidays in July
611             elsif ( $date->mon == 7 ) {
612             }
613              
614             #Fixed holidays in August
615             elsif ( $date->mon == 8 ) {
616 44 100 100     1175 if ( $date->mday == 6 && $lectionary eq 'acna' ) {
617             return {
618 3         40 commonName => "The Transfiguration",
619             season => 'Ordinary'
620             };
621             }
622             }
623              
624             #Fixed holidays in September
625             elsif ( $date->mon == 9 ) {
626             }
627              
628             #Fixed holidays in October
629             elsif ( $date->mon == 10 ) {
630             }
631              
632             #Fixed holidays in November
633             elsif ( $date->mon == 11 ) {
634 50 100       1852 if ( $date->mday == 1 ) {
635             return {
636 4         37 commonName => "All Saints' Day",
637             season => 'Ordinary'
638             };
639             }
640             }
641              
642             #Fixed holidays in December
643             elsif ( $date->mon == 12 ) {
644 25 100       1176 if ( $date->mday == 25 ) {
645             return {
646 8         84 commonName => "Christmas Day",
647             season => 'Christmas'
648             };
649             }
650             }
651             else {
652 0         0 confess "Date [" . $date->ymd . "] is not a known or valid date.";
653             }
654             }
655              
656             =head2 _determineAshWednesday
657              
658             Private method that takes the Time::Piece date for Easter and determines the date for Ash Wednesday. Ash Wednesday is the start of Lent. It occurs 46 days before Easter for the given year.
659              
660             =cut
661              
662             sub _determineAshWednesday {
663 575     575   943 my $easter = shift;
664              
665 575         872 my $ashWednesday = undef;
666              
667             try {
668 575     575   10362 my $secondsToSubtract = 46 * ONE_DAY;
669 575         1327 $ashWednesday = $easter - $secondsToSubtract;
670 575         26490 return $ashWednesday;
671             }
672             catch {
673 0     0   0 confess "Could not calculate Ash Wednesday for Easter [" . $easter->ymd . "].";
674 575         3796 };
675             }
676              
677             =head2 _determineAscension
678              
679             Private method that takes the Time::Piece date for Easter and determines the date for Ascension. Ascension is forty days (inclusive) after Easter.
680              
681             =cut
682              
683             sub _determineAscension {
684 539     539   823 my $easter = shift;
685              
686 539         1046 my $ascension = undef;
687              
688             try {
689 539     539   9759 my $secondsToAdd = 39 * ONE_DAY;
690 539         1153 $ascension = $easter + $secondsToAdd;
691 539         20002 return $ascension;
692             }
693             catch {
694 0     0   0 confess "Could not calculate Ascension for Easter [" . $easter->ymd . "].";
695 539         3557 };
696             }
697              
698             =head2 _determinePentecost
699              
700             Private method the takes the Time::Piece date for Easter and determines the date for Pentecost. Pentecost is fifty days (inclusive) after Easter.
701              
702             =cut
703              
704             sub _determinePentecost {
705 536     536   836 my $easter = shift;
706              
707 536         745 my $pentecost = undef;
708              
709             try {
710 536     536   9357 my $secondsToAdd = 49 * ONE_DAY;
711 536         1167 $pentecost = $easter + $secondsToAdd;
712 536         20188 return $pentecost;
713             }
714             catch {
715 0     0   0 confess "Could not calculate Pentecost for Easter [" . $easter->ymd . "].";
716 536         2981 };
717             }
718              
719             =head2 _determineHolyWeek
720              
721             Private method used to return the names of various days within Holy Week. Takes the Time::Piece date given at construction and the Time::Piece date for Easter. Returns undef if the date given at construction is not found in Holy Week.
722              
723             =cut
724              
725             sub _determineHolyWeek {
726 572     572   932 my $date = shift;
727 572         872 my $easter = shift;
728              
729 572         1187 my $dateMark = $easter - ONE_DAY;
730 572 100       23386 if ( $date == $dateMark ) {
731 3         64 return "Holy Saturday";
732             }
733              
734 569         11055 $dateMark = $dateMark - ONE_DAY;
735 569 100       22377 if ( $date == $dateMark ) {
736 3         70 return "Good Friday";
737             }
738              
739 566         10786 $dateMark = $dateMark - ONE_DAY;
740 566 100       21733 if ( $date == $dateMark ) {
741 2         48 return "Maundy Thursday";
742             }
743              
744 564         10594 $dateMark = $dateMark - ONE_DAY;
745 564 100       21413 if ( $date == $dateMark ) {
746 2         49 return "Wednesday in Holy Week";
747             }
748              
749 562         10761 $dateMark = $dateMark - ONE_DAY;
750 562 100       21306 if ( $date == $dateMark ) {
751 2         49 return "Tuesday in Holy Week";
752             }
753              
754 560         10580 $dateMark = $dateMark - ONE_DAY;
755 560 100       21404 if ( $date == $dateMark ) {
756 2         52 return "Monday in Holy Week";
757             }
758              
759 558         10449 $dateMark = $dateMark - ONE_DAY;
760 558 100       21090 if ( $date == $dateMark ) {
761 9         176 return "Palm Sunday";
762             }
763              
764 549         10524 return undef;
765             }
766              
767             =head2 _determineEasterWeek
768              
769             Private method used to return the names of various days within Easter Week. Takes the Time::Piece date given at construction and the Time::Piece date for Easter. Returns undef if the date given at construction is not found in Easter Week.
770              
771             =cut
772              
773             sub _determineEasterWeek {
774 549     549   835 my $date = shift;
775 549         800 my $easter = shift;
776              
777 549         1226 my $dateMark = $easter + ONE_DAY;
778 549 100       20143 if ( $date == $dateMark ) {
779 2         48 return "Monday of Easter Week";
780             }
781              
782 547         10590 $dateMark = $dateMark + ONE_DAY;
783 547 100       19197 if ( $date == $dateMark ) {
784 4         88 return "Tuesday of Easter Week";
785             }
786              
787 543         10256 $dateMark = $dateMark + ONE_DAY;
788 543 100       19202 if ( $date == $dateMark ) {
789 1         25 return "Wednesday of Easter Week";
790             }
791              
792 542         10159 $dateMark = $dateMark + ONE_DAY;
793 542 100       18731 if ( $date == $dateMark ) {
794 1         24 return "Thursday of Easter Week";
795             }
796              
797 541         10116 $dateMark = $dateMark + ONE_DAY;
798 541 100       18869 if ( $date == $dateMark ) {
799 1         27 return "Friday of Easter Week";
800             }
801              
802 540         10163 $dateMark = $dateMark + ONE_DAY;
803 540 100       19193 if ( $date == $dateMark ) {
804 1         25 return "Saturday of Easter Week";
805             }
806              
807 539         10234 return undef;
808             }
809              
810             =head2 _hasChristmas2
811              
812             Private method to determine if there is a second Sunday of Christmas in the current liturgical year. Returns 1 when there is a second Sunday of Christmas and 0 otherwise.
813              
814             =cut
815              
816             sub _hasChristmas2 {
817 79     79   135 my $advent = shift;
818 79         106 my $epiphany = shift;
819              
820 79         2311 my $firstChristmas = nextSunday( $advent->fourthSunday );
821 79         8810 my $dateMarker = nextSunday($firstChristmas);
822              
823 79 100       7390 if ( $dateMarker < $epiphany ) {
824 65         1342 return 1;
825             }
826             else {
827 14         287 return 0;
828             }
829              
830 0         0 return 0;
831             }
832              
833             =head2 _determineChristmasEpiphany
834              
835             Private method that matches the date given at construction against the Sundays in Christmastide and Epiphany. Returns a string representation of the name of the Sunday in the lectionary.
836              
837             =cut
838              
839             sub _determineChristmasEpiphany {
840 79     79   134 my $date = shift;
841              
842 79         106 my $advent = shift;
843              
844 79         106 my $ashWednesday = shift;
845              
846 79         112 my $lectionary = shift;
847              
848 79         168 my $epiphany = Time::Piece->strptime( $date->year . "-01-06", "%Y-%m-%d" );
849              
850 79         7656 my $christmas2 = _hasChristmas2( $advent, $epiphany );
851              
852             #Is the date in Christmastide?
853 79         2040 my $dateMarker = nextSunday( $advent->fourthSunday );
854 79 100       7887 if ( $date == $dateMarker ) {
855 6         174 return "The First Sunday of Christmas";
856             }
857              
858 73         1442 $dateMarker = nextSunday($dateMarker);
859 73 100 100     6589 if ( $date == $dateMarker && $christmas2 == 1 ) {
    100          
860 6         153 return "The Second Sunday of Christmas";
861             }
862             elsif ( $date == $dateMarker ) {
863 1         40 return "The First Sunday of Epiphany";
864             }
865              
866 66         2441 my @epiphanySundays = ( "The First Sunday of Epiphany", "The Second Sunday of Epiphany", "The Third Sunday of Epiphany", "The Fourth Sunday of Epiphany", "The Fifth Sunday of Epiphany", "The Sixth Sunday of Epiphany", "The Seventh Sunday of Epiphany", "The Last Sunday after Epiphany" );
867              
868             #Is the date in Epiphany?
869 66         108 my $sunCount = 0;
870 66         154 foreach my $sunday (@epiphanySundays) {
871 236         466 $dateMarker = nextSunday($dateMarker);
872 236 100 100     21539 if ( $date == $dateMarker && $date == prevSunday($ashWednesday) ) {
873 10         1370 return "The Last Sunday after Epiphany";
874             }
875 226 100 100     10675 if ( $date == $dateMarker && $date == prevSunday( prevSunday($ashWednesday) ) && $lectionary eq 'acna' ) {
      100        
876 7         1561 return "The Second to Last Sunday after Epiphany";
877             }
878              
879 219 100 100     13355 if ( $date == $dateMarker && $christmas2 == 1 ) {
    100 100        
    100 66        
880 44         1235 return $epiphanySundays[$sunCount];
881             }
882             elsif ( $date == $dateMarker && $epiphany->wday == 1 ) {
883 2         94 return $epiphanySundays[$sunCount];
884             }
885             elsif ( $date == $dateMarker && $christmas2 == 0 ) {
886 3         174 return $epiphanySundays[ $sunCount + 1 ];
887             }
888              
889 170         7879 $sunCount++;
890             }
891              
892 0         0 confess "There are no further Sundays of Christmastide or Epiphany.";
893             }
894              
895             =head2 _determineLent
896              
897             Private method that matches the date given at construction against the Sundays in Lent. Returns a string representation of the name of the Sunday in the lectionary.
898              
899             =cut
900              
901             sub _determineLent {
902 46     46   85 my $date = shift;
903 46         68 my $ashWednesday = shift;
904              
905 46         154 my $dateMarker = nextSunday($ashWednesday);
906 46 100       4780 if ( $date == $dateMarker ) {
907 10         258 return "The First Sunday in Lent";
908             }
909              
910 36         706 $dateMarker = nextSunday($dateMarker);
911 36 100       3547 if ( $date == $dateMarker ) {
912 9         214 return "The Second Sunday in Lent";
913             }
914              
915 27         518 $dateMarker = nextSunday($dateMarker);
916 27 100       2440 if ( $date == $dateMarker ) {
917 9         238 return "The Third Sunday in Lent";
918             }
919              
920 18         363 $dateMarker = nextSunday($dateMarker);
921 18 100       1628 if ( $date == $dateMarker ) {
922 9         219 return "The Fourth Sunday in Lent";
923             }
924              
925 9         196 $dateMarker = nextSunday($dateMarker);
926 9 50       819 if ( $date == $dateMarker ) {
927 9         220 return "The Fifth Sunday in Lent";
928             }
929              
930 0         0 confess "There are no further Sundays in Lent";
931             }
932              
933             =head2 _determineEasterSeason
934              
935             Private method that matches the date given at construction against the Sundays in the Easter season. Returns a string representation of the name of the Sunday in the lectionary.
936              
937             =cut
938              
939             sub _determineEasterSeason {
940 56     56   99 my $date = shift;
941 56         77 my $easter = shift;
942              
943 56         183 my $dateMarker = nextSunday($easter);
944 56 100       5804 if ( $date == $dateMarker ) {
945 9         239 return "The Second Sunday of Easter";
946             }
947              
948 47         931 $dateMarker = nextSunday($dateMarker);
949 47 100       4262 if ( $date == $dateMarker ) {
950 9         212 return "The Third Sunday of Easter";
951             }
952              
953 38         749 $dateMarker = nextSunday($dateMarker);
954 38 100       3431 if ( $date == $dateMarker ) {
955 11         264 return "The Fourth Sunday of Easter";
956             }
957              
958 27         560 $dateMarker = nextSunday($dateMarker);
959 27 100       2403 if ( $date == $dateMarker ) {
960 9         215 return "The Fifth Sunday of Easter";
961             }
962              
963 18         370 $dateMarker = nextSunday($dateMarker);
964 18 100       1593 if ( $date == $dateMarker ) {
965 9         216 return "The Sixth Sunday of Easter";
966             }
967              
968 9         180 $dateMarker = nextSunday($dateMarker);
969 9 50       791 if ( $date == $dateMarker ) {
970 9         245 return "The Sunday after Ascension Day";
971             }
972              
973 0         0 confess "There are no further Sundays of Easter for [" . $date->ymd . "].";
974             }
975              
976             =head2 _determineOrdinary
977              
978             Private method that matches the date given at construction against the Sundays in Ordinary time, e.g. Trinity Sunday and following Sundays. Returns a string representation of the name of the Sunday in the lectionary.
979              
980             =cut
981              
982             sub _determineOrdinary {
983 242     242   372 my $date = shift;
984 242         326 my $pentecost = shift;
985              
986 242         796 my $trinitySunday = nextSunday($pentecost);
987 242 100       25004 if ( $date == $trinitySunday ) {
988 9         222 return "Trinity Sunday";
989             }
990              
991 233         4617 my $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-05-25", "%Y-%m-%d" ) );
992 233 50       108837 if ( $date == $dateMarker ) {
993 0         0 return "Ordinary 8";
994             }
995              
996 233         4316 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-01", "%Y-%m-%d" ) );
997 233 100       103941 if ( $date == $dateMarker ) {
998 3         71 return "Ordinary 9";
999             }
1000              
1001 230         4628 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-08", "%Y-%m-%d" ) );
1002 230 100       101802 if ( $date == $dateMarker ) {
1003 6         142 return "Ordinary 10";
1004             }
1005              
1006 224         4114 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-15", "%Y-%m-%d" ) );
1007 224 100       98626 if ( $date == $dateMarker ) {
1008 9         214 return "Ordinary 11";
1009             }
1010              
1011 215         3979 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-22", "%Y-%m-%d" ) );
1012 215 100       94756 if ( $date == $dateMarker ) {
1013 9         216 return "Ordinary 12";
1014             }
1015              
1016 206         3809 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-29", "%Y-%m-%d" ) );
1017 206 100       90883 if ( $date == $dateMarker ) {
1018 10         252 return "Ordinary 13";
1019             }
1020              
1021 196         3637 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-07-06", "%Y-%m-%d" ) );
1022 196 100       85730 if ( $date == $dateMarker ) {
1023 9         219 return "Ordinary 14";
1024             }
1025              
1026 187         3437 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-07-13", "%Y-%m-%d" ) );
1027 187 100       81657 if ( $date == $dateMarker ) {
1028 9         216 return "Ordinary 15";
1029             }
1030              
1031 178         3348 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-07-20", "%Y-%m-%d" ) );
1032 178 100       78889 if ( $date == $dateMarker ) {
1033 9         206 return "Ordinary 16";
1034             }
1035              
1036 169         3122 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-07-27", "%Y-%m-%d" ) );
1037 169 100       73923 if ( $date == $dateMarker ) {
1038 9         208 return "Ordinary 17";
1039             }
1040              
1041 160         3001 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-03", "%Y-%m-%d" ) );
1042 160 100       69930 if ( $date == $dateMarker ) {
1043 8         184 return "Ordinary 18";
1044             }
1045              
1046 152         2788 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-10", "%Y-%m-%d" ) );
1047 152 100       66142 if ( $date == $dateMarker ) {
1048 9         207 return "Ordinary 19";
1049             }
1050              
1051 143         2751 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-17", "%Y-%m-%d" ) );
1052 143 100       62513 if ( $date == $dateMarker ) {
1053 9         207 return "Ordinary 20";
1054             }
1055              
1056 134         2595 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-24", "%Y-%m-%d" ) );
1057 134 100       58590 if ( $date == $dateMarker ) {
1058 9         213 return "Ordinary 21";
1059             }
1060              
1061 125         2300 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-31", "%Y-%m-%d" ) );
1062 125 100       55130 if ( $date == $dateMarker ) {
1063 9         217 return "Ordinary 22";
1064             }
1065              
1066 116         2159 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-09-07", "%Y-%m-%d" ) );
1067 116 100       50846 if ( $date == $dateMarker ) {
1068 9         217 return "Ordinary 23";
1069             }
1070              
1071 107         2112 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-09-14", "%Y-%m-%d" ) );
1072 107 100       47675 if ( $date == $dateMarker ) {
1073 9         238 return "Ordinary 24";
1074             }
1075              
1076 98         2127 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-09-21", "%Y-%m-%d" ) );
1077 98 100       43298 if ( $date == $dateMarker ) {
1078 9         216 return "Ordinary 25";
1079             }
1080              
1081 89         1684 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-09-28", "%Y-%m-%d" ) );
1082 89 100       38981 if ( $date == $dateMarker ) {
1083 9         221 return "Ordinary 26";
1084             }
1085              
1086 80         1528 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-10-05", "%Y-%m-%d" ) );
1087 80 100       35329 if ( $date == $dateMarker ) {
1088 9         218 return "Ordinary 27";
1089             }
1090              
1091 71         1323 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-10-12", "%Y-%m-%d" ) );
1092 71 100       31620 if ( $date == $dateMarker ) {
1093 9         209 return "Ordinary 28";
1094             }
1095              
1096 62         1238 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-10-19", "%Y-%m-%d" ) );
1097 62 100       27170 if ( $date == $dateMarker ) {
1098 9         221 return "Ordinary 29";
1099             }
1100              
1101 53         998 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-10-26", "%Y-%m-%d" ) );
1102 53 100       23184 if ( $date == $dateMarker ) {
1103 9         231 return "Ordinary 30";
1104             }
1105              
1106 44         833 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-11-02", "%Y-%m-%d" ) );
1107 44 100       19177 if ( $date == $dateMarker ) {
1108 6         162 return "Ordinary 31";
1109             }
1110              
1111 38         771 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-11-09", "%Y-%m-%d" ) );
1112 38 100       16509 if ( $date == $dateMarker ) {
1113 9         216 return "Ordinary 32";
1114             }
1115              
1116 29         551 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-11-16", "%Y-%m-%d" ) );
1117 29 100       12908 if ( $date == $dateMarker ) {
1118 17         399 return "Ordinary 33";
1119             }
1120              
1121 12         270 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-11-23", "%Y-%m-%d" ) );
1122 12 50       5284 if ( $date == $dateMarker ) {
1123 12         309 return "Christ the King";
1124             }
1125              
1126 0         0 confess "There are no further Sundays of Ordinary Time.";
1127             }
1128              
1129             =head2 _determineDay
1130              
1131             Private method that takes the Time::Piece data given at construction and, using other private methods, determines the name of the Feast Day or Sunday in the lectionary. If the date given at construction is a fixed feast, that day will be returned. If the date given is a special feast -- e.g. Easter, Ash Wednesday, etc. -- or a Sunday the name of that day will be returned. If the date isn't a special feast or a Sunday the date represented as a string will be returned as the name with no associated readings.
1132              
1133             =cut
1134              
1135             sub _determineDay {
1136 624     624   1209 my $date = shift;
1137 624         940 my $lectionary = shift;
1138 624         922 my $includeFeasts = shift;
1139              
1140 624         956 my $advent = shift;
1141 624         942 my $easter = shift;
1142              
1143             #Is the date in Advent?
1144 624 100       12189 if ( $date == $advent->firstSunday ) {
    100          
    100          
    100          
1145             return (
1146 9         264 commonName => "The First Sunday in Advent",
1147             type => 'Sunday',
1148             season => 'Advent'
1149             );
1150             }
1151             elsif ( $date == $advent->secondSunday ) {
1152             return (
1153 9         605 commonName => "The Second Sunday in Advent",
1154             type => 'Sunday',
1155             season => 'Advent'
1156             );
1157             }
1158             elsif ( $date == $advent->thirdSunday ) {
1159             return (
1160 9         945 commonName => "The Third Sunday in Advent",
1161             type => 'Sunday',
1162             season => 'Advent'
1163             );
1164             }
1165             elsif ( $date == $advent->fourthSunday ) {
1166             return (
1167 9         1283 commonName => "The Fourth Sunday in Advent",
1168             type => 'Sunday',
1169             season => 'Advent'
1170             );
1171             }
1172              
1173             #Is the date Easter Sunday?
1174 588 100       84867 if ( $date == $easter ) {
1175             return (
1176 13         260 commonName => "Easter Day",
1177             type => 'fixedFeast',
1178             season => 'Easter'
1179             );
1180             }
1181              
1182             #Determine when Ash Wednesday is
1183 575         10129 my $ashWednesday = _determineAshWednesday($easter);
1184 575 100       8032 if ( $date == $ashWednesday ) {
1185             return (
1186 3         124 commonName => "Ash Wednesday",
1187             type => 'fixedFeast',
1188             season => 'Lent'
1189             );
1190             }
1191              
1192             #Holy Week
1193 572         11880 my $holyWeekDay = _determineHolyWeek( $date, $easter );
1194 572 100       1369 if ($holyWeekDay) {
1195             return (
1196 23         138 commonName => $holyWeekDay,
1197             type => 'fixedFeast',
1198             season => 'Lent'
1199             );
1200             }
1201              
1202             #Easter Week
1203 549         1135 my $easterWeekDay = _determineEasterWeek( $date, $easter );
1204 549 100       1290 if ($easterWeekDay) {
1205             return (
1206 10         60 commonName => $easterWeekDay,
1207             type => 'fixedFeast',
1208             season => 'Easter'
1209             );
1210             }
1211              
1212             #Ascension is 40 days after Easter
1213 539         1281 my $ascension = _determineAscension($easter);
1214 539 100       7029 if ( $date == $ascension ) {
1215             return (
1216 3         77 commonName => "Ascension Day",
1217             type => 'fixedFeast',
1218             season => 'Easter'
1219             );
1220             }
1221              
1222             #Pentecost is 50 days after Easter
1223 536         11023 my $pentecost = _determinePentecost($easter);
1224 536 100       6651 if ( $date == $pentecost ) {
1225             return (
1226 12         290 commonName => "Pentecost",
1227             type => 'fixedFeast',
1228             season => 'Pentecost'
1229             );
1230             }
1231              
1232             #Feast Day Celebrations
1233 524 100       10726 if ( $includeFeasts eq 'yes' ) {
1234 523         1483 my %feastDay = _determineFeasts( $date, $lectionary );
1235 523 100       1967 if ( $feastDay{commonName} ) {
1236             return (
1237             commonName => $feastDay{commonName},
1238             type => $feastDay{type},
1239             season => $feastDay{season}
1240 70         468 );
1241             }
1242             }
1243              
1244             #If the date isn't a Sunday and we've determined it is not a fixed holiday
1245             #then there are no readings for that day.
1246 454 100       1088 if ( $date->wday != 1 ) {
1247             return (
1248 31         239 commonName => $date->fullday . ', ' . $date->fullmonth . ' ' . $date->mday . ', ' . $date->year,
1249             type => 'noLect',
1250             season => 'NaN'
1251             );
1252             }
1253              
1254             #Sundays of the Liturgical Year
1255 423 100       2523 if ( $date < $ashWednesday ) {
1256 79         1691 my %xmasEpiphany = (
1257             commonName => _determineChristmasEpiphany( $date, $advent, $ashWednesday, $lectionary ),
1258             type => 'Sunday'
1259             );
1260              
1261 79 100       451 if ( $xmasEpiphany{commonName} =~ m/Christmas/ig ) {
1262 12         47 $xmasEpiphany{season} = 'Christmas';
1263 12         82 return %xmasEpiphany;
1264             }
1265             else {
1266 67         155 $xmasEpiphany{season} = 'Epiphany';
1267 67         408 return %xmasEpiphany;
1268             }
1269             }
1270              
1271 344 100       6754 if ( $date < $easter ) {
1272             return (
1273 46         843 commonName => _determineLent( $date, $ashWednesday ),
1274             type => 'Sunday',
1275             season => 'Lent'
1276             );
1277             }
1278              
1279 298 100 66     4862 if ( $date > $easter && $date < $pentecost ) {
1280             return (
1281 56         1869 commonName => _determineEasterSeason( $date, $easter ),
1282             type => 'Sunday',
1283             season => 'Easter'
1284             );
1285             }
1286              
1287 242 50       7765 if ( $date > $pentecost ) {
1288             return (
1289 242         4243 commonName => _determineOrdinary( $date, $pentecost ),
1290             type => 'Sunday',
1291             season => 'Ordinary'
1292             );
1293             }
1294             }
1295              
1296             =head1 AUTHOR
1297              
1298             Michael Wayne Arnold, C<< <michael at rnold.info> >>
1299              
1300             =head1 BUGS
1301              
1302             Please report any bugs or feature requests to C<bug-date-lectionary at rt.cpan.org>, or through
1303             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Date-Lectionary-Day>. I will be notified, and then you'll
1304             automatically be notified of progress on your bug as I make changes.
1305              
1306             =head1 SUPPORT
1307              
1308             You can find documentation for this module with the perldoc command.
1309              
1310             perldoc Date::Lectionary::Day
1311              
1312              
1313             You can also look for information at:
1314              
1315             =over 4
1316              
1317             =item * RT: CPAN's request tracker (report bugs here)
1318              
1319             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Date-Lectionary-Day>
1320              
1321             =item * AnnoCPAN: Annotated CPAN documentation
1322              
1323             L<http://annocpan.org/dist/Date-Lectionary-Day>
1324              
1325             =item * CPAN Ratings
1326              
1327             L<http://cpanratings.perl.org/d/Date-Lectionary-Day>
1328              
1329             =item * Search CPAN
1330              
1331             L<http://search.cpan.org/dist/Date-Lectionary-Day/>
1332              
1333             =back
1334              
1335             =head1 ACKNOWLEDGEMENTS
1336              
1337             Many thanks to my beautiful wife, Jennifer, my amazing daughter, Rosemary, and my sweet son, Oliver. But, above all, SOLI DEO GLORIA!
1338              
1339             =head1 LICENSE
1340              
1341             Copyright 2016-2018 MICHAEL WAYNE ARNOLD
1342              
1343             Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1344              
1345             1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
1346              
1347             2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
1348              
1349             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1350              
1351              
1352             =cut
1353              
1354             __PACKAGE__->meta->make_immutable;
1355              
1356             1; # End of Date::Lectionary::Day