Bodu.Globalization.Calendar.Algorithms Namespace
- Package
Bodu.Globalization.Calendar.Algorithms
Purpose
Bodu.Globalization.Calendar.Algorithms is the date-calculation layer of Bodu.Globalization.Calendar. It defines the strategy a rule uses to find its nominal date for a year, and the contract and registry for plugging in custom calculators.
Every NotableDateRule carries exactly one occurrence source: an IDateCalculationStrategy (13 single-date strategies) or an IDateRecurrenceStrategy (four frequency-based recurrence sources). The loader maps each <Strategy> (or <Recurrence>) element in a rule document to one of these built-in strategies; you rarely construct them by hand, but they are the public vocabulary the engine resolves against. The most common are listed below - the strategy reference covers the full catalogue.
Static documentation
- Date calculation algorithms - the strategy kinds, the built-in algorithm keys, and how to register a custom algorithm.
- Notable-date rule strategies - the full catalogue of single-date strategies and recurrence sources.
- Working with non-Gregorian calendars - fixed dates expressed in Hijri / Hebrew / Persian / Chinese lunisolar calendars.
Key types
The strategy contract and built-in strategies
- IDateCalculationStrategy -
DateOnly? Calculate(int year, StrategyResolutionContext context). Implemented by every single-date strategy: the six below plus OrdinalDayOfMonthStrategy, DayOfYearStrategy, IsoWeekDateStrategy, WeekdayNearRuleStrategy, NthWeekdayFromRuleStrategy, WorkingDayOffsetFromRuleStrategy, and WorkingDayInMonthStrategy. - IDateRecurrenceStrategy - the frequency-based recurrence sources a
<Recurrence>element maps to: DailyIntervalRecurrenceStrategy, WeeklyRecurrenceStrategy, MonthlyDayRecurrenceStrategy, MonthlyWeekdayRecurrenceStrategy. - FixedDateStrategy - a fixed month / day, optionally expressed in a non-Gregorian CalendarSystem (a short Hijri month can recur twice in a Gregorian year, so it also exposes
CalculateAll). - DayOfWeekInMonthStrategy - the nth or last weekday in a month (e.g. fourth Thursday in November), driven by WeekOrdinal.
- RelativeWeekdayInMonthStrategy - a weekday relative to a weekday-in-month anchor (e.g. the Tuesday after the first Monday).
- WeekdayNearDateStrategy - a weekday on / before / after / nearest a fixed date (e.g. the Monday nearest 24 May), driven by WeekdayProximity.
- OffsetFromRuleStrategy - a fixed day offset from another rule's occurrence (e.g. Good Friday = Easter Sunday − 2).
- AlgorithmDateStrategy - dispatch to a named algorithm by key.
Algorithm keys
AlgorithmDateStrategy resolves a string key to a bundled astronomical / gazetted calculator. Built-in keys include western-easter and orthodox-easter (exposed as the WesternEasterKey / OrthodoxEasterKey constants), vernal-equinox, autumnal-equinox, jp-vernal-equinox, jp-autumnal-equinox, qingming, vesak, asalha-puja, losar, matariki, and the Hindu-festival keys (diwali, holi, maha-shivaratri, ganesh-chaturthi, …). AlgorithmDateStrategy.IsKnownKey(key) reports whether a key is built in. The calculators that back these keys are an internal implementation detail reached only through the key.
Custom algorithms
- INotableDateAlgorithm -
DateOnly? Calculate(int year). Implement this to add a calculator (returningnullfor years you do not support). - INotableDateAlgorithmRegistry, NotableDateAlgorithmRegistry - the lookup and its chainable, mutable implementation (
Register(key, algorithm)). Keys not recognised byAlgorithmDateStrategyfall through to this registry, so a custom key registered here can be referenced from a rule as<Algorithm key="my-key" />. Pass the registry toNotableDateResourceLoader.Load(xml, resolver, registry)(to whitelist the key during validation) and to the service through NotableDateServiceOptions.Algorithms-new NotableDateService(resource, new NotableDateServiceOptions { Algorithms = registry }). - StrategyResolutionContext - the per-resolution context passed to strategies; resolves referenced rules (
ResolveReference) cycle-safely and carries the custom algorithm registry.
Minimal sample
using Bodu.Globalization.Calendar;
using Bodu.Globalization.Calendar.Algorithms;
// A custom calculator …
public sealed class PiDayAlgorithm : INotableDateAlgorithm
{
public DateOnly? Calculate(int year) => new DateOnly(year, 3, 14);
}
// … registered under a key the rule document references via <Algorithm key="pi-day" />.
var registry = new NotableDateAlgorithmRegistry().Register("pi-day", new PiDayAlgorithm());
NotableDateResource resource = NotableDateResourceLoader.Load(xml, _ => null, registry);
NotableDateService service = new NotableDateService(resource, new NotableDateServiceOptions { Algorithms = registry });
Classes
- AlgorithmDateStrategy
Calculates a notable date using a named, algorithm-backed computation such as Easter, an equinox, a lunar-phase festival, or a gazetted date table.
- DailyIntervalRecurrenceStrategy
Generates an occurrence every fixed number of calendar days from an anchor date, such as every 14 days from 1 January 2026.
- DayOfWeekInMonthStrategy
Calculates a notable date that falls on the nth (or last) occurrence of a weekday within a month, such as the fourth Thursday of November or the last Monday of May.
- DayOfYearStrategy
Calculates a date by its ordinal position within a Gregorian year, such as the 100th day or the final day of the year.
- FixedDateStrategy
Calculates a notable date that falls on a fixed month and day every year, optionally expressed in a non-Gregorian calendar system such as the Islamic, Hebrew, Persian, or Chinese lunisolar calendar.
- IsoWeekDateStrategy
Calculates a weekday within an ISO-8601 week of an ISO week-year, such as the Monday of ISO week 1 or the Friday of ISO week 20.
- MonthlyDayRecurrenceStrategy
Generates an occurrence on a specified calendar day every fixed number of months, such as the 15th of every month or the 20th of every third month.
- MonthlyWeekdayRecurrenceStrategy
Generates an ordinal weekday every fixed number of months, such as the first Monday of every month or the last Friday of every third month.
- NotableDateAlgorithmRegistry
A mutable registry of custom INotableDateAlgorithm implementations keyed by algorithm key.
- NthWeekdayFromRuleStrategy
Calculates the Nth occurrence of a weekday strictly before or strictly after another rule's occurrence, such as the second Monday after a festival.
- OffsetFromRuleStrategy
Calculates a notable date as a fixed day offset from another rule's occurrence, such as Good Friday two days before Easter Sunday.
- OrdinalDayOfMonthStrategy
Calculates a day by its ordinal position from the beginning or end of a Gregorian month, such as the last day of February or the second-last day of a month.
- RelativeWeekdayInMonthStrategy
Calculates a notable date that falls on a weekday relative to an anchor weekday occurrence within a month, such as the Tuesday after the first Monday of November (United States general election day).
- StrategyResolutionContext
Provides a strategy with access to the surrounding resource so that referential strategies (such as OffsetFromRuleStrategy) can resolve the occurrence of another rule for the same year.
- WeekdayNearDateStrategy
Calculates a notable date that falls on a weekday on, before, after, or nearest to a fixed month and day, such as the Monday on or after 24 May.
- WeekdayNearRuleStrategy
Calculates a weekday on, before, after, or nearest to the date produced by another rule, such as the first Monday after Easter Sunday.
- WeeklyRecurrenceStrategy
Generates occurrences on one or more selected weekdays every fixed number of weeks, such as every Monday and Friday or every second Tuesday.
- WorkingDayInMonthStrategy
Calculates the Nth working day from the beginning or end of a Gregorian month, such as the first working day of January or the last working day of a reporting month.
- WorkingDayOffsetFromRuleStrategy
Calculates a date a specified number of working days before or after another rule's occurrence, such as the last working day before a public-holiday shutdown.
Interfaces
- IDateCalculationStrategy
Defines the calculation contract for a single rule strategy: given a Gregorian year, produce the occurrence of the notable date in that year, if any.
- IDateRecurrenceStrategy
Calculates every occurrence of a recurring notable-date pattern that falls within a bounded date range, such as every second Tuesday or the last Friday of every month.
- INotableDateAlgorithm
Computes the date of a notable date for a Gregorian year from a closed-form or tabular algorithm. Implementations are registered under a key and dispatched by the AlgorithmDateStrategy when a rule references that key, allowing the algorithm catalogue to be extended beyond the built-in computations.
- INotableDateAlgorithmRegistry
Provides lookup of custom INotableDateAlgorithm implementations by key, supplementing the engine's built-in algorithm catalogue.
Enums
- InvalidDayOfMonthBehavior
Specifies how a monthly day-of-month recurrence handles a month that does not contain the requested day, such as the 31st in February.