import { BaseEventProperties, CalendarDay, CalendaryPlugin } from 'calendaryjs'; import { Selector } from 'calendaryjs/builder'; /** * Module augmentation for CalendarDay. * When this plugin is imported, TypeScript will recognize the optional `lunar` property * on CalendarDay objects returned by getDays() and getDay(). */ declare module "calendaryjs" { interface CalendarDay { /** * Lunar date information (available when lunar plugin is used with enrichDays: true) */ lunar?: LunarInfo; } } /** * Calendar date representation (year, month, day). * Used for both solar and lunar dates in conversion functions. */ interface CalendarDate { year: number; month: number; day: number; } /** * Lunar date representation for internal converter use. * Includes isLeapMonth flag needed for accurate lunar-solar conversion. * @internal */ interface LunarDate extends CalendarDate { isLeapMonth: boolean; } /** * Solar date representation. * Alias for CalendarDate for semantic clarity. */ type SolarDate = CalendarDate; /** * Lunar event configuration. * Provide `lunarMonth` and `lunarDay`; the event resolves to the regular month. * Set `isLeapMonth: true` to prefer the leap month (闰月) — in years that don't * have it, the event falls back to the regular month (like Temporal's `monthCode`). * @template TMetadata - Custom metadata type extending Record */ interface LunarEvent = Record> extends BaseEventProperties { type: "lunar"; lunarMonth: number; lunarDay: number; /** Prefer the leap month; defaults to false. Falls back to the regular month when absent. */ isLeapMonth?: boolean; /** * Pin this event to a calendar variant (`"chinese"` | `"vietnamese"`), so a * stored/shared event generates the same dates for every consumer — a `.cdy` * collection stays self-describing. When omitted, the plugin instance's * `calendar` option applies (default `"chinese"`). */ calendar?: "chinese" | "vietnamese"; } /** * Which national lunisolar calendar to compute — named calendar systems, like * `Intl`/Temporal calendar identifiers (`chinese`, `dangi`, …). These are * distinct standards, not just timezones: whenever a new moon falls between * 23:00 and 24:00 at UTC+7, the Vietnamese month starts a day earlier than the * Chinese one — occasionally moving Tết (1968, 1985, 2007, 2030) or a * leap-month boundary (1984, 1985, 1987, 1995, 2031). * * - `"chinese"` — the standard 1900–2100 table at 120°E / UTC+8, matching the * published Chinese almanac exactly. **Default.** * - `"vietnamese"` — astronomical computation at 105°E / UTC+7 (the Ho Ngoc * Duc algorithm, the de-facto Vietnamese standard — âm lịch Việt Nam). */ type LunarCalendar = "chinese" | "vietnamese"; interface LunarConvertOptions { /** @default "chinese" */ calendar?: LunarCalendar; } /** * Convert a solar (Gregorian) date to a lunar date. * Defaults to the Chinese calendar; pass `{ calendar: "vietnamese" }` for * Vietnamese âm lịch (see {@link LunarCalendar} for when they differ). */ declare function solarToLunar(solar: SolarDate, options?: LunarConvertOptions): LunarDate; /** * Convert a lunar date to a solar (Gregorian) date. * `isLeapMonth: true` for a month that isn't that year's leap month falls back * to the regular month (both variants — the recurring-event leap fallback). */ declare function lunarToSolar(lunar: LunarDate, options?: LunarConvertOptions): SolarDate; /** * Check whether a lunar date exists (year in 1900–2099, month/leap combination * present that year, day within the month's 29/30 days). */ declare function isValidLunarDate(lunar: LunarDate, options?: LunarConvertOptions): boolean; /** * Lunar date info added by lunar plugin */ interface LunarInfo { year: number; month: number; day: number; isLeapMonth: boolean; } /** * CalendarDay with lunar enrichment */ interface CalendarDayWithLunar extends CalendarDay { lunar: LunarInfo; } /** * Options for lunar plugin */ interface LunarPluginOptions { /** * Whether to enrich days with lunar date information. * When true, getDays() will include lunarDate on each day. * @default false */ enrichDays?: boolean; /** * Which national lunisolar calendar the instance computes — `"chinese"` * (the standard almanac table) or `"vietnamese"` (âm lịch Việt Nam, * astronomical at UTC+7). Applies to lunar events and day enrichment alike. * @default "chinese" */ calendar?: LunarCalendar; } /** * Lunar calendar plugin for Calendary * * Provides: * - `lunar` event type for lunar calendar events * - Optional day enricher that adds `lunar` info to CalendarDay (opt-in via enrichDays: true) * * @param options - Plugin options * * @example * ```typescript * const cal = calendary(); * * // Basic usage - only lunar events, no day enrichment * cal.use(lunar()); * * // With day enrichment - getDays() will include lunar info * cal.use(lunar({ enrichDays: true })); * * // Vietnamese âm lịch (defaults to the Chinese calendar) * cal.use(lunar({ calendar: "vietnamese" })); * * // Lunar events * cal.addGroup({ * id: "lunar-holidays", * name: "Lunar Holidays", * events: [ * { type: "lunar", id: "lunar-new-year", title: "Lunar New Year", lunarMonth: 1, lunarDay: 1 } * ] * }); * * // With enrichDays: true, days have lunar info * const day = cal.getDay("2025-01-29"); * console.log(day.lunar); // { year: 2025, month: 1, day: 1, isLeapMonth: false } * ``` */ declare function lunarPlugin(options?: LunarPluginOptions): CalendaryPlugin; /** * The lunar plugin, plus a builder selector: * - `calendary().use(lunar())` registers the `lunar` event type. * - `every("year").on(lunar.date(1, 1))` authors a lunar event via the builder. */ declare const lunar: typeof lunarPlugin & { /** * Builder selector for a lunar date — `every("year").on(lunar.date(1, 1))`. * Pass `{ leap: true }` to target the leap month — `lunar.date(6, 15, { leap: true })`. * Pass `{ calendar: "vietnamese" }` to pin the event to a calendar variant * (portable across consumers); omitted, the plugin instance's default applies. */ date(month: number, day: number, options?: { leap?: boolean; calendar?: LunarCalendar; }): Selector; /** * Lunar date fields for a known solar date, with `isLeapMonth` computed rather * than guessed — e.g. `lunar.fromSolar(deathDate)` for a recurring giỗ/birthday. * Pass the same calendar variant the plugin instance uses. */ fromSolar(date: Date, options?: LunarConvertOptions): { lunarMonth: number; lunarDay: number; isLeapMonth: boolean; }; }; export { type CalendarDate, type CalendarDayWithLunar, type LunarCalendar, type LunarConvertOptions, type LunarDate, type LunarEvent, type LunarInfo, type LunarPluginOptions, type SolarDate, isValidLunarDate, lunar, lunarToSolar, solarToLunar };