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   133 use v5.22;
  10         35  
4 10     10   104 use strict;
  10         25  
  10         221  
5 10     10   51 use warnings;
  10         28  
  10         241  
6              
7 10     10   53 use Moose;
  10         24  
  10         54  
8 10     10   63505 use MooseX::StrictConstructor;
  10         21  
  10         65  
9 10     10   35188 use MooseX::Aliases;
  10         13120  
  10         42  
10 10     10   455940 use Carp;
  10         24  
  10         754  
11 10     10   72 use Try::Catch;
  10         24  
  10         633  
12 10     10   78 use Time::Piece;
  10         26  
  10         115  
13 10     10   1172 use Time::Seconds;
  10         36  
  10         693  
14 10     10   63 use Date::Advent;
  10         20  
  10         262  
15 10     10   5219 use Date::Easter;
  10         7094  
  10         624  
16 10     10   82 use Date::Lectionary::Time qw(nextSunday prevSunday closestSunday);
  10         22  
  10         495  
17 10     10   68 use namespace::autoclean;
  10         20  
  10         86  
18 10     10   928 use Moose::Util::TypeConstraints;
  10         24  
  10         79  
19 10     10   23709 use File::Share ':all';
  10         25  
  10         1679  
20 10     10   74 use XML::LibXML;
  10         21  
  10         93  
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.20200203
29              
30             =cut
31              
32 10     10   1801 use version; our $VERSION = version->declare("v1.20200203");
  10         23  
  10         77  
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   1645 no Moose::Util::TypeConstraints;
  10         22  
  10         68  
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 625     625 1 1118 my $self = shift;
172              
173 625         17620 my $advent = _determineAdvent( $self->date );
174 625         21391 my $easter = _determineEaster( $advent->firstSunday->year + 1 );
175              
176 625         26915 my %commonNameInfo = _determineDay( $self->date, $self->lectionary, $self->includeFeasts, $advent, $easter );
177 625         26385 $self->_setCommonName( $commonNameInfo{commonName} );
178 625         17436 $self->_setDisplayName( _determineDisplayName( $self->lectionary, $commonNameInfo{commonName} ) );
179 625         75647 $self->_setAltName( _determineAltName( $self->lectionary, $commonNameInfo{commonName} ) );
180              
181 625         77776 $self->_setType( $commonNameInfo{type} );
182 625         19170 $self->_setSeason( $commonNameInfo{season} );
183              
184 625         16368 my %multiLectInfo = _determineMultiLect( $self->lectionary, $commonNameInfo{commonName} );
185 625         89420 $self->_setMultiLect( $multiLectInfo{multiLect} );
186 625         19684 $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 625     625   1178 my $tradition = shift;
197 625         956 my $commonName = shift;
198              
199 625         1979 my $parser = XML::LibXML->new();
200 625         8117 my $data_location;
201             my $lectionary;
202              
203             try {
204 625     625   13810 $data_location = dist_file( 'Date-Lectionary', 'date_lectionary_xref.xml' );
205 625         122262 $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 625         3476 };
210              
211 625         407062 my $compiled_xpath;
212              
213             try {
214 625     625   21516 $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 625         4032 };
219              
220 625         7972 my @multiNames;
221              
222             try {
223 625 100   625   12927 if ( $lectionary->exists($compiled_xpath) ) {
224 30         2793 my @nodes = $lectionary->findnodes($compiled_xpath);
225 30         2704 foreach my $node (@nodes) {
226 90         421 push( @multiNames, $node->textContent );
227             }
228 30         141 return ( multiLect => 'yes', multiNames => \@multiNames );
229             }
230             else {
231 595         54110 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 625         3103 };
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 625     625   1158 my $tradition = shift;
247 625         967 my $commonName = shift;
248              
249 625         2088 my $parser = XML::LibXML->new();
250 625         8019 my $data_location;
251             my $lectionary;
252              
253             try {
254 625     625   13511 $data_location = dist_file( 'Date-Lectionary', 'date_lectionary_xref.xml' );
255 625         128826 $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 625         3688 };
260              
261 625         384677 my $compiled_xpath;
262             my $multi_xpath;
263              
264             try {
265 625     625   22236 $compiled_xpath = XML::LibXML::XPathExpression->new("/xref/day[\@name=\"$commonName\"]/alt[\@type='$tradition']");
266 625         5024 $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 625         4227 };
271              
272 625         7787 my $displayName;
273              
274             try {
275 625     625   13230 $displayName = $lectionary->findvalue($compiled_xpath);
276              
277 625 100       96917 if ( $lectionary->exists($multi_xpath) ) {
    100          
278 30         2531 return $commonName;
279             }
280             elsif ( $displayName eq '' ) {
281 82         7219 return $commonName;
282             }
283             else {
284 513         44478 return $displayName;
285             }
286             }
287             catch {
288 0     0   0 confess "An unpected error occured while querying the cross reference database.";
289 625         2980 };
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 625     625   1299 my $tradition = shift;
301 625         1005 my $commonName = shift;
302              
303 625         2003 my $parser = XML::LibXML->new();
304 625         7988 my $data_location;
305             my $lectionary;
306              
307             try {
308 625     625   13744 $data_location = dist_file( 'Date-Lectionary', 'date_lectionary_xref.xml' );
309 625         123390 $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 625         3779 };
314              
315 625         411231 my $compiled_xpath;
316             my $multi_xpath;
317              
318             try {
319 625     625   21528 $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 625         4358 };
324              
325 625         7624 my $altName;
326              
327             try {
328 625     625   13041 $altName = $lectionary->findvalue($compiled_xpath);
329 625         83107 return $altName;
330             }
331             catch {
332 0     0   0 confess "An unpected error occured while querying the cross reference database.";
333 625         3084 };
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 625     625   1013 my $date = shift;
345              
346 625         1055 my $advent = undef;
347              
348             try {
349 625     625   26083 $advent = Date::Advent->new( date => $date );
350 625         598879 return $advent;
351             }
352             catch {
353 0     0   0 confess "Could not calculate Advent for the given date [" . $date->ymd . "].";
354 625         3774 };
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 625     625   7212 my $easterYear = shift;
365              
366 625         1129 my $easter = undef;
367              
368             try {
369 625     625   13722 my ( $easterMonth, $easterDay ) = easter($easterYear);
370 625         15716 $easter = Time::Piece->strptime( $easterYear . "-" . $easterMonth . "-" . $easterDay, "%Y-%m-%d" );
371 625         66347 return $easter;
372             }
373             catch {
374 0     0   0 confess "Could not calculate Easter for the year [" . $easterYear . "]";
375 625         3810 };
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 524     524   844 my $date = shift;
386 524         855 my $lectionary = shift;
387              
388 524         1202 my $yesterday = $date - ONE_DAY;
389              
390 524         23146 my $yesterdayName;
391 524 100       1613 if ( $yesterday->wday == 1 ) {
392 27         214 $yesterdayName = _buildMoveableDays( $yesterday, $lectionary );
393             }
394              
395 524 100       3555 if ($yesterdayName) {
396             return (
397 17         100 commonName => $yesterdayName,
398             type => 'moveableFeast',
399             season => 'NaN'
400             );
401             }
402              
403 507         1263 my $fixedDayName = _buildFixedDays( $date, $lectionary );
404 507 100       8746 if ($fixedDayName) {
405             return (
406             commonName => $fixedDayName->{commonName},
407             type => 'fixedFeast',
408             season => $fixedDayName->{season}
409 25         180 );
410             }
411              
412 482         1112 my $moveableDayName = _buildMoveableDays( $date, $lectionary );
413 482 100 100     3558 if ( $moveableDayName && $date->wday != 1 ) {
414             return (
415 28         303 commonName => $moveableDayName,
416             type => 'moveableFeast',
417             season => 'NaN'
418             );
419             }
420              
421 454         2467 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 509     509   824 my $date = shift;
432 509         767 my $lectionary = shift;
433              
434             #Moveable holidays in January
435 509 100       1050 if ( $date->mon == 1 ) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
436 57 100 100     306 if ( $date->mday == 18 && $lectionary eq 'acna' ) {
437 4         34 return "Confession of St. Peter";
438             }
439 53 100 100     316 if ( $date->mday == 25 && $lectionary eq 'acna' ) {
440 4         46 return "Conversion of St. Paul";
441             }
442             }
443              
444             #Moveable holidays in February
445             elsif ( $date->mon == 2 ) {
446 48 100       466 if ( $date->mday == 2 ) {
447 4         27 return "The Presentation of Christ in the Temple";
448             }
449 44 100 100     265 if ( $date->mday == 24 && $lectionary eq 'acna' ) {
450 2         28 return "St. Matthias";
451             }
452             }
453              
454             #Moveable holidays in March
455             elsif ( $date->mon == 3 ) {
456 36 100 100     452 if ( $date->mday == 19 && $lectionary eq 'acna' ) {
457 4         37 return "St. Joseph";
458             }
459 32 100       219 if ( $date->mday == 25 ) {
460 2         17 return "The Annunciation";
461             }
462             }
463              
464             #Moveable holidays in April
465             elsif ( $date->mon == 4 ) {
466 34 100 100     603 if ( $date->mday == 25 && $lectionary eq 'acna' ) {
467 1         13 return "St. Mark";
468             }
469             }
470              
471             #Moveable holidays in May
472             elsif ( $date->mon == 5 ) {
473 43 100 100     792 if ( $date->mday == 1 && $lectionary eq 'acna' ) {
474 4         39 return "St. Philip & St. James";
475             }
476 39 100       252 if ( $date->mday == 31 ) {
477 6         45 return "The Visitation";
478             }
479             }
480              
481             #Moveable holidays in June
482             elsif ( $date->mon == 6 ) {
483 41 100 100     933 if ( $date->mday == 11 && $lectionary eq 'acna' ) {
484 4         38 return "St. Barnabas";
485             }
486 37 100 100     271 if ( $date->mday == 24 && $lectionary eq 'acna' ) {
487 1         16 return "Nativity of St. John the Baptist";
488             }
489 36 100 100     228 if ( $date->mday == 29 && $lectionary eq 'acna' ) {
490 1         20 return "St. Peter & St. Paul";
491             }
492             }
493              
494             #Moveable holidays in July
495             elsif ( $date->mon == 7 ) {
496 49 100 100     1664 if ( $date->mday == 22 && $lectionary eq 'acna' ) {
497 2         24 return "St. Mary Magdalene";
498             }
499 47 100 100     353 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     1177 if ( $date->mday == 15 && $lectionary eq 'acna' ) {
507 1         12 return "St. Mary the Virgin";
508             }
509 40 100 100     233 if ( $date->mday == 24 && $lectionary eq 'acna' ) {
510 1         21 return "St. Bartholomew";
511             }
512             }
513              
514             #Moveable holidays in September
515             elsif ( $date->mon == 9 ) {
516 42 100       1411 if ( $date->mday == 14 ) {
517 2         15 return "Holy Cross Day";
518             }
519 40 100 100     243 if ( $date->mday == 21 && $lectionary eq 'acna' ) {
520 1         13 return "St. Matthew";
521             }
522 39 100 100     238 if ( $date->mday == 29 && $lectionary eq 'acna' ) {
523 1         22 return "Holy Michael & All Angels";
524             }
525             }
526              
527             #Moveable holidays in October
528             elsif ( $date->mon == 10 ) {
529 51 100 100     2020 if ( $date->mday == 18 && $lectionary eq 'acna' ) {
530 6         78 return "St. Luke";
531             }
532 45 100 100     308 if ( $date->mday == 28 && $lectionary eq 'acna' ) {
533 1         16 return "St. Simon & St. Jude";
534             }
535             }
536              
537             #Moveable holidays in November
538             elsif ( $date->mon == 11 ) {
539 46 100 100     1913 if ( $date->mday == 30 && $lectionary eq 'acna' ) {
540 1         14 return "St. Andrew";
541             }
542             }
543              
544             #Moveable holidays in December
545             elsif ( $date->mon == 12 ) {
546 21 100 100     1032 if ( $date->mday == 21 && $lectionary eq 'acna' ) {
547 1         12 return "St. Thomas";
548             }
549 20 100 100     141 if ( $date->mday == 26 && $lectionary eq 'acna' ) {
550 2         19 return "St. Stephen";
551             }
552 18 100 100     114 if ( $date->mday == 27 && $lectionary eq 'acna' ) {
553 4         37 return "St. John";
554             }
555 14 100 100     98 if ( $date->mday == 28 && $lectionary eq 'acna' ) {
556 1         17 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 507     507   845 my $date = shift;
572 507         824 my $lectionary = shift;
573              
574             #Fixed holidays in January
575 507 100       1086 if ( $date->mon == 1 ) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
576 60 100       389 if ( $date->mday == 1 ) {
577             return {
578 6         51 commonName => "Holy Name",
579             season => 'Christmas'
580             };
581             }
582 54 100       323 if ( $date->mday == 6 ) {
583             return {
584 4         35 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     1256 if ( $date->mday == 6 && $lectionary eq 'acna' ) {
617             return {
618 3         47 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       2018 if ( $date->mday == 1 ) {
635             return {
636 4         50 commonName => "All Saints' Day",
637             season => 'Ordinary'
638             };
639             }
640             }
641              
642             #Fixed holidays in December
643             elsif ( $date->mon == 12 ) {
644 25 100       1348 if ( $date->mday == 25 ) {
645             return {
646 8         99 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 576     576   1012 my $easter = shift;
664              
665 576         947 my $ashWednesday = undef;
666              
667             try {
668 576     576   12168 my $secondsToSubtract = 46 * ONE_DAY;
669 576         1524 $ashWednesday = $easter - $secondsToSubtract;
670 576         29695 return $ashWednesday;
671             }
672             catch {
673 0     0   0 confess "Could not calculate Ash Wednesday for Easter [" . $easter->ymd . "].";
674 576         3860 };
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 540     540   839 my $easter = shift;
685              
686 540         1088 my $ascension = undef;
687              
688             try {
689 540     540   11133 my $secondsToAdd = 39 * ONE_DAY;
690 540         1263 $ascension = $easter + $secondsToAdd;
691 540         22696 return $ascension;
692             }
693             catch {
694 0     0   0 confess "Could not calculate Ascension for Easter [" . $easter->ymd . "].";
695 540         3705 };
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 537     537   854 my $easter = shift;
706              
707 537         928 my $pentecost = undef;
708              
709             try {
710 537     537   10642 my $secondsToAdd = 49 * ONE_DAY;
711 537         1320 $pentecost = $easter + $secondsToAdd;
712 537         22816 return $pentecost;
713             }
714             catch {
715 0     0   0 confess "Could not calculate Pentecost for Easter [" . $easter->ymd . "].";
716 537         3021 };
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 573     573   929 my $date = shift;
727 573         884 my $easter = shift;
728              
729 573         1264 my $dateMark = $easter - ONE_DAY;
730 573 100       25786 if ( $date == $dateMark ) {
731 3         73 return "Holy Saturday";
732             }
733              
734 570         12556 $dateMark = $dateMark - ONE_DAY;
735 570 100       24925 if ( $date == $dateMark ) {
736 3         76 return "Good Friday";
737             }
738              
739 567         12540 $dateMark = $dateMark - ONE_DAY;
740 567 100       24701 if ( $date == $dateMark ) {
741 2         51 return "Maundy Thursday";
742             }
743              
744 565         12249 $dateMark = $dateMark - ONE_DAY;
745 565 100       24105 if ( $date == $dateMark ) {
746 2         54 return "Wednesday in Holy Week";
747             }
748              
749 563         12164 $dateMark = $dateMark - ONE_DAY;
750 563 100       24083 if ( $date == $dateMark ) {
751 2         51 return "Tuesday in Holy Week";
752             }
753              
754 561         11898 $dateMark = $dateMark - ONE_DAY;
755 561 100       23924 if ( $date == $dateMark ) {
756 2         62 return "Monday in Holy Week";
757             }
758              
759 559         12076 $dateMark = $dateMark - ONE_DAY;
760 559 100       24014 if ( $date == $dateMark ) {
761 9         207 return "Palm Sunday";
762             }
763              
764 550         12172 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 550     550   946 my $date = shift;
775 550         769 my $easter = shift;
776              
777 550         1360 my $dateMark = $easter + ONE_DAY;
778 550 100       22352 if ( $date == $dateMark ) {
779 2         52 return "Monday of Easter Week";
780             }
781              
782 548         11951 $dateMark = $dateMark + ONE_DAY;
783 548 100       22301 if ( $date == $dateMark ) {
784 4         100 return "Tuesday of Easter Week";
785             }
786              
787 544         11679 $dateMark = $dateMark + ONE_DAY;
788 544 100       21517 if ( $date == $dateMark ) {
789 1         27 return "Wednesday of Easter Week";
790             }
791              
792 543         11642 $dateMark = $dateMark + ONE_DAY;
793 543 100       21543 if ( $date == $dateMark ) {
794 1         27 return "Thursday of Easter Week";
795             }
796              
797 542         11627 $dateMark = $dateMark + ONE_DAY;
798 542 100       21491 if ( $date == $dateMark ) {
799 1         30 return "Friday of Easter Week";
800             }
801              
802 541         11918 $dateMark = $dateMark + ONE_DAY;
803 541 100       21384 if ( $date == $dateMark ) {
804 1         26 return "Saturday of Easter Week";
805             }
806              
807 540         12117 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 80     80   146 my $advent = shift;
818 80         128 my $epiphany = shift;
819              
820 80         2351 my $firstChristmas = nextSunday( $advent->fourthSunday );
821 80         10170 my $dateMarker = nextSunday($firstChristmas);
822              
823 80 100       8620 if ( $dateMarker < $epiphany ) {
824 66         1530 return 1;
825             }
826             else {
827 14         338 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 80     80   157 my $date = shift;
841              
842 80         141 my $advent = shift;
843              
844 80         128 my $ashWednesday = shift;
845              
846 80         136 my $lectionary = shift;
847              
848 80         184 my $epiphany = Time::Piece->strptime( $date->year . "-01-06", "%Y-%m-%d" );
849              
850 80         8922 my $christmas2 = _hasChristmas2( $advent, $epiphany );
851              
852             #Is the date in Christmastide?
853 80         2339 my $dateMarker = nextSunday( $advent->fourthSunday );
854 80 100       9165 if ( $date == $dateMarker ) {
855 6         172 return "The First Sunday of Christmas";
856             }
857              
858 74         1763 $dateMarker = nextSunday($dateMarker);
859 74 100 100     7708 if ( $date == $dateMarker && $christmas2 == 1 ) {
    100          
860 6         172 return "The Second Sunday of Christmas";
861             }
862             elsif ( $date == $dateMarker ) {
863 1         50 return "The First Sunday of Epiphany";
864             }
865              
866 67         2804 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 67         114 my $sunCount = 0;
870 67         166 foreach my $sunday (@epiphanySundays) {
871 241         508 $dateMarker = nextSunday($dateMarker);
872 241 100 100     25733 if ( $date == $dateMarker && $date == prevSunday($ashWednesday) ) {
873 10         1544 return "The Last Sunday after Epiphany";
874             }
875 231 100 100     12512 if ( $date == $dateMarker && $date == prevSunday( prevSunday($ashWednesday) ) && $lectionary eq 'acna' ) {
      100        
876 7         2191 return "The Second to Last Sunday after Epiphany";
877             }
878              
879 224 100 100     16010 if ( $date == $dateMarker && $christmas2 == 1 ) {
    100 100        
    100 66        
880 45         1119 return $epiphanySundays[$sunCount];
881             }
882             elsif ( $date == $dateMarker && $epiphany->wday == 1 ) {
883 2         73 return $epiphanySundays[$sunCount];
884             }
885             elsif ( $date == $dateMarker && $christmas2 == 0 ) {
886 3         220 return $epiphanySundays[ $sunCount + 1 ];
887             }
888              
889 174         9361 $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   80 my $date = shift;
903 46         72 my $ashWednesday = shift;
904              
905 46         146 my $dateMarker = nextSunday($ashWednesday);
906 46 100       5187 if ( $date == $dateMarker ) {
907 10         314 return "The First Sunday in Lent";
908             }
909              
910 36         816 $dateMarker = nextSunday($dateMarker);
911 36 100       3724 if ( $date == $dateMarker ) {
912 9         249 return "The Second Sunday in Lent";
913             }
914              
915 27         600 $dateMarker = nextSunday($dateMarker);
916 27 100       2802 if ( $date == $dateMarker ) {
917 9         266 return "The Third Sunday in Lent";
918             }
919              
920 18         431 $dateMarker = nextSunday($dateMarker);
921 18 100       1870 if ( $date == $dateMarker ) {
922 9         312 return "The Fourth Sunday in Lent";
923             }
924              
925 9         228 $dateMarker = nextSunday($dateMarker);
926 9 50       909 if ( $date == $dateMarker ) {
927 9         257 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   102 my $date = shift;
941 56         91 my $easter = shift;
942              
943 56         179 my $dateMarker = nextSunday($easter);
944 56 100       6458 if ( $date == $dateMarker ) {
945 9         264 return "The Second Sunday of Easter";
946             }
947              
948 47         1062 $dateMarker = nextSunday($dateMarker);
949 47 100       4974 if ( $date == $dateMarker ) {
950 9         246 return "The Third Sunday of Easter";
951             }
952              
953 38         924 $dateMarker = nextSunday($dateMarker);
954 38 100       4061 if ( $date == $dateMarker ) {
955 11         316 return "The Fourth Sunday of Easter";
956             }
957              
958 27         626 $dateMarker = nextSunday($dateMarker);
959 27 100       2856 if ( $date == $dateMarker ) {
960 9         247 return "The Fifth Sunday of Easter";
961             }
962              
963 18         460 $dateMarker = nextSunday($dateMarker);
964 18 100       1844 if ( $date == $dateMarker ) {
965 9         258 return "The Sixth Sunday of Easter";
966             }
967              
968 9         216 $dateMarker = nextSunday($dateMarker);
969 9 50       966 if ( $date == $dateMarker ) {
970 9         270 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   401 my $date = shift;
984 242         363 my $pentecost = shift;
985              
986 242         744 my $trinitySunday = nextSunday($pentecost);
987 242 100       27571 if ( $date == $trinitySunday ) {
988 9         269 return "Trinity Sunday";
989             }
990              
991 233         5396 my $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-05-25", "%Y-%m-%d" ) );
992 233 50       124322 if ( $date == $dateMarker ) {
993 0         0 return "Ordinary 8";
994             }
995              
996 233         5074 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-01", "%Y-%m-%d" ) );
997 233 100       120111 if ( $date == $dateMarker ) {
998 3         81 return "Ordinary 9";
999             }
1000              
1001 230         4974 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-08", "%Y-%m-%d" ) );
1002 230 100       117820 if ( $date == $dateMarker ) {
1003 6         165 return "Ordinary 10";
1004             }
1005              
1006 224         4829 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-15", "%Y-%m-%d" ) );
1007 224 100       113539 if ( $date == $dateMarker ) {
1008 9         292 return "Ordinary 11";
1009             }
1010              
1011 215         4640 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-22", "%Y-%m-%d" ) );
1012 215 100       109055 if ( $date == $dateMarker ) {
1013 9         257 return "Ordinary 12";
1014             }
1015              
1016 206         4434 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-06-29", "%Y-%m-%d" ) );
1017 206 100       104704 if ( $date == $dateMarker ) {
1018 10         298 return "Ordinary 13";
1019             }
1020              
1021 196         4183 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-07-06", "%Y-%m-%d" ) );
1022 196 100       99469 if ( $date == $dateMarker ) {
1023 9         257 return "Ordinary 14";
1024             }
1025              
1026 187         4016 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-07-13", "%Y-%m-%d" ) );
1027 187 100       94179 if ( $date == $dateMarker ) {
1028 9         245 return "Ordinary 15";
1029             }
1030              
1031 178         3768 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-07-20", "%Y-%m-%d" ) );
1032 178 100       89102 if ( $date == $dateMarker ) {
1033 9         251 return "Ordinary 16";
1034             }
1035              
1036 169         3561 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-07-27", "%Y-%m-%d" ) );
1037 169 100       85066 if ( $date == $dateMarker ) {
1038 9         264 return "Ordinary 17";
1039             }
1040              
1041 160         3484 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-03", "%Y-%m-%d" ) );
1042 160 100       80700 if ( $date == $dateMarker ) {
1043 8         221 return "Ordinary 18";
1044             }
1045              
1046 152         3211 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-10", "%Y-%m-%d" ) );
1047 152 100       77353 if ( $date == $dateMarker ) {
1048 9         259 return "Ordinary 19";
1049             }
1050              
1051 143         3083 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-17", "%Y-%m-%d" ) );
1052 143 100       72582 if ( $date == $dateMarker ) {
1053 9         250 return "Ordinary 20";
1054             }
1055              
1056 134         3022 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-24", "%Y-%m-%d" ) );
1057 134 100       67743 if ( $date == $dateMarker ) {
1058 9         246 return "Ordinary 21";
1059             }
1060              
1061 125         2708 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-08-31", "%Y-%m-%d" ) );
1062 125 100       63358 if ( $date == $dateMarker ) {
1063 9         250 return "Ordinary 22";
1064             }
1065              
1066 116         2541 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-09-07", "%Y-%m-%d" ) );
1067 116 100       58860 if ( $date == $dateMarker ) {
1068 9         249 return "Ordinary 23";
1069             }
1070              
1071 107         2379 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-09-14", "%Y-%m-%d" ) );
1072 107 100       53583 if ( $date == $dateMarker ) {
1073 9         250 return "Ordinary 24";
1074             }
1075              
1076 98         2189 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-09-21", "%Y-%m-%d" ) );
1077 98 100       49841 if ( $date == $dateMarker ) {
1078 9         259 return "Ordinary 25";
1079             }
1080              
1081 89         1961 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-09-28", "%Y-%m-%d" ) );
1082 89 100       45223 if ( $date == $dateMarker ) {
1083 9         272 return "Ordinary 26";
1084             }
1085              
1086 80         1746 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-10-05", "%Y-%m-%d" ) );
1087 80 100       40575 if ( $date == $dateMarker ) {
1088 9         269 return "Ordinary 27";
1089             }
1090              
1091 71         1627 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-10-12", "%Y-%m-%d" ) );
1092 71 100       35821 if ( $date == $dateMarker ) {
1093 9         247 return "Ordinary 28";
1094             }
1095              
1096 62         1357 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-10-19", "%Y-%m-%d" ) );
1097 62 100       31395 if ( $date == $dateMarker ) {
1098 9         251 return "Ordinary 29";
1099             }
1100              
1101 53         1176 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-10-26", "%Y-%m-%d" ) );
1102 53 100       26825 if ( $date == $dateMarker ) {
1103 9         258 return "Ordinary 30";
1104             }
1105              
1106 44         994 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-11-02", "%Y-%m-%d" ) );
1107 44 100       22328 if ( $date == $dateMarker ) {
1108 6         164 return "Ordinary 31";
1109             }
1110              
1111 38         906 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-11-09", "%Y-%m-%d" ) );
1112 38 100       19607 if ( $date == $dateMarker ) {
1113 9         246 return "Ordinary 32";
1114             }
1115              
1116 29         676 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-11-16", "%Y-%m-%d" ) );
1117 29 100       15323 if ( $date == $dateMarker ) {
1118 17         483 return "Ordinary 33";
1119             }
1120              
1121 12         341 $dateMarker = closestSunday( Time::Piece->strptime( $pentecost->year . "-11-23", "%Y-%m-%d" ) );
1122 12 50       5963 if ( $date == $dateMarker ) {
1123 12         342 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 625     625   1177 my $date = shift;
1137 625         997 my $lectionary = shift;
1138 625         926 my $includeFeasts = shift;
1139              
1140 625         914 my $advent = shift;
1141 625         905 my $easter = shift;
1142              
1143             #Is the date in Advent?
1144 625 100       13242 if ( $date == $advent->firstSunday ) {
    100          
    100          
    100          
1145             return (
1146 9         311 commonName => "The First Sunday in Advent",
1147             type => 'Sunday',
1148             season => 'Advent'
1149             );
1150             }
1151             elsif ( $date == $advent->secondSunday ) {
1152             return (
1153 9         725 commonName => "The Second Sunday in Advent",
1154             type => 'Sunday',
1155             season => 'Advent'
1156             );
1157             }
1158             elsif ( $date == $advent->thirdSunday ) {
1159             return (
1160 9         1071 commonName => "The Third Sunday in Advent",
1161             type => 'Sunday',
1162             season => 'Advent'
1163             );
1164             }
1165             elsif ( $date == $advent->fourthSunday ) {
1166             return (
1167 9         1463 commonName => "The Fourth Sunday in Advent",
1168             type => 'Sunday',
1169             season => 'Advent'
1170             );
1171             }
1172              
1173             #Is the date Easter Sunday?
1174 589 100       94140 if ( $date == $easter ) {
1175             return (
1176 13         318 commonName => "Easter Day",
1177             type => 'fixedFeast',
1178             season => 'Easter'
1179             );
1180             }
1181              
1182             #Determine when Ash Wednesday is
1183 576         11322 my $ashWednesday = _determineAshWednesday($easter);
1184 576 100       8559 if ( $date == $ashWednesday ) {
1185             return (
1186 3         92 commonName => "Ash Wednesday",
1187             type => 'fixedFeast',
1188             season => 'Lent'
1189             );
1190             }
1191              
1192             #Holy Week
1193 573         13722 my $holyWeekDay = _determineHolyWeek( $date, $easter );
1194 573 100       1391 if ($holyWeekDay) {
1195             return (
1196 23         145 commonName => $holyWeekDay,
1197             type => 'fixedFeast',
1198             season => 'Lent'
1199             );
1200             }
1201              
1202             #Easter Week
1203 550         1228 my $easterWeekDay = _determineEasterWeek( $date, $easter );
1204 550 100       1231 if ($easterWeekDay) {
1205             return (
1206 10         61 commonName => $easterWeekDay,
1207             type => 'fixedFeast',
1208             season => 'Easter'
1209             );
1210             }
1211              
1212             #Ascension is 40 days after Easter
1213 540         1340 my $ascension = _determineAscension($easter);
1214 540 100       7735 if ( $date == $ascension ) {
1215             return (
1216 3         83 commonName => "Ascension Day",
1217             type => 'fixedFeast',
1218             season => 'Easter'
1219             );
1220             }
1221              
1222             #Pentecost is 50 days after Easter
1223 537         12124 my $pentecost = _determinePentecost($easter);
1224 537 100       7765 if ( $date == $pentecost ) {
1225             return (
1226 12         391 commonName => "Pentecost",
1227             type => 'fixedFeast',
1228             season => 'Pentecost'
1229             );
1230             }
1231              
1232             #Feast Day Celebrations
1233 525 100       11919 if ( $includeFeasts eq 'yes' ) {
1234 524         1400 my %feastDay = _determineFeasts( $date, $lectionary );
1235 524 100       1903 if ( $feastDay{commonName} ) {
1236             return (
1237             commonName => $feastDay{commonName},
1238             type => $feastDay{type},
1239             season => $feastDay{season}
1240 70         499 );
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 455 100       1072 if ( $date->wday != 1 ) {
1247             return (
1248 31         337 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 424 100       2705 if ( $date < $ashWednesday ) {
1256 80         1817 my %xmasEpiphany = (
1257             commonName => _determineChristmasEpiphany( $date, $advent, $ashWednesday, $lectionary ),
1258             type => 'Sunday'
1259             );
1260              
1261 80 100       430 if ( $xmasEpiphany{commonName} =~ m/Christmas/ig ) {
1262 12         36 $xmasEpiphany{season} = 'Christmas';
1263 12         89 return %xmasEpiphany;
1264             }
1265             else {
1266 68         160 $xmasEpiphany{season} = 'Epiphany';
1267 68         434 return %xmasEpiphany;
1268             }
1269             }
1270              
1271 344 100       7581 if ( $date < $easter ) {
1272             return (
1273 46         921 commonName => _determineLent( $date, $ashWednesday ),
1274             type => 'Sunday',
1275             season => 'Lent'
1276             );
1277             }
1278              
1279 298 100 66     5565 if ( $date > $easter && $date < $pentecost ) {
1280             return (
1281 56         2148 commonName => _determineEasterSeason( $date, $easter ),
1282             type => 'Sunday',
1283             season => 'Easter'
1284             );
1285             }
1286              
1287 242 50       9101 if ( $date > $pentecost ) {
1288             return (
1289 242         4874 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