UNPKG

rrule-rust

Version:

RRule implementation for browsers and Node.js written in Rust

457 lines (456 loc) 15.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RRule = exports.Weekday = exports.Month = exports.Frequency = void 0; const datetime_1 = require("./datetime"); const lib_1 = require("./lib"); /** * Recurrence frequency enumeration. */ var Frequency; (function (Frequency) { Frequency[Frequency["Yearly"] = 0] = "Yearly"; Frequency[Frequency["Monthly"] = 1] = "Monthly"; Frequency[Frequency["Weekly"] = 2] = "Weekly"; Frequency[Frequency["Daily"] = 3] = "Daily"; Frequency[Frequency["Hourly"] = 4] = "Hourly"; Frequency[Frequency["Minutely"] = 5] = "Minutely"; Frequency[Frequency["Secondly"] = 6] = "Secondly"; })(Frequency || (exports.Frequency = Frequency = {})); /** * Month enumeration (1-based). */ var Month; (function (Month) { Month[Month["January"] = 1] = "January"; Month[Month["February"] = 2] = "February"; Month[Month["March"] = 3] = "March"; Month[Month["April"] = 4] = "April"; Month[Month["May"] = 5] = "May"; Month[Month["June"] = 6] = "June"; Month[Month["July"] = 7] = "July"; Month[Month["August"] = 8] = "August"; Month[Month["September"] = 9] = "September"; Month[Month["October"] = 10] = "October"; Month[Month["November"] = 11] = "November"; Month[Month["December"] = 12] = "December"; })(Month || (exports.Month = Month = {})); /** * Weekday enumeration (0-based, Monday = 0). */ var Weekday; (function (Weekday) { Weekday[Weekday["Monday"] = 0] = "Monday"; Weekday[Weekday["Tuesday"] = 1] = "Tuesday"; Weekday[Weekday["Wednesday"] = 2] = "Wednesday"; Weekday[Weekday["Thursday"] = 3] = "Thursday"; Weekday[Weekday["Friday"] = 4] = "Friday"; Weekday[Weekday["Saturday"] = 5] = "Saturday"; Weekday[Weekday["Sunday"] = 6] = "Sunday"; })(Weekday || (exports.Weekday = Weekday = {})); /** * Represents a recurrence rule (RRULE) according to RFC 5545. * * RRule defines a rule for generating recurring date/time values. It supports * various frequencies (yearly, monthly, weekly, etc.) and provides fine-grained * control through options like byWeekday, byMonth, byHour, etc. * * @example * ```typescript * // Daily recurrence * const daily = new RRule(Frequency.Daily); * * // Every weekday * const weekdays = new RRule({ * frequency: Frequency.Weekly, * byWeekday: [Weekday.Monday, Weekday.Tuesday, Weekday.Wednesday, Weekday.Thursday, Weekday.Friday] * }); * * // First Monday of each month, 10 times * const firstMonday = new RRule({ * frequency: Frequency.Monthly, * byWeekday: [{ n: 1, weekday: Weekday.Monday }], * count: 10 * }); * * // Every 2 weeks on Tuesday and Thursday * const biweekly = new RRule({ * frequency: Frequency.Weekly, * interval: 2, * byWeekday: [Weekday.Tuesday, Weekday.Thursday] * }); * ``` */ class RRule { constructor(frequencyOrOptions) { if (typeof frequencyOrOptions === 'object' && frequencyOrOptions !== null) { this.frequency = frequencyOrOptions.frequency; this.interval = frequencyOrOptions.interval; this.until = frequencyOrOptions.until; this.count = frequencyOrOptions.count; this.byWeekday = frequencyOrOptions.byWeekday ?? []; this.byHour = frequencyOrOptions.byHour ?? []; this.byMinute = frequencyOrOptions.byMinute ?? []; this.bySecond = frequencyOrOptions.bySecond ?? []; this.byMonthday = frequencyOrOptions.byMonthday ?? []; this.bySetpos = frequencyOrOptions.bySetpos ?? []; this.byMonth = frequencyOrOptions.byMonth ?? []; this.byWeekno = frequencyOrOptions.byWeekno ?? []; this.byYearday = frequencyOrOptions.byYearday ?? []; this.weekstart = frequencyOrOptions.weekstart; } else { this.frequency = frequencyOrOptions; this.until = undefined; this.byWeekday = []; this.byHour = []; this.byMinute = []; this.bySecond = []; this.byMonthday = []; this.bySetpos = []; this.byMonth = []; this.byWeekno = []; this.byYearday = []; } } /** * Parses an RFC 5545 RRULE string into an RRule instance. * * @param str - RRULE string (e.g., "FREQ=DAILY;COUNT=10") * @returns A new RRule instance * * @example * ```typescript * const rrule = RRule.fromString("FREQ=WEEKLY;BYDAY=MO,WE,FR;COUNT=10"); * ``` */ static fromString(str) { const rust = lib_1.RRule.parse(str); return this.fromRust(rust); } static fromPlain(rrule) { return new this({ frequency: rrule.frequency, interval: rrule.interval, until: rrule.until && datetime_1.DateTime.fromPlain(rrule.until), count: rrule.count, byWeekday: rrule.byWeekday, byHour: rrule.byHour, byMinute: rrule.byMinute, bySecond: rrule.bySecond, byMonthday: rrule.byMonthday, bySetpos: rrule.bySetpos, byMonth: rrule.byMonth, byWeekno: rrule.byWeekno, byYearday: rrule.byYearday, weekstart: rrule.weekstart, }); } /** * @internal */ static fromRust(rust) { const rrule = new this({ frequency: rust.frequency, interval: rust.interval ?? undefined, until: rust.until ? datetime_1.DateTime.fromInt32Array(rust.until) : undefined, count: rust.count ?? undefined, byWeekday: rust.byWeekday, byHour: rust.byHour, byMinute: rust.byMinute, bySecond: rust.bySecond, byMonthday: rust.byMonthday, bySetpos: rust.bySetpos, byMonth: rust.byMonth, byWeekno: rust.byWeekno, byYearday: rust.byYearday, weekstart: rust.weekstart ?? undefined, }); rrule.rust = rust; return rrule; } /** * Creates a new RRule with a different frequency. * * @param frequency - The new frequency * @returns A new RRule instance * * @example * ```typescript * const daily = new RRule(Frequency.Daily); * const weekly = daily.setFrequency(Frequency.Weekly); * ``` */ setFrequency(frequency) { return new RRule({ ...this.toOptions(), frequency }); } /** * Creates a new RRule with a different interval. * * @param interval - The new interval (e.g., 2 for every other occurrence) * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Weekly); * const biweekly = rrule.setInterval(2); // Every 2 weeks * ``` */ setInterval(interval) { return new RRule({ ...this.toOptions(), interval }); } /** * Creates a new RRule with a different count limit. * * @param count - Maximum number of occurrences * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Daily); * const limited = rrule.setCount(10); // Only 10 occurrences * ``` */ setCount(count) { return new RRule({ ...this.toOptions(), count }); } /** * Creates a new RRule with different weekday constraints. * * @param weekdays - List of weekdays or nth-weekday specifications * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Weekly); * const weekdays = rrule.setByWeekday([Weekday.Monday, Weekday.Wednesday, Weekday.Friday]); * * // First and last Friday of the month * const fridays = rrule.setByWeekday([ * { n: 1, weekday: Weekday.Friday }, * { n: -1, weekday: Weekday.Friday } * ]); * ``` */ setByWeekday(weekdays) { return new RRule({ ...this.toOptions(), byWeekday: weekdays }); } /** * Creates a new RRule with different hour constraints. * * @param hours - List of hours (0-23) * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Daily); * const morningAndEvening = rrule.setByHour([9, 17]); // 9 AM and 5 PM * ``` */ setByHour(hours) { return new RRule({ ...this.toOptions(), byHour: hours }); } /** * Creates a new RRule with different minute constraints. * * @param minutes - List of minutes (0-59) * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Hourly); * const quarterHours = rrule.setByMinute([0, 15, 30, 45]); * ``` */ setByMinute(minutes) { return new RRule({ ...this.toOptions(), byMinute: minutes }); } /** * Creates a new RRule with different second constraints. * * @param seconds - List of seconds (0-59) * @returns A new RRule instance */ setBySecond(seconds) { return new RRule({ ...this.toOptions(), bySecond: seconds }); } /** * Creates a new RRule with different month day constraints. * * @param days - List of days (1-31, negative for counting from end) * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Monthly); * const firstAndLast = rrule.setByMonthday([1, -1]); // First and last day of month * ``` */ setByMonthday(days) { return new RRule({ ...this.toOptions(), byMonthday: days }); } /** * Creates a new RRule with different set position constraints. * * @param poses - List of positions (1-based, negative for from end) to include after all other BY* parts * @returns A new RRule instance * * @example * ```typescript * // Get only the first occurrence from each monthly set of Mondays and Tuesdays. * // Without BYSETPOS this would include every Monday and Tuesday in every month. * const rrule = new RRule({ * frequency: Frequency.Monthly, * byWeekday: [Weekday.Monday, Weekday.Tuesday] * }); * const first = rrule.setBySetpos([1]); * * // Resulting RRULE string: * console.log(first.toString()); // "RRULE:FREQ=MONTHLY;BYDAY=MO,TU;BYSETPOS=1" * * // Effect: * // For each month, all Mondays and Tuesdays are collected, then only the earliest * // (the 1st in chronological order) is kept. This will usually be the first Monday * // of the month unless the month starts on a Tuesday (e.g., if the 1st is Tuesday). * * // Another example: keep the first and last matching weekday in each month. * const firstAndLast = rrule.setBySetpos([1, -1]); * console.log(firstAndLast.toString()); // "RRULE:FREQ=MONTHLY;BYDAY=MO,TU;BYSETPOS=1,-1" * ``` */ setBySetpos(poses) { return new RRule({ ...this.toOptions(), bySetpos: poses }); } /** * Creates a new RRule with different month constraints. * * @param months - List of months * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Yearly); * const quarterly = rrule.setByMonth([Month.January, Month.April, Month.July, Month.October]); * ``` */ setByMonth(months) { return new RRule({ ...this.toOptions(), byMonth: months }); } /** * Creates a new RRule with different week number constraints. * * @param weekNumbers - List of week numbers (1-53, negative for counting from end) * @returns A new RRule instance */ setByWeekno(weekNumbers) { return new RRule({ ...this.toOptions(), byWeekno: weekNumbers }); } /** * Creates a new RRule with different year day constraints. * * @param days - List of days of the year (1-366, negative for counting from end) * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Yearly); * const firstAndLastDay = rrule.setByYearday([1, -1]); // Jan 1 and Dec 31 * ``` */ setByYearday(days) { return new RRule({ ...this.toOptions(), byYearday: days }); } /** * Creates a new RRule with a different week start day. * * @param day - The weekday that starts the week * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Weekly); * const sundayStart = rrule.setWeekstart(Weekday.Sunday); * ``` */ setWeekstart(day) { return new RRule({ ...this.toOptions(), weekstart: day }); } /** * Creates a new RRule with a different end date. * * @param until - The date/time at which to end the recurrence * @returns A new RRule instance * * @example * ```typescript * const rrule = new RRule(Frequency.Daily); * const limited = rrule.setUntil(DateTime.date(2024, 12, 31)); * ``` */ setUntil(until) { return new RRule({ ...this.toOptions(), until }); } /** * Converts the RRule to an RFC 5545 RRULE string. * * @returns RFC 5545 formatted string * * @example * ```typescript * const rrule = new RRule({ * frequency: Frequency.Weekly, * byWeekday: [Weekday.Monday, Weekday.Wednesday], * count: 10 * }); * console.log(rrule.toString()); // "RRULE:FREQ=WEEKLY;COUNT=10;BYDAY=MO,WE" * ``` */ toString() { return this.toRust().toString(); } /** * @internal */ toRust() { this.rust ??= new lib_1.RRule(this.frequency, this.interval, this.count, this.weekstart, this.until?.toInt32Array(), this.byWeekday, this.byHour, this.byMinute, this.bySecond, this.byMonthday, this.bySetpos, this.byMonth, this.byWeekno, this.byYearday); return this.rust; } toPlain() { return { frequency: this.frequency, interval: this.interval, count: this.count, byWeekday: this.byWeekday, byHour: this.byHour, byMinute: this.byMinute, bySecond: this.bySecond, byMonthday: this.byMonthday, bySetpos: this.bySetpos, byMonth: this.byMonth, byWeekno: this.byWeekno, byYearday: this.byYearday, weekstart: this.weekstart, until: this.until?.toPlain(), }; } toOptions() { return { frequency: this.frequency, interval: this.interval, count: this.count, byWeekday: this.byWeekday, byHour: this.byHour, byMinute: this.byMinute, bySecond: this.bySecond, byMonthday: this.byMonthday, bySetpos: this.bySetpos, byMonth: this.byMonth, byWeekno: this.byWeekno, byYearday: this.byYearday, weekstart: this.weekstart, until: this.until, }; } } exports.RRule = RRule;