BreviariumBreviarium
LibreríasBreviarium Core

Conceptos clave

Cómo resuelve la librería una fecha, qué significan los ciclos y las opciones, y qué hacer cuando falta un texto.

Fechas

Cada método recibe un Date opcional. Si no lo pasas, se usa la fecha de la instancia: la del constructor, la de setDate() o, por defecto, el momento en que se creó la instancia.

La librería trabaja con el día del calendario local de esa fecha, sin la hora. Por eso conviene crear las fechas con componentes locales:

new Date(2025, 5, 16);        // ✅ 16 de junio de 2025, hora local
new Date('2025-06-16');       // ⚠️ medianoche UTC: en América puede ser el 15
new Date('2025-06-16T12:00'); // ✅ también válido: hora local

Instancias de larga duración

new Breviarium() fija la fecha en el momento de crearse. Si tu app permanece abierta varios días, llama a setDate(new Date()) o pasa la fecha en cada llamada para no quedarte en el día anterior.

Asociación entre textos y fechas

Uno de los problemas que resuelve esta librería es asociar una fecha civil a su día litúrgico. El 25 de diciembre siempre es Navidad, pero la mayoría de celebraciones cambian cada año porque dependen de la Pascua, cuya fecha se calcula con el computus.

En vez de reimplementar esos cálculos, la librería usa Romcal con el calendario de España. Para cada fecha:

  1. Romcal genera el calendario litúrgico del año civil.
  2. De las celebraciones de ese día se toma la primera que no es opcional. Las memorias libres se ignoran, de modo que ese día se reza la feria.
  3. Esa celebración tiene un identificador estable, como ordinary_time_11_monday, barnabas_apostle o nativity_of_the_lord, que se usa para buscar los textos en la base de datos.

Ese identificador es el id que verás en todas las respuestas.

Ciclos

El campo cycle indica a qué variante de los textos pertenece una respuesta:

ValorSignificadoDónde aparece
ANYTexto válido para cualquier añoTodas las horas y lecturas
YEAR_A, YEAR_B, YEAR_CCiclo dominical A, B o CLecturas de domingos y solemnidades
ODD, EVENAño impar (I) o par (II) del ciclo ferialLecturas de días feriales
MEMORYLecturas propias de una memoriaLecturas, Oficio
MEMORY_PROPERMemoria con textos propiosLaudes, Vísperas, Oficio, Hora intermedia
MEMORY_FERIAL, MEMORY_FERIAL1, MEMORY_FERIAL2Memoria que toma parte de sus textos de la feriaLaudes, Vísperas, Hora intermedia
FEAST, SPECIALFiestas y días con hora intermedia especialHora intermedia, Oficio

No necesitas interpretar los valores de memoria: cuando a una memoria le falta un texto, la librería ya lo completa con el de la feria correspondiente.

El ciclo dominical (A, B, C) del día lo devuelve getLiturgyInformation. El ciclo ferial (año I o II) se deduce del año en que termina el año litúrgico:

const info = await breviarium.getLiturgyInformation();
const endYear = Number(info.calendar?.endOfLiturgycalSeason.split('-')[0]);
const ferialCycle = endYear % 2 === 0 ? 'II (par)' : 'I (impar)';

Varias opciones para un mismo día

Algunos días admiten más de un formulario. Por eso getLaudes() y getVesperae() devuelven un array:

  • [0] es la celebración del día. Si es una memoria, los textos que no tiene propios se completan con los de la feria.
  • [1], si existe, es el formulario de la feria de ese día, para quien prefiera rezar el ferial.
const opciones = await breviarium.getLaudes(new Date(2025, 5, 11)); // San Bernabé
opciones?.map((o) => o.id); // ["barnabas_apostle", "ordinary_time_10_wednesday"]

En un día ferial normal el array tiene un solo elemento. El resto de horas (getOfficium, getTertia, etc.) devuelven un único objeto ya combinado.

Oficio de lectura: ciclo ordinario y bienal

Las lecturas del Oficio de lectura existen en tres variantes, distinguidas por el sufijo del campo:

SufijoCiclo
_aCiclo ordinario (anual): el que se publica en el Breviario
_iCiclo bienal, año impar
_pCiclo bienal, año par

Muchas memorias tienen una única lectura patrística para todos los ciclos, y muchas fiestas una única primera lectura. Más detalles en Oficio de lectura.

Textos que faltan

  • Si un texto no existe en la base de datos, el campo llega como cadena vacía '', no como undefined. La librería además escribe un aviso en la consola (id … Not found in …).
  • Los campos opcionales de Completas (segundo_salmo_*) llegan como undefined los días que no tienen segundo salmo.
  • Si para una fecha no hay datos (por ejemplo, si Romcal no puede generar el calendario), algunos métodos pueden rechazar la promesa. Envuelve las llamadas en try/catch si tu interfaz debe seguir funcionando:
async function safe<T>(fn: () => Promise<T>): Promise<T | undefined> {
  try {
    return await fn();
  } catch (error) {
    console.error(error);
    return undefined;
  }
}

const oficio = await safe(() => breviarium.getOfficium());

Rendimiento y tamaño

  • Cada llamada genera el calendario del año con Romcal, así que es asíncrona y conviene no repetirla en bucles. Si muestras varias horas del mismo día, lánzalas en paralelo con Promise.all.
  • El paquete incluye toda la base de datos de textos (unos 15 MB sin comprimir). En aplicaciones web, impórtalo de forma diferida para no penalizar la carga inicial:
const { Breviarium } = await import('breviarium');

On this page