Utility library that outputs the Liturgical Calendar used by the Roman Rite (Western Church) for Node JS v6 and above.
Contributions are welcome!
Please fork/raise merge requests or issues to improve the quality of this module.
I especially reach out to you all for help with translations/localizations of celebration names so that this module can cater to a wider audience.
See contributing for more information.
- Description
- Revisions
- Credits
- Features
- Module Robustness & Data Integrity
- Builds
- Usage
- Celebration Types
- Celebration Titles
- Liturgical Seasons
- Liturgical Cycles
- Liturgical Colors
- Psalter Weeks
- Calendar Sources
- Queries
- Overriding dates
- Removing general dates in national calendar output
- Localizing celebration names
romcal generates the General Roman Calendar used in the Roman Catholic Rite. Output conforms to the revised liturgical calendar for the Western Church as approved by Paul VI in Mysterii Paschalis dated 14 February 1969.
Output can be configured for the standard calendar year (Jan, 1st - Dec, 31st) or the liturgical year (First Sunday of Advent - Christ the King). Additional filters for filtering output are also available (described below).
See history for latest updates and important/breaking changes.
This node module is inspired by the C program romcal written by Kenneth G. Bath. This module, while exhibiting similar output, is written ground up using different tools and technologies and exposes many new functionalities.
Additional credits for bug fixes, localizations and suggestions go to:
- Able to query liturgical dates for any year in the gregorian calendar (1582 - now). Note that dates for years before 1969 will still be returned in a format conforming to Mysterii Paschalis even though those years came before the calendar reforms in 1969.
- Filter queries to allow more streamlined date results to be obtained for the year.
- Localization of liturgical date names to cater for different languages.
- National liturgical calendars for country specific calendars.
- Richly commented code to help developers and contributors understand how the module works.
NOTE: This module uses Moment.js and Lodash for calculations and operations. Additional plugins such as Range and Recur are used to extend date computation functionality.
Calendar entries for this module are pulled from various sources from the net. As such their accuracy cannot be ensured. If you find an incorrect calendar entry (e.g. wrong date, wrong feast type, spelling issue, typos), you are most welcome to contribute to the source code or inform me so that the necessary changes can be made to make this a more robust and reliable module.
romcal’s code logic is developed according to calendar requirements descibed in various church documents sourced from the internet (and even from Wikipedia). If you notice discrepancies between romcal’s output and actual liturgical dates, please do contribute your fixes or submit an issue on GitHub.
romcal employs TDD
using mocha
and should
.
Run npm test
in your console to view test output.
Travis CI is used to validate romcal builds to ensure functionality is working as expected.
The romcal source code is actually the same for backend and frontend usage. To make it working on the frontend side, the frontend library is wrapped and built thanks to webpack
. This build step is done automatically when you perform a npm install
on the romcal directory.
But if you have edited the codebase, you can update manually the frontend library with this command:
npm run build
The frontend library is generated in the dist
folder, not included in the romcal codebase. When built, it contains romcal.bundle.min.js
, a minified and obfruscated bundle of romcal + all its dependencies wrapped in a UMD module shell that is suitable for being included directly in browsers.
ℹ️ romcal was re-written using ES6, and use the new import/export syntax to manage node modules. However, thanks to
esm
andbabel
, it can still be included by other non ES6 aware node modules via the normal CommonJsrequire
call.
Add romcal to your project via npm:
$ npm install romcal
Then require romcal in your node project:
var romcal = require('romcal');
or as a CommonJS module
import romcal from 'romcal';
or in a webpage for direct usage on browsers
<script type="text/javascript" src="romcal.bundle.min.js"></script>
Including romcal directly in the browser will result in an object called Romcal
being attached to the DOM window
object. All the functions below will exist as properties of the Romcal
object.
Invoke the calendarFor
method to retrieve an array of liturgical dates and celebrations in the Roman Calendar. This method accepts an object (optional) of configuration properties to obtain customized output.
romcal.calendarFor({
year: 2020,
country: 'unitedStates',
locale: 'pl',
christmastideEnds: 't|o|e',
epiphanyOnJan6: true|false,
christmastideIncludesTheSeasonOfEpiphany: true | false,
corpusChristiOnThursday: true|false,
ascensionOnSunday: true|false,
type: 'calendar|liturgical',
query: {
day: 0 - 6, // 0 - Sunday, 6 - Saturday (week beginning with Sunday)
month: 0 - 11, // 0 - Jan, 11 - Dec (month begining with Jan)
group: '',
title: '',
}
},
true|false );
year
: Retrieve calendar dates for the given year (year should be an integer). Defaults to the current system year if not specifiedcountry
: Include celebration dates requested by the Episcopal council(s) of the given country that were approved by the Holy See. If not specified, no National dates are included in the calendar output. If an unrecognized country is specified, romcal will silently ignore the property and will not return any National dates in the calendar output. Country names should be specified in camel case (i.e.unitedStates
,czechRepublic
).locale
: Defaults toen
(English) if not set. romcal celebration names can be localized to different languages. If a given locale does not have the localized name for a celebration in that language, romcal will fall back to use the celebration name in the base language (if a region was specified in the locale), and finally in English. More details on locales management in the localization.christmastideEnds
: Specifies the end of the Christmas season. Can be eithert
(traditional where Christmastide ends on Epiphany),o
(ordinary where Christmastide ends on the Baptism of the Lord) ande
(extraordinary where Christmastide ends on the Presentation of the Lord). Defaults too
if not specifiedepiphanyOnJan6
: Iftrue
, fixes Epiphany on January 6th always. Usually, Epiphany will be set to a Sunday between 2 - 8 Jan based on an internal calculation. Defaults tofalse
.christmastideIncludesTheSeasonOfEpiphany
: Iffalse
, the season of epiphany (i.e. days before Epiphany and days after Epiphany) will not appear within the Christmastide.true
by default.corpusChristiOnThursday
: Determines if Corpus Christi should be celebrated on Thursday on the 7th week of Easter (60 days after Easter) or Sunday (63 days after Easter). Defaults tofalse
.ascensionOnSunday
: Determines if Ascension should replace the 7th Sunday of Easter (42 days after Easter). Defaults tofalse
where Ascension will be on Thursday, 39 days after Easter, if value not recognized or specified.type
: Determines the type of calendar output. Can either beliturgical
orcalendar
. Defaults tocalendar
if value not recognized or specified. Theliturgical
year runs from 1st Sunday of Advent of the given year to Saturday of the 34th Week of Ordinary Time in the following year. The civil year on the other hand refers to the standard year from Jan 1 - Dec 31.query
: A nested query object which filters the dates according to the given criteria. For more details on how to use queries, see Queries section.
The second parameter that can be passed to the romcal.calendarFor()
method.
It is an optional parameter: If true, skip converting dates to ISO8601 strings and return dates as Moment objects. Defaults to false if not specified.
romcal can also be invoked without parameters or via shorthand properties like so:
// Get calendar year dates (1st Jan - 31st Dec) for the current year
romcal.calendarFor();
// Get calendar year dates for the specified year
romcal.calendarFor(2020);
// Get calendar year dates and do not convert Moment date objects to ISO8601 strings
romcal.calendarFor(true);
romcal returns an array of liturgical date objects in the following structure
[
{
"key": "",
"name": "",
"type": "",
"moment": "",
"source": "",
"data": {
"prioritized": boolean
"season": "",
"meta": {
"liturgicalColor": {}
"titles": []
}
}
}
]
key
: A camel case string which serves as a unique identifier for the celebration. This key is an essential element in overriding datesname
: The localizable name of the celebrationtype
: A key representing the celebration typemoment
: Moment.js object or ISO8601 string of the date of the celebrationsource
: The internal calendar source of this celebrationdata
: An object that holds additional information about the celebration- prioritized: A optional boolean that when true, gives the celebration higher priority over another coinciding celebration even though that celebration has a higher ranking type. This flag should be used with caution.
- season: Required: A string that identifies the liturgical season this celebration belongs to
- meta:
- liturgicalColor: The liturgical color assigned for this celebration (usually follows the liturgical season but may defer if this celebration is a solemnity, feast or memorial)
- titles: An array of titles that may be assigned to this celebration
Each date in the liturgical calendar is assigned a type. romcal defines these types in src/constants/Types.js
which are:
SOLEMNITY
SUNDAY
TRIDUUM
HOLY_WEEK
FEAST
MEMORIAL
OPT_MEMORIAL
COMMEMORATION
FERIA
Where the importance or rank of the celebration is in descending order (Solemnity being of highest importance and feria being the lowest).
Types play an important role in determining which celebration should take precendence over another when two or more celebrations coincide on the same date. Certain celebration types will also have different liturgical colors applied to them.
The array of types can be imported into consumer apps via:
import { Types } from 'romcal';
On top of having a celebration type, liturgical dates may also have one or more titles of significance assigned to it.
For example, the feast of Saint Catherine of Siena is assigned the titles PATRON_OF_EUROPE
(for national calendars of countries in Europe only) and DOCTOR_OF_THE_CHURCH
due to those titles being conferred on her by the Church.
romcal defines liturgical seasons in src/constants/Titles.js
which are:
Titles are currently available for:
PATRON_OF_EUROPE
FEAST_OF_THE_LORD
DOCTOR_OF_THE_CHURCH
MARIAN_FEAST
TRIDUUM
MARTYR
The titles object can be imported into consumer apps via:
ES6
import { Titles } from 'romcal';
CommonJS
var Titles = require('romcal').Titles;
The liturgical calendar is divided into various seasons that occur throughout the liturgical year.
romcal defines liturgical seasons in src/constants/LiturgicalSeasons.js
which are:
ADVENT
CHRISTMASTIDE
EARLY_ORDINARY_TIME
LATER_ORDINARY_TIME
LENT
HOLY_WEEK
EASTER
Methods in src/lib/Seasons.js
assigns seasons to the dates it generates to indicate the season to which the range of dates generated belong.
The LiturgicalSeasons object can be imported into consumer apps via:
ES6
import { LiturgicalSeasons } from 'romcal';
CommonJS
var LiturgicalSeasons = require('romcal').LiturgicalSeasons;
A liturgical year consists of a cycles (either A, B, C) that determines which portions of scripture are to be read. romcal automatically calculates the correct cycle for the given liturgical year and includes it in the meta information of each liturgical date for that year.
romcal defines cycles in src/constants/Cycles.js
which are:
Year A
denoted by the key0
Year B
denoted by the key1
Year C
denoted by the key2
Cycle information can be read via the dates[idx].data.meta.cycle
property in each date element in the array that calendarFor
returns.
The cycles object can be imported into consumer apps via:
ES6
import { Cycles } from 'romcal';
CommonJS
var Cycles = require('romcal').Cycles;
romcal defines 6 colors in src/constants/LiturgicalColors.js
which are:
RED
ROSE
PURPLE
GREEN
WHITE
GOLD
More information on how these colors are used for celebration can be found here
Liturgical colors can be read via the dates[idx].data.meta.liturgicalColor
property in each date element in the array that calendarFor
returns.
The LiturgicalColors object can be imported into consumer apps via:
ES6
import { LiturgicalColors } from 'romcal';
CommonJS
var LiturgicalColors = require('romcal').LiturgicalColors;
With the exception of the Easter Octave, each week in the liturgical year is assigned readings from the Psalter. There are also some rules that govern the set of Psalter readings used for particular occasions or seasons in the year.
romcal defines the Psalter Weeks used in the liturgical year in src/constants/PsalterWeeks.js
which are:
Week I
Week II
Week III
Week IV
Easter
(seperate set of readings only used during the Octave of Easter)
Psalter weeks can be read via the dates[idx].data.meta.psalterWeek
property in each date element in the array that calendarFor
returns.
The PsalterWeeks object can be imported into consumer apps via:
ES6
import { PsalterWeeks } from 'romcal';
CommonJS
var PsalterWeeks = require('romcal').PsalterWeeks;
romcal generates dates that come from 4 different internal sources:
l
: liturgicalc
: celebrationsg
: generaln
: national
Each date is assigned a source with one of the four calendar sources above.
Calendar sources play an important role in how romcal manages coinciding dates (see overriding dates).
Represents a standard date in the liturgical year. Dates from this source build the basic structure of the liturgical calendar from the start of the liturgical year to its end.
Dates from src/lib/Seasons.js
will be assigned the source value l
.
The module responsible for generating the liturgical
dates is src/lib/Seasons.js
. It is unlikely that this module will need customization or overriding of any kind.
Represents central celebrations observed in the Roman Catholic rite. They take precendence and will replace coinciding dates from the liturgical
calendar or general
calendar.
Dates from src/lib/Celebrations.js
will be assigned the source value c
.
The module responsible for generating celebrations
is src/lib/Celebrations.js
. It is highly unlikely that this module will need customization or overriding of any kind.
A prioritized date defined in the national
calendar can replace a date in the celebrations
calendar when:
- the key of the
national
date matches a key incelebrations
- the
national
date is prioritized
In most cases, it is unlikely that a national calendar event will replace a celebration because of the significance of celebrations. If a national event must override a celebration date, it should be properly verified.
The following are a list of dates defined in the celebrations
calendar:
- Immaculate Conception
- Christmas
- Mary Mother of God
- Epiphany
- Trinity Sunday
- Corpus Christi
- Sacred Heart of Jesus
- Birth of John the Baptist
- Peter and Paul, Apostles
- Assumption
- All Saints
- Christ the King
- Joseph, Husband of Mary
- Annunciation
- Easter
- Divine Mercy Sunday
- Ascension
- Pentecost Sunday
- Ash Wednesday
- Palm Sunday
- Holy Thursday
- Good Friday
- Holy Saturday
- Holy Family
- Baptism of the Lord
- Presentation of the Lord
- Transfiguration
- Triumph of the Cross
- Immaculate Heart of Mary
Represents general celebrations throughout the liturgical year. Dates from the general
calendar will override those from the liturgical
calendar.
Dates from src/calendars/general.js
are assigned the source value g
.
The module responsible for generating the general
dates is src/lib/Calendars/general.js
.
general
calendar dates will always be overwritten by celebration
or national
calendar dates even if they are prioritized. Celebrations in this calendar should reflect the General Roman Calendar, therefore there should be changes only when there is a change in the General Roman Calendar. When one wants to add, remove or modify a celebration that is celebrated only in a national calendar, they should make this changes in that particular calendar, not in the general
.
In situations where a given celebration must override one in the general calendar, define it in the national
calendar instead.
Represents specific liturgical dates that were approved for use by the Holy See for a particular country. It can be used to define unique celebrations celebrated by that particular country or existing celebrations that were transferred to another date.
A prioritized celebration in the national
calendar takes precedence over celebrations in general
, celebrations
and liturgical
calendars. As such, this marker should be used with caution as it may cause national events to override important celebrations that should not be overriden.
In situations when there are 2 celebrations from a national
calendar that coincide on the same date, the one with the higher ranking celebration type will take precendence.
A new national
calendar for a country can be defined by creating a new .js
file with the country name in upper case, lower case or camel case in the src/lib/calendars
folder (i.e. malaysia.mjs
). This new file will automatically be picked up by the module and will be used when the user supplies the matching key in the country argument in the calendarFor
method.
Dates from src/calendars/<countryName>.js
will be assigned the source key n
See Overriding dates for more examples.
romcal can generate filtered liturgical or calendar year dates by:
- passing an additional query object along with the initial configuration object to the
calendarFor
method, or - invoking the
queryFor
method and supplying an array of dates generated fromcalendarFor
and a query object
import { Calendar } from 'romcal';
Calendar.calendarFor({
query: {
month: 0 // 0 - 11 (Jan = 0, Dec = 11)
}
});
Calendar.calendarFor({
query: {
day: 0, // 0 - 6 (0 = Sunday, 6 = Saturday)
}
});
or
import { Calendar } from 'romcal';
let dates = Calendar.calendarFor();
let datesGroupedByDay = Calendar.queryFor(dates, {
day: 0 // 0 - 6
});
let datesGroupedByMonth = Calendar.queryFor(dates, {
month: 0 // 0 - 11
});
Calendar dates can be grouped by various criteria upon invocation like so:
import { Calendar } from 'romcal';
Calendar.calendarFor({
query: {
group: 'days|months|daysByMonth|weeksByMonth|cycles|types|liturgicalSeasons|liturgicalColors|psalterWeeks'
}
});
Or invoking the query function at a later point
import { Calendar } from 'romcal';
let dates = Calendar.calendarFor();
// Some code,
// then ...
let groupedCalendar = Calendar.queryFor(dates, {
group: 'days|months|daysByMonth|weeksByMonth|cycles|types|liturgicalSeasons|liturgicalColors|psalterWeeks'
});
romcal.calendarFor({
query: {
title: 'PATRON_OF_EUROPE'
}
});
Other possible values can be checked here.
It is possible to query for dates against multiple criteria:
// Filter dates in January and group the results according to days
romcal.queryFor(dates, {
month: 0,
group: 'days'
});
romcal is designed with extensibility in mind to cater for unique scenarios that are common in the liturgical calendar.
The order of importance of calendar sources are: celebrations
> national
> general
> liturgical
.
Prioritizing a date allows it to:
- Override a higher ranking
type
date object with the same key - Prevent it from being overriden by other coinciding dates
A date can be prioritized by adding prioritized
: true
to the data
object in the given date object. See src/lib/Celebrations.js
for more examples.
All dates in src/lib/Celebrations.js
(Christmas, Easter) are prioritized as they must override any other date in the liturgical calendar and cannot be overriden by any other coinciding date regardless of rank unless the coinciding date is itself prioritized
For example, allSaints
in src/lib/Celebrations.js
can be overriden by allSaints
in src/calendars/england.js
) because the entry in that national
calendar was set with prioritized
: true
.
⚠️ If a coinciding date’s source is from thecelebration
ornational
calendars, but the prioritized date is defined in thegeneral
calendar, it will still be overidden by the coinciding date becausecelebration
andnational
calendar sources have higher precedence (see Overriding a date by its calendar source section).
In most countries, All Saints and All Souls are always celebrated on the 1st and 2nd of November respectively. However, in England and Wales, if All Saints (1 November) falls on a Saturday, it is transferred to the Sunday and All Souls is transferred to Monday 3rd Novemeber.
romcal implements this unique difference by overriding the allSouls
and allSaints
celebrations in the national calendars of src/calendars/england.js
and src/calendars/wales.js
(the original definition was in src/calendars/general.js
). The overriding dates in these calendars define a IIFE callback function for the Moment property that holds logic for determining if the date should be moved.
Since national calendar dates have higher precendence than general calendar dates, the national date definitions for All Saints and All Souls will override the ones in the general calendar.
Also, since prioritized dates in the national calendar sources can override dates in celebration calendar sources, the date definitions for All Saints and All Souls will now be taken from the national calendar.
Therefore, it is important that the key in the national calendar is exactly the same as the one in the general calendar so that romcal recognizes it for overriding. Typos (even case mismatch), will cause unexpected results.
By default, romcal
does not remove any celebrations in its output. Instead, prioritization (see above) is the preferred way to go about overriding celebrations to exhibit different characteristics.
However, in some cases, a national calendar may need to omit a celebration entirely from its output. For example, the possible reasons could be:
- that the given celebration is entirely irrelevant to the observances of the nation;
- when a celebration of two or more saints are celebrated jointly in the
general
calendar, but separately in the national calendar; - when a celebration of two or more saints are celebrated separately in the
general
calendar, but jointly in the national calendar.
romcal
enables this flexibility via the drop
key.
When defined, the drop
key should contain a boolean
value of true
to indicate that the given celebration should be removed from the calendar output.
Usually, this means excluding a celebration defined in src/calendars/general.js
. The construct would be defined in the relevant national
calendar and look like this:
{
"key": "",
"drop": true
}
Note: When defining drop
, only the key of the celebration is mandatory. Other keys do not have to be defined. drop
operations also have higher precedence than overriding (meaning, they are run first before prioritization logic).
Celebration names in romcal can be localized to any language that is already supported by Moment i18n.
Locales are stored as .js
files in the src/locales
directory.
If the given locale contains a region (the second group of letters after a hyphen, e.g. for fr-CA
, the CA
represents the region), a base language will be set as a locale fallback (fr
in our example).
A locale can have one or two fallbacks. en
is the default locale in romcal and always serves as the last fallback.
Fallbacks are used when a string in the specified locale is not defined in the src/locales
directory or the given key does not exist in any of previous the locale(s).
For example, a given locale containing region (like fr-CA
) will gracefully fall back to fr
if a localization key isn’t in fr-CA
, or if fr-CA.js
doesn’t exits in the src/locales
directory. In the end, it always falls back to en
, which is the default language in romcal. This should be used also to make the localisation files smaller, i.e. when the locale containing region has a particular string translated the same way as the main locale (e.g. fr
), we should not localise that particular string in the locale containing region.
The structure of the locale file is typically like so:
{
"advent": {
},
"christmastide": {
},
"epiphany": {
},
"ordinaryTime": {
},
"lent": {
},
"holyWeek": {
},
"eastertide": {
},
"celebrations": {
},
"general": {
},
"national": {
}
}
The first 7 objects define locale keys used by src/lib/Seasons.js
when generating litugical dates.
The celebrations
, general
and national
objects will hold localizations for src/lib/Celebrations.js
, src/calendars/general.js
and src/calendars/<country>.js
respectively where the celebrations key
is used as the identifier for localization purposes.
See the end of these files to see the function that localizes the dates according to their keys.
romcal uses the utility function Utils.localize()
to resolve the correct locale string based on the given key.
The function accepts several parameters:
Utils.localize({
key: '',
week: 0,
count: 0
});
key
: A dot deliminated string representing the locale key (celebrations.christmas
)week
: A non zero integer for weeks which will be converted to its ordinal representation (1st Sunday of Advent)count
: A non zero integer for days which will be converted to its ordinal representation (2nd Sunday of Christmas)