UNPKG

rrule-temporal

Version:

Recurrence rule (rrule) processing using Temporal PlainDate/PlainDateTime, with cross-timezone and cross-calendar rrule support

2,433 lines 98.9 kB
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (__hasOwnProp.call(b, prop))
      __defNormalProp(a, prop, b[prop]);
  if (__getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(b)) {
      if (__propIsEnum.call(b, prop))
        __defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
  var target = {};
  for (var prop in source)
    if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
      target[prop] = source[prop];
  if (source != null && __getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(source)) {
      if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
        target[prop] = source[prop];
    }
  return target;
};

// src/index.ts
import { Temporal } from "@js-temporal/polyfill";
function isIcsOpts(opts) {
  return typeof opts.rruleString === "string";
}
function unfoldLine(foldedLine) {
  return foldedLine.replace(/\r?\n[ \t]/g, "");
}
function parseIcsDateTime(dateStr, tzid, valueType) {
  const isDate = valueType === "DATE" || !dateStr.includes("T");
  const isoDate = `${dateStr.slice(0, 4)}-${dateStr.slice(4, 6)}-${dateStr.slice(6, 8)}`;
  if (isDate) {
    return Temporal.PlainDate.from(isoDate).toZonedDateTime({ timeZone: tzid });
  }
  if (dateStr.endsWith("Z")) {
    const iso = `${isoDate}T${dateStr.slice(9, 15)}Z`;
    return Temporal.Instant.from(iso).toZonedDateTimeISO(tzid || "UTC");
  } else {
    const iso = `${isoDate}T${dateStr.slice(9)}`;
    return Temporal.PlainDateTime.from(iso).toZonedDateTime(tzid);
  }
}
function parseDateLines(lines, linePrefix, defaultTzid) {
  const dates = [];
  const regex = new RegExp(`^${linePrefix}(?:;VALUE=([^;]+))?(?:;TZID=([^:]+))?:(.+)`, "i");
  for (const line of lines) {
    const match = line.match(regex);
    if (match) {
      const [, valueType, tzid, dateValuesStr] = match;
      const timezone = tzid || defaultTzid;
      const dateValues = dateValuesStr.split(",");
      dates.push(...dateValues.map((dateValue) => parseIcsDateTime(dateValue, timezone, valueType)));
    }
  }
  return dates;
}
function parseNumberArray(val, sort = false) {
  const arr = val.split(",").map((n) => parseInt(n, 10));
  if (sort) {
    return arr.sort((a, b) => a - b);
  }
  return arr;
}
function parseByMonthArray(val) {
  return val.split(",").map((tok) => {
    const t = tok.trim();
    if (/^\d+L$/i.test(t)) return t.toUpperCase();
    const n = parseInt(t, 10);
    return Number.isFinite(n) ? n : t;
  });
}
function parseRRuleString(input, targetTimezone, dtstart) {
  var _a, _b, _c, _d, _e;
  const unfoldedInput = unfoldLine(input).trim();
  let parsedDtstart;
  let tzid = targetTimezone;
  let rruleLine;
  let exDate = [];
  let rDate = [];
  if (/^DTSTART/im.test(unfoldedInput)) {
    const lines = unfoldedInput.split(/\s+/);
    const dtLine = lines.find((line) => line.match(/^DTSTART/i));
    const rrLine = lines.find((line) => line.match(/^RRULE:/i));
    const exLines = lines.filter((line) => line.match(/^EXDATE/i));
    const rLines = lines.filter((line) => line.match(/^RDATE/i));
    const dtMatch = dtLine.match(/DTSTART(?:;VALUE=([^;]+))?(?:;TZID=([^:]+))?:(.+)/i);
    if (!dtMatch) throw new Error("Invalid DTSTART in ICS snippet");
    const [, valueType, dtTzid, dtValue] = dtMatch;
    const effectiveTzid = (_b = (_a = dtTzid != null ? dtTzid : targetTimezone) != null ? _a : tzid) != null ? _b : "UTC";
    parsedDtstart = parseIcsDateTime(dtValue, effectiveTzid, valueType);
    tzid = (_e = (_d = (_c = dtTzid != null ? dtTzid : parsedDtstart.timeZoneId) != null ? _c : targetTimezone) != null ? _d : tzid) != null ? _e : "UTC";
    rruleLine = rrLine;
    exDate = parseDateLines(exLines, "EXDATE", tzid != null ? tzid : "UTC");
    rDate = parseDateLines(rLines, "RDATE", tzid != null ? tzid : "UTC");
  } else {
    parsedDtstart = dtstart;
    rruleLine = unfoldedInput;
    if (parsedDtstart) {
      tzid = parsedDtstart.timeZoneId;
    }
  }
  const parts = rruleLine ? rruleLine.replace(/^RRULE:/i, "").split(";") : [];
  const opts = {
    dtstart: parsedDtstart,
    tzid,
    exDate: exDate.length > 0 ? exDate : void 0,
    rDate: rDate.length > 0 ? rDate : void 0
  };
  let pendingSkip;
  for (const part of parts) {
    const [key, val] = part.split("=");
    if (!key) continue;
    switch (key.toUpperCase()) {
      case "RSCALE":
        if (val) {
          opts.rscale = val.toUpperCase();
          if (pendingSkip && !opts.skip) {
            opts.skip = pendingSkip;
            pendingSkip = void 0;
          }
        }
        break;
      case "SKIP": {
        const v = (val || "").toUpperCase();
        if (!["OMIT", "BACKWARD", "FORWARD"].includes(v)) {
          throw new Error(`Invalid SKIP value: ${val}`);
        }
        if (opts.rscale) {
          opts.skip = v;
        } else {
          pendingSkip = v;
        }
        break;
      }
      case "FREQ":
        opts.freq = val.toUpperCase();
        break;
      case "INTERVAL":
        opts.interval = parseInt(val, 10);
        break;
      case "COUNT":
        opts.count = parseInt(val, 10);
        break;
      case "UNTIL": {
        opts.until = parseIcsDateTime(val, tzid || "UTC");
        if (!val.endsWith("Z") && tzid !== "UTC") {
          throw new Error("UNTIL rule part MUST always be specified as a date with UTC time");
        }
        break;
      }
      case "BYHOUR":
        opts.byHour = parseNumberArray(val, true);
        break;
      case "BYMINUTE":
        opts.byMinute = parseNumberArray(val, true);
        break;
      case "BYSECOND":
        opts.bySecond = parseNumberArray(val, true);
        break;
      case "BYDAY":
        opts.byDay = val.split(",");
        break;
      case "BYMONTH":
        opts.byMonth = parseByMonthArray(val);
        break;
      case "BYMONTHDAY":
        opts.byMonthDay = parseNumberArray(val);
        break;
      case "BYYEARDAY":
        opts.byYearDay = parseNumberArray(val);
        break;
      case "BYWEEKNO":
        opts.byWeekNo = parseNumberArray(val);
        break;
      case "BYSETPOS":
        opts.bySetPos = parseNumberArray(val);
        break;
      case "WKST":
        opts.wkst = val;
        break;
    }
  }
  if (pendingSkip && !opts.rscale) {
    throw new Error("SKIP MUST NOT be present unless RSCALE is present");
  }
  if (pendingSkip && opts.rscale && !opts.skip) {
    opts.skip = pendingSkip;
  }
  return opts;
}
var _RRuleTemporal = class _RRuleTemporal {
  constructor(params) {
    var _a, _b, _c, _d, _e, _f, _g;
    let manual;
    if (isIcsOpts(params)) {
      const parsed = parseRRuleString(params.rruleString, params.tzid, params.dtstart);
      if (!parsed.dtstart) {
        throw new Error("dtstart is required - provide it either in rruleString or as a separate parameter");
      }
      this.tzid = (_b = (_a = parsed.tzid) != null ? _a : params.tzid) != null ? _b : "UTC";
      this.originalDtstart = parsed.dtstart;
      manual = __spreadProps(__spreadValues({}, parsed), {
        // Allow explicit COUNT/UNTIL overrides when omitted from the RRULE string
        count: (_c = params.count) != null ? _c : parsed.count,
        until: (_d = params.until) != null ? _d : parsed.until,
        strict: params.strict,
        maxIterations: params.maxIterations,
        includeDtstart: params.includeDtstart,
        tzid: this.tzid
      });
    } else {
      manual = __spreadValues({}, params);
      if (typeof manual.dtstart === "string") {
        throw new Error("Manual dtstart must be a ZonedDateTime");
      }
      manual.tzid = manual.tzid || manual.dtstart.timeZoneId;
      this.tzid = manual.tzid;
      this.originalDtstart = manual.dtstart;
    }
    if (!manual.freq) throw new Error("RRULE must include FREQ");
    manual.interval = (_e = manual.interval) != null ? _e : 1;
    if (manual.interval <= 0) {
      throw new Error("Cannot create RRule: interval must be greater than 0");
    }
    if (manual.until && !(manual.until instanceof Temporal.ZonedDateTime)) {
      throw new Error("Manual until must be a ZonedDateTime");
    }
    this.opts = this.sanitizeOpts(manual);
    this.maxIterations = (_f = manual.maxIterations) != null ? _f : 1e4;
    this.includeDtstart = (_g = manual.includeDtstart) != null ? _g : false;
  }
  sanitizeNumericArray(arr, min, max, allowZero = false, sort = false) {
    if (!arr) return void 0;
    const sanitized = arr.filter((n) => Number.isInteger(n) && n >= min && n <= max && (allowZero || n !== 0));
    if (sanitized.length === 0) return void 0;
    return sort ? sanitized.sort((a, b) => a - b) : sanitized;
  }
  sanitizeByDay(byDay) {
    const validDay = /^([+-]?\d{1,2})?(MO|TU|WE|TH|FR|SA|SU)$/;
    const days = (byDay != null ? byDay : []).filter((day) => day && typeof day === "string");
    for (const day of days) {
      const match = day.match(validDay);
      if (!match) {
        throw new Error(`Invalid BYDAY value: ${day}`);
      }
      const ord = match[1];
      if (ord) {
        const ordInt = parseInt(ord, 10);
        if (ordInt === 0) {
          throw new Error(`Invalid BYDAY value: ${day}`);
        }
      }
    }
    return days.length > 0 ? days : void 0;
  }
  enforceStrictRfc(opts) {
    var _a;
    if (!opts.strict) return;
    const freq = opts.freq;
    if (opts.byWeekNo && freq !== "YEARLY") {
      throw new Error("BYWEEKNO MUST NOT be used unless FREQ=YEARLY");
    }
    if (opts.byYearDay && ["DAILY", "WEEKLY", "MONTHLY"].includes(freq)) {
      throw new Error("BYYEARDAY MUST NOT be used when FREQ is DAILY, WEEKLY, or MONTHLY");
    }
    if (opts.byMonthDay && freq === "WEEKLY") {
      throw new Error("BYMONTHDAY MUST NOT be used when FREQ is WEEKLY");
    }
    const hasNumericByDay = ((_a = opts.byDay) != null ? _a : []).some((day) => /^[+-]?\d/.test(day));
    if (hasNumericByDay && !["MONTHLY", "YEARLY"].includes(freq)) {
      throw new Error("BYDAY with numeric value MUST NOT be used unless FREQ is MONTHLY or YEARLY");
    }
    if (hasNumericByDay && freq === "YEARLY" && opts.byWeekNo) {
      throw new Error("BYDAY with numeric value MUST NOT be used with FREQ=YEARLY when BYWEEKNO is present");
    }
    const hasOtherBy = Boolean(
      opts.byDay || opts.byMonth || opts.byMonthDay || opts.byYearDay || opts.byWeekNo || opts.byHour || opts.byMinute || opts.bySecond
    );
    if (opts.bySetPos && !hasOtherBy) {
      throw new Error("BYSETPOS MUST be used with another BYxxx rule part");
    }
  }
  sanitizeOpts(opts) {
    var _a;
    opts.byDay = this.sanitizeByDay(opts.byDay);
    if (opts.byMonth) {
      const numeric = opts.byMonth.filter((v) => typeof v === "number");
      const stringy = opts.byMonth.filter((v) => typeof v === "string");
      const sanitizedNum = (_a = this.sanitizeNumericArray(numeric, 1, 12, false, false)) != null ? _a : [];
      const merged = [...sanitizedNum, ...stringy];
      opts.byMonth = merged.length > 0 ? merged : void 0;
    }
    if (opts.rscale && !opts.skip) {
      opts.skip = "OMIT";
    }
    opts.byMonthDay = this.sanitizeNumericArray(opts.byMonthDay, -31, 31, false, false);
    opts.byYearDay = this.sanitizeNumericArray(opts.byYearDay, -366, 366, false, false);
    opts.byWeekNo = this.sanitizeNumericArray(opts.byWeekNo, -53, 53, false, false);
    opts.byHour = this.sanitizeNumericArray(opts.byHour, 0, 23, true, true);
    opts.byMinute = this.sanitizeNumericArray(opts.byMinute, 0, 59, true, true);
    opts.bySecond = this.sanitizeNumericArray(opts.bySecond, 0, 59, true, true);
    if (opts.bySetPos) {
      if (opts.bySetPos.some((p) => p === 0)) {
        throw new Error("bySetPos may not contain 0");
      }
      opts.bySetPos = this.sanitizeNumericArray(opts.bySetPos, -Infinity, Infinity, false, false);
    }
    this.enforceStrictRfc(opts);
    return opts;
  }
  rawAdvance(zdt) {
    const { freq, interval } = this.opts;
    switch (freq) {
      case "DAILY":
        return zdt.add({ days: interval });
      case "WEEKLY":
        return zdt.add({ weeks: interval });
      case "MONTHLY":
        return zdt.add({ months: interval });
      case "YEARLY":
        return zdt.add({ years: interval });
      case "HOURLY": {
        const originalHour = zdt.hour;
        let next = zdt.add({ hours: interval });
        if (next.hour === originalHour && interval === 1) {
          next = next.add({ hours: interval });
        }
        return next;
      }
      case "MINUTELY":
        return zdt.add({ minutes: interval });
      case "SECONDLY":
        return zdt.add({ seconds: interval });
      default:
        throw new Error(`Unsupported FREQ: ${freq}`);
    }
  }
  /**  Expand one base ZonedDateTime into all BYHOUR × BYMINUTE × BYSECOND
   *  combinations, keeping chronological order. If the options are not
   *  present the original date is returned unchanged.
   */
  expandByTime(base) {
    var _a, _b, _c;
    const hours = (_a = this.opts.byHour) != null ? _a : [base.hour];
    const minutes = (_b = this.opts.byMinute) != null ? _b : [base.minute];
    const seconds = (_c = this.opts.bySecond) != null ? _c : [base.second];
    const out = [];
    for (const h of hours) {
      for (const m of minutes) {
        for (const s of seconds) {
          out.push(base.with({ hour: h, minute: m, second: s }));
        }
      }
    }
    return out.sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
  }
  nextCandidateSameDate(zdt) {
    const { freq, interval = 1, byHour, byMinute, bySecond } = this.opts;
    if (freq === "HOURLY" && byHour && byHour.length === 1) {
      return this.applyTimeOverride(zdt.add({ days: interval }));
    }
    if (freq === "MINUTELY" && byMinute && byMinute.length === 1) {
      return this.applyTimeOverride(zdt.add({ hours: interval }));
    }
    if (bySecond && bySecond.length > 1) {
      const idx = bySecond.indexOf(zdt.second);
      if (idx !== -1 && idx < bySecond.length - 1) {
        return zdt.with({ second: bySecond[idx + 1] });
      }
    }
    if (freq === "MINUTELY" && byHour && byHour.length > 1 && !byMinute) {
      const next = zdt.add({ minutes: interval });
      if (byHour.includes(next.hour)) {
        return next.with({ second: bySecond ? bySecond[0] : zdt.second });
      }
      const nextHour = byHour.find((h) => h > zdt.hour) || byHour[0];
      if (nextHour && nextHour > zdt.hour) {
        return zdt.with({ hour: nextHour, minute: 0, second: bySecond ? bySecond[0] : zdt.second });
      }
      return this.applyTimeOverride(zdt.add({ days: 1 }));
    }
    if (freq === "SECONDLY") {
      let candidate = zdt;
      if (bySecond && bySecond.length > 0) {
        const nextSecondInList = bySecond.find((s) => s > candidate.second);
        if (nextSecondInList !== void 0) {
          return candidate.with({ second: nextSecondInList });
        }
        candidate = candidate.with({ second: bySecond[0] }).add({ minutes: 1 });
      } else {
        candidate = candidate.add({ seconds: interval });
      }
      if (byMinute && byMinute.length > 0) {
        if (!byMinute.includes(candidate.minute) || candidate.minute === zdt.minute && candidate.second < zdt.second) {
          const nextMinuteInList = byMinute.find((m) => m > candidate.minute);
          if (nextMinuteInList !== void 0) {
            return candidate.with({ minute: nextMinuteInList, second: bySecond ? bySecond[0] : 0 });
          }
          candidate = candidate.with({ minute: byMinute[0], second: bySecond ? bySecond[0] : 0 }).add({ hours: 1 });
        }
      }
      if (byHour && byHour.length > 0) {
        if (!byHour.includes(candidate.hour) || candidate.hour === zdt.hour && candidate.minute < zdt.minute) {
          const nextHourInList = byHour.find((h) => h > candidate.hour);
          if (nextHourInList !== void 0) {
            return candidate.with({
              hour: nextHourInList,
              minute: byMinute ? byMinute[0] : 0,
              second: bySecond ? bySecond[0] : 0
            });
          }
          candidate = candidate.with({ hour: byHour[0], minute: byMinute ? byMinute[0] : 0, second: bySecond ? bySecond[0] : 0 }).add({ days: 1 });
        }
      }
      return candidate;
    }
    if (byMinute && byMinute.length > 1) {
      const idx = byMinute.indexOf(zdt.minute);
      if (idx !== -1 && idx < byMinute.length - 1) {
        return zdt.with({
          minute: byMinute[idx + 1],
          second: bySecond ? bySecond[0] : zdt.second
        });
      }
      if (freq === "MINUTELY" && idx === byMinute.length - 1) {
        if (byHour && byHour.length > 0) {
          const currentHourIdx = byHour.indexOf(zdt.hour);
          if (currentHourIdx !== -1 && currentHourIdx < byHour.length - 1) {
            return zdt.with({
              hour: byHour[currentHourIdx + 1],
              minute: byMinute[0],
              second: bySecond ? bySecond[0] : zdt.second
            });
          } else {
            return this.applyTimeOverride(zdt.add({ days: 1 }));
          }
        }
        return zdt.add({ hours: interval }).with({
          minute: byMinute[0],
          second: bySecond ? bySecond[0] : zdt.second
        });
      }
    }
    if (byHour && byHour.length > 1) {
      const idx = byHour.indexOf(zdt.hour);
      if (idx !== -1 && idx < byHour.length - 1) {
        return zdt.with({
          hour: byHour[idx + 1],
          minute: byMinute ? byMinute[0] : zdt.minute,
          second: bySecond ? bySecond[0] : zdt.second
        });
      }
    }
    if (freq === "HOURLY" && byHour && byHour.length > 1) {
      return this.applyTimeOverride(zdt.add({ days: 1 }));
    }
    return this.applyTimeOverride(this.rawAdvance(zdt));
  }
  applyTimeOverride(zdt) {
    const { byHour, byMinute, bySecond } = this.opts;
    let dt = zdt;
    if (byHour) dt = dt.with({ hour: byHour[0] });
    if (byMinute) dt = dt.with({ minute: byMinute[0] });
    if (bySecond) dt = dt.with({ second: bySecond[0] });
    return dt;
  }
  computeFirst() {
    var _a, _b, _c, _d;
    let zdt = this.originalDtstart;
    if (((_a = this.opts.byWeekNo) == null ? void 0 : _a.length) && ["DAILY", "HOURLY", "MINUTELY", "SECONDLY"].includes(this.opts.freq)) {
      let targetWeek = this.opts.byWeekNo[0];
      let targetYear = zdt.year;
      while (targetYear <= zdt.year + 10) {
        const jan1 = zdt.with({ year: targetYear, month: 1, day: 1 });
        const dec31 = zdt.with({ year: targetYear, month: 12, day: 31 });
        let hasTargetWeek = false;
        if (targetWeek > 0) {
          let maxWeek = 52;
          if (jan1.dayOfWeek === 4 || dec31.dayOfWeek === 4) {
            maxWeek = 53;
          }
          hasTargetWeek = targetWeek <= maxWeek;
        } else {
          let maxWeek = 52;
          if (jan1.dayOfWeek === 4 || dec31.dayOfWeek === 4) {
            maxWeek = 53;
          }
          hasTargetWeek = -targetWeek <= maxWeek;
        }
        if (hasTargetWeek) {
          const firstThursday = jan1.add({ days: (4 - jan1.dayOfWeek + 7) % 7 });
          let weekStart;
          if (targetWeek > 0) {
            weekStart = firstThursday.subtract({ days: 3 }).add({ weeks: targetWeek - 1 });
          } else {
            const lastWeek = jan1.dayOfWeek === 4 || dec31.dayOfWeek === 4 ? 53 : 52;
            weekStart = firstThursday.subtract({ days: 3 }).add({ weeks: lastWeek + targetWeek });
          }
          if ((_b = this.opts.byDay) == null ? void 0 : _b.length) {
            const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
            const targetDays = this.opts.byDay.map((tok) => {
              var _a2;
              return (_a2 = tok.match(/(MO|TU|WE|TH|FR|SA|SU)$/)) == null ? void 0 : _a2[1];
            }).filter(Boolean).map((day) => dayMap[day]).filter(Boolean);
            if (targetDays.length) {
              const candidates = targetDays.map((dayOfWeek) => {
                const delta = (dayOfWeek - weekStart.dayOfWeek + 7) % 7;
                return weekStart.add({ days: delta });
              });
              const firstCandidate = candidates.sort((a, b) => Temporal.ZonedDateTime.compare(a, b))[0];
              if (firstCandidate && Temporal.ZonedDateTime.compare(firstCandidate, this.originalDtstart) >= 0) {
                zdt = firstCandidate;
                break;
              }
            }
          } else {
            if (Temporal.ZonedDateTime.compare(weekStart, this.originalDtstart) >= 0) {
              zdt = weekStart;
              break;
            }
          }
        }
        targetYear++;
      }
    }
    if (((_c = this.opts.byDay) == null ? void 0 : _c.length) && !this.opts.byWeekNo) {
      const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
      const hasOrdinalTokens = this.opts.byDay.some((tok) => /^[+-]?\d/.test(tok));
      if (hasOrdinalTokens && this.opts.byMonth && (this.opts.freq === "MINUTELY" || this.opts.freq === "SECONDLY")) {
        const months = this.opts.byMonth.filter((v) => typeof v === "number").sort((a, b) => a - b);
        let foundFirst = false;
        for (let year = zdt.year; year <= zdt.year + 10 && !foundFirst; year++) {
          for (const month of months) {
            if (year === zdt.year && month < zdt.month) continue;
            const monthSample = zdt.with({ year, month, day: 1 });
            const monthlyOccs = this.generateMonthlyOccurrences(monthSample);
            for (const occ of monthlyOccs) {
              if (Temporal.ZonedDateTime.compare(occ, zdt) >= 0) {
                if (!occ.toPlainDate().equals(zdt.toPlainDate())) {
                  zdt = this.applyTimeOverride(occ.with({ hour: 0, minute: 0, second: 0 }));
                } else {
                  zdt = occ;
                }
                foundFirst = true;
                break;
              }
            }
            if (foundFirst) break;
          }
        }
      } else {
        let deltas;
        if (["DAILY", "HOURLY", "MINUTELY", "SECONDLY"].includes(this.opts.freq) && this.opts.byDay.every((tok) => /^[A-Z]{2}$/.test(tok))) {
          deltas = this.opts.byDay.map((tok) => (dayMap[tok] - zdt.dayOfWeek + 7) % 7);
        } else {
          deltas = this.opts.byDay.map((tok) => {
            var _a2;
            const wdTok = (_a2 = tok.match(/(MO|TU|WE|TH|FR|SA|SU)$/)) == null ? void 0 : _a2[1];
            return wdTok ? (dayMap[wdTok] - zdt.dayOfWeek + 7) % 7 : null;
          }).filter((d) => d !== null);
        }
        if (deltas.length) {
          zdt = zdt.add({ days: Math.min(...deltas) });
        }
      }
    }
    const { byHour, byMinute, bySecond } = this.opts;
    if (this.opts.freq === "HOURLY" && !byHour && Temporal.ZonedDateTime.compare(
      zdt.with({ hour: 0, minute: 0, second: 0, microsecond: 0, nanosecond: 0 }),
      this.originalDtstart
    ) > 0) {
      zdt = zdt.with({ hour: 0, minute: 0, second: 0, microsecond: 0, nanosecond: 0 });
    }
    if (this.opts.freq === "MINUTELY" && !byMinute && Temporal.ZonedDateTime.compare(
      zdt.with({ hour: 0, minute: 0, second: 0, microsecond: 0, nanosecond: 0 }),
      this.originalDtstart
    ) > 0) {
      zdt = zdt.with({ hour: 0, minute: 0, second: 0, microsecond: 0, nanosecond: 0 });
    }
    if (this.opts.freq === "SECONDLY" && ((_d = this.opts.byWeekNo) == null ? void 0 : _d.length) && !bySecond && Temporal.ZonedDateTime.compare(
      zdt.with({ hour: 0, minute: 0, second: 0, microsecond: 0, nanosecond: 0 }),
      this.originalDtstart
    ) > 0) {
      zdt = zdt.with({ hour: 0, minute: 0, second: 0, microsecond: 0, nanosecond: 0 });
    }
    if (byHour || byMinute || bySecond) {
      const candidates = this.expandByTime(zdt);
      for (const candidate of candidates) {
        if (Temporal.ZonedDateTime.compare(candidate, this.originalDtstart) >= 0) {
          return candidate;
        }
      }
      zdt = this.applyTimeOverride(this.rawAdvance(zdt));
    }
    return zdt;
  }
  // --- NEW: constraint checks ---
  // 2) Replace your matchesByDay with this:
  matchesByDay(zdt) {
    const { byDay, freq } = this.opts;
    if (!byDay) return true;
    const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
    for (const token of byDay) {
      const m = token.match(/^([+-]?\d{1,2})?(MO|TU|WE|TH|FR|SA|SU)$/);
      if (!m) continue;
      const ord = m[1] ? parseInt(m[1], 10) : 0;
      const weekday = m[2];
      if (!weekday) continue;
      const wd = dayMap[weekday];
      if (freq === "DAILY") {
        if (zdt.dayOfWeek === wd) return true;
        continue;
      }
      if (ord === 0) {
        if (zdt.dayOfWeek === wd) return true;
        continue;
      }
      const month = zdt.month;
      let dt = zdt.with({ day: 1 });
      const candidates = [];
      while (dt.month === month) {
        if (dt.dayOfWeek === wd) candidates.push(dt.day);
        dt = dt.add({ days: 1 });
      }
      const idx = ord > 0 ? ord - 1 : candidates.length + ord;
      if (candidates[idx] === zdt.day) return true;
    }
    return false;
  }
  matchesByMonth(zdt) {
    const { byMonth } = this.opts;
    if (!byMonth) return true;
    const nums = byMonth.filter((v) => typeof v === "number");
    if (nums.length === 0) return true;
    return nums.includes(zdt.month);
  }
  matchesNumericConstraint(value, constraints, maxPositiveValue) {
    return constraints.some((c) => {
      const target = c > 0 ? c : maxPositiveValue + c + 1;
      return value === target;
    });
  }
  matchesByMonthDay(zdt) {
    const { byMonthDay } = this.opts;
    if (!byMonthDay) return true;
    const lastDay = zdt.with({ day: 1 }).add({ months: 1 }).subtract({ days: 1 }).day;
    return this.matchesNumericConstraint(zdt.day, byMonthDay, lastDay);
  }
  matchesByHour(zdt) {
    const { byHour } = this.opts;
    if (!byHour) return true;
    if (byHour.includes(zdt.hour)) {
      return true;
    }
    for (const h of byHour) {
      const intendedTime = zdt.with({ hour: h });
      if (intendedTime.hour === zdt.hour) {
        return true;
      }
    }
    return false;
  }
  matchesByMinute(zdt) {
    const { byMinute } = this.opts;
    if (!byMinute) return true;
    return byMinute.includes(zdt.minute);
  }
  matchesBySecond(zdt) {
    const { bySecond } = this.opts;
    if (!bySecond) return true;
    return bySecond.includes(zdt.second);
  }
  matchesAll(zdt) {
    return this.matchesByMonth(zdt) && this.matchesByWeekNo(zdt) && this.matchesByYearDay(zdt) && this.matchesByMonthDay(zdt) && this.matchesByDay(zdt) && this.matchesByHour(zdt) && this.matchesByMinute(zdt) && this.matchesBySecond(zdt);
  }
  matchesByYearDay(zdt) {
    const { byYearDay } = this.opts;
    if (!byYearDay) return true;
    const dayOfYear = zdt.dayOfYear;
    const last = zdt.with({ month: 12, day: 31 }).dayOfYear;
    return this.matchesNumericConstraint(dayOfYear, byYearDay, last);
  }
  getIsoWeekInfo(zdt) {
    const thursday = zdt.add({ days: 4 - zdt.dayOfWeek });
    const year = thursday.year;
    const jan1 = zdt.with({ year, month: 1, day: 1 });
    const firstThursday = jan1.add({ days: (4 - jan1.dayOfWeek + 7) % 7 });
    const diffDays = thursday.toPlainDate().since(firstThursday.toPlainDate()).days;
    const week = Math.floor(diffDays / 7) + 1;
    return { week, year };
  }
  matchesByWeekNo(zdt) {
    const { byWeekNo } = this.opts;
    if (!byWeekNo) return true;
    const { week, year } = this.getIsoWeekInfo(zdt);
    const jan1 = zdt.with({ year, month: 1, day: 1 });
    const isLeapYear = jan1.inLeapYear;
    const lastWeek = jan1.dayOfWeek === 4 || isLeapYear && jan1.dayOfWeek === 3 ? 53 : 52;
    return byWeekNo.some((wn) => {
      if (wn > 0) {
        return week === wn;
      } else {
        return week === lastWeek + wn + 1;
      }
    });
  }
  options() {
    return this.opts;
  }
  cloneOptions() {
    const _a = this.opts, {
      byHour,
      byMinute,
      bySecond,
      byDay,
      byMonth,
      byMonthDay,
      byYearDay,
      byWeekNo,
      bySetPos,
      rDate,
      exDate
    } = _a, rest = __objRest(_a, [
      "byHour",
      "byMinute",
      "bySecond",
      "byDay",
      "byMonth",
      "byMonthDay",
      "byYearDay",
      "byWeekNo",
      "bySetPos",
      "rDate",
      "exDate"
    ]);
    return __spreadProps(__spreadValues({}, rest), {
      byHour: byHour ? [...byHour] : void 0,
      byMinute: byMinute ? [...byMinute] : void 0,
      bySecond: bySecond ? [...bySecond] : void 0,
      byDay: byDay ? [...byDay] : void 0,
      byMonth: byMonth ? [...byMonth] : void 0,
      byMonthDay: byMonthDay ? [...byMonthDay] : void 0,
      byYearDay: byYearDay ? [...byYearDay] : void 0,
      byWeekNo: byWeekNo ? [...byWeekNo] : void 0,
      bySetPos: bySetPos ? [...bySetPos] : void 0,
      rDate: rDate ? [...rDate] : void 0,
      exDate: exDate ? [...exDate] : void 0
    });
  }
  cloneUpdateOptions(updates) {
    const cloned = {};
    if (Object.prototype.hasOwnProperty.call(updates, "byHour")) {
      cloned.byHour = Array.isArray(updates.byHour) ? [...updates.byHour] : updates.byHour;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "byMinute")) {
      cloned.byMinute = Array.isArray(updates.byMinute) ? [...updates.byMinute] : updates.byMinute;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "bySecond")) {
      cloned.bySecond = Array.isArray(updates.bySecond) ? [...updates.bySecond] : updates.bySecond;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "byDay")) {
      cloned.byDay = Array.isArray(updates.byDay) ? [...updates.byDay] : updates.byDay;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "byMonth")) {
      cloned.byMonth = Array.isArray(updates.byMonth) ? [...updates.byMonth] : updates.byMonth;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "byMonthDay")) {
      cloned.byMonthDay = Array.isArray(updates.byMonthDay) ? [...updates.byMonthDay] : updates.byMonthDay;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "byYearDay")) {
      cloned.byYearDay = Array.isArray(updates.byYearDay) ? [...updates.byYearDay] : updates.byYearDay;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "byWeekNo")) {
      cloned.byWeekNo = Array.isArray(updates.byWeekNo) ? [...updates.byWeekNo] : updates.byWeekNo;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "bySetPos")) {
      cloned.bySetPos = Array.isArray(updates.bySetPos) ? [...updates.bySetPos] : updates.bySetPos;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "rDate")) {
      cloned.rDate = Array.isArray(updates.rDate) ? [...updates.rDate] : updates.rDate;
    }
    if (Object.prototype.hasOwnProperty.call(updates, "exDate")) {
      cloned.exDate = Array.isArray(updates.exDate) ? [...updates.exDate] : updates.exDate;
    }
    return cloned;
  }
  /**
   * Create a new {@link RRuleTemporal} instance with modified options while keeping the current one unchanged.
   *
   * @example
   * ```ts
   * const updated = rule.with({byMonthDay: [3]});
   * ```
   */
  with(updates) {
    var _a, _b;
    const merged = __spreadProps(__spreadValues(__spreadValues(__spreadValues({}, this.cloneOptions()), updates), this.cloneUpdateOptions(updates)), {
      tzid: (_a = updates.tzid) != null ? _a : this.opts.tzid,
      dtstart: (_b = updates.dtstart) != null ? _b : this.opts.dtstart
    });
    return new _RRuleTemporal(merged);
  }
  addDtstartIfNeeded(dates, iterator) {
    if (this.includeDtstart && !this.matchesAll(this.originalDtstart)) {
      if (iterator && this.isExcluded(this.originalDtstart)) {
        return true;
      }
      if (iterator && !iterator(this.originalDtstart, dates.length)) {
        return false;
      }
      dates.push(this.originalDtstart);
      if (this.shouldBreakForCountLimit(dates.length)) {
        return false;
      }
    }
    return true;
  }
  processOccurrences(occs, dates, start, iterator, extraFilters) {
    let shouldBreak = false;
    for (const occ of occs) {
      if (Temporal.ZonedDateTime.compare(occ, start) < 0) continue;
      if (this.opts.until && Temporal.ZonedDateTime.compare(occ, this.opts.until) > 0) {
        shouldBreak = true;
        break;
      }
      if (extraFilters && !extraFilters(occ)) {
        continue;
      }
      if (iterator && this.isExcluded(occ)) {
        continue;
      }
      if (iterator && !iterator(occ, dates.length)) {
        shouldBreak = true;
        break;
      }
      dates.push(occ);
      if (this.shouldBreakForCountLimit(dates.length)) {
        shouldBreak = true;
        break;
      }
    }
    return { shouldBreak };
  }
  /**
   * Returns all occurrences of the rule.
   * @param iterator - An optional callback iterator function that can be used to filter or modify the occurrences.
   * @returns An array of Temporal.ZonedDateTime objects representing all occurrences of the rule.
   */
  _allMonthlyByDayOrMonthDay(iterator) {
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    let monthCursor = start.with({ day: 1 });
    while (true) {
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      let occs = this.generateMonthlyOccurrences(monthCursor);
      occs = this.applyBySetPos(occs);
      if (monthCursor.month === start.month && occs.some((o) => Temporal.ZonedDateTime.compare(o, start) < 0) && occs.some((o) => Temporal.ZonedDateTime.compare(o, start) === 0)) {
        monthCursor = monthCursor.add({ months: this.opts.interval });
        continue;
      }
      const { shouldBreak } = this.processOccurrences(occs, dates, start, iterator);
      if (shouldBreak) {
        break;
      }
      monthCursor = monthCursor.add({ months: this.opts.interval });
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  _allWeekly(iterator) {
    var _a;
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
    const tokens = this.opts.byDay ? [...this.opts.byDay] : this.opts.byMonthDay && this.opts.byMonthDay.length > 0 ? Object.keys(dayMap) : [Object.entries(dayMap).find(([, d]) => d === start.dayOfWeek)[0]];
    const dows = tokens.map((tok) => dayMap[tok.slice(-2)]).filter((d) => d !== void 0).sort((a, b) => a - b);
    const firstWeekDates = dows.map((dw) => {
      const delta = (dw - start.dayOfWeek + 7) % 7;
      return start.add({ days: delta });
    });
    const firstOccurrence = firstWeekDates.reduce((a, b) => Temporal.ZonedDateTime.compare(a, b) <= 0 ? a : b);
    const wkstDay = (_a = dayMap[this.opts.wkst || "MO"]) != null ? _a : 1;
    const firstOccWeekOffset = (firstOccurrence.dayOfWeek - wkstDay + 7) % 7;
    let weekCursor = firstOccurrence.subtract({ days: firstOccWeekOffset });
    while (true) {
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      let occs = dows.flatMap((dw) => {
        const delta = (dw - wkstDay + 7) % 7;
        const sameDate = weekCursor.add({ days: delta });
        return this.expandByTime(sameDate);
      }).sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
      occs = this.applyBySetPos(occs);
      const { shouldBreak } = this.processOccurrences(
        occs,
        dates,
        start,
        iterator,
        (occ) => this.matchesByMonth(occ) && this.matchesByMonthDay(occ)
      );
      if (shouldBreak) {
        break;
      }
      weekCursor = weekCursor.add({ weeks: this.opts.interval });
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  _allMonthlyByMonth(iterator) {
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    const months = this.opts.byMonth.filter((v) => typeof v === "number").sort((a, b) => a - b);
    let monthOffset = 0;
    let startMonthIndex = months.findIndex((m) => m >= start.month);
    if (startMonthIndex === -1) {
      startMonthIndex = 0;
      monthOffset = 1;
    }
    while (true) {
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      const monthIndex = startMonthIndex + monthOffset;
      const targetMonth = months[monthIndex % months.length];
      const yearsToAdd = Math.floor(monthIndex / months.length);
      const candidate = start.with({
        year: start.year + yearsToAdd,
        month: targetMonth
      });
      if (this.opts.until && Temporal.ZonedDateTime.compare(candidate, this.opts.until) > 0) {
        break;
      }
      if (Temporal.ZonedDateTime.compare(candidate, start) >= 0) {
        if (iterator && this.isExcluded(candidate)) {
          continue;
        }
        if (iterator && !iterator(candidate, dates.length)) {
          break;
        }
        dates.push(candidate);
        if (this.shouldBreakForCountLimit(dates.length)) {
          break;
        }
      }
      monthOffset++;
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  _allYearlyByMonth(iterator) {
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    const months = this.opts.byMonth.filter((v) => typeof v === "number").sort((a, b) => a - b);
    let yearOffset = 0;
    while (true) {
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      const year = start.year + yearOffset * this.opts.interval;
      for (const month of months) {
        let occ = start.with({ year, month });
        occ = this.applyTimeOverride(occ);
        if (Temporal.ZonedDateTime.compare(occ, start) < 0) {
          continue;
        }
        if (this.opts.until && Temporal.ZonedDateTime.compare(occ, this.opts.until) > 0) {
          return this.applyCountLimitAndMergeRDates(dates, iterator);
        }
        if (iterator && this.isExcluded(occ)) {
          continue;
        }
        if (iterator && !iterator(occ, dates.length)) {
          return this.applyCountLimitAndMergeRDates(dates, iterator);
        }
        dates.push(occ);
        if (this.shouldBreakForCountLimit(dates.length)) {
          return this.applyCountLimitAndMergeRDates(dates, iterator);
        }
      }
      yearOffset++;
    }
  }
  _allYearlyComplex(iterator) {
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    let yearCursor = start.with({ month: 1, day: 1 });
    while (true) {
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      const occs = this.generateYearlyOccurrences(yearCursor);
      const uniqueOccs = [];
      if (occs.length > 0) {
        uniqueOccs.push(occs[0]);
        for (let i = 1; i < occs.length; i++) {
          if (Temporal.ZonedDateTime.compare(occs[i], occs[i - 1]) !== 0) {
            uniqueOccs.push(occs[i]);
          }
        }
      }
      const { shouldBreak } = this.processOccurrences(uniqueOccs, dates, start, iterator);
      if (shouldBreak) {
        break;
      }
      const interval = this.opts.freq === "WEEKLY" ? 1 : this.opts.interval;
      yearCursor = yearCursor.add({ years: interval });
      if (this.opts.freq === "WEEKLY" && this.opts.until && yearCursor.year > this.opts.until.year) {
        break;
      }
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  _allMinutelySecondlyComplex(iterator) {
    const dates = [];
    let iterationCount = 0;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    let current = this.computeFirst();
    while (true) {
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      if (this.opts.until && Temporal.ZonedDateTime.compare(current, this.opts.until) > 0) {
        break;
      }
      if (this.matchesAll(current)) {
        if (iterator && this.isExcluded(current)) {
          current = this.nextCandidateSameDate(current);
          continue;
        }
        if (iterator && !iterator(current, dates.length)) {
          break;
        }
        dates.push(current);
        if (this.shouldBreakForCountLimit(dates.length)) {
          break;
        }
        current = this.nextCandidateSameDate(current);
      } else {
        current = this.findNextValidDate(current);
      }
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  _allMonthlyByWeekNo(iterator) {
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    let current = start;
    const weekNos = [...this.opts.byWeekNo].sort((a, b) => a - b);
    const interval = this.opts.interval;
    let monthsAdvanced = 0;
    let lastYearProcessed = -1;
    outer_loop: while (true) {
      if (this.shouldBreakForCountLimit(dates.length)) {
        break;
      }
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      const year = current.year;
      if (year !== lastYearProcessed && current.month >= start.month) {
        lastYearProcessed = year;
        for (const weekNo of weekNos) {
          const occs = this.generateOccurrencesForWeekInYear(year, weekNo);
          for (const occ of occs) {
            if (Temporal.ZonedDateTime.compare(occ, start) >= 0) {
              if (iterator && this.isExcluded(occ)) {
                continue;
              }
              if (iterator && !iterator(occ, dates.length)) {
                break outer_loop;
              }
              dates.push(occ);
              if (this.shouldBreakForCountLimit(dates.length)) {
                break outer_loop;
              }
            }
          }
        }
      }
      monthsAdvanced += interval;
      current = start.add({ months: monthsAdvanced });
      if (this.opts.until && Temporal.ZonedDateTime.compare(current, this.opts.until) > 0) {
        break;
      }
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  _allMonthlyByYearDay(iterator) {
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    let year = start.year;
    const yearDays = [...this.opts.byYearDay].sort((a, b) => a - b);
    const interval = this.opts.interval;
    const startMonthAbs = start.year * 12 + start.month;
    outer_loop: while (true) {
      if (this.shouldBreakForCountLimit(dates.length)) {
        break;
      }
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      const yearStart = start.with({ year, month: 1, day: 1 });
      const lastDayOfYear = yearStart.with({ month: 12, day: 31 }).dayOfYear;
      for (const yd of yearDays) {
        const dayNum = yd > 0 ? yd : lastDayOfYear + yd + 1;
        if (dayNum <= 0 || dayNum > lastDayOfYear) continue;
        const baseOcc = yearStart.add({ days: dayNum - 1 });
        for (const occ of this.expandByTime(baseOcc)) {
          if (Temporal.ZonedDateTime.compare(occ, start) < 0) continue;
          if (dates.some((d) => Temporal.ZonedDateTime.compare(d, occ) === 0)) continue;
          const occMonthAbs = occ.year * 12 + occ.month;
          if ((occMonthAbs - startMonthAbs) % interval !== 0) {
            continue;
          }
          if (!this.matchesByMonth(occ)) {
            continue;
          }
          if (this.opts.until && Temporal.ZonedDateTime.compare(occ, this.opts.until) > 0) {
            break outer_loop;
          }
          if (iterator && this.isExcluded(occ)) {
            continue;
          }
          if (iterator && !iterator(occ, dates.length)) {
            break outer_loop;
          }
          dates.push(occ);
          if (this.shouldBreakForCountLimit(dates.length)) {
            break outer_loop;
          }
        }
      }
      year++;
      if (this.opts.until && year > this.opts.until.year + 2) {
        break;
      }
      if (!this.opts.until && this.opts.count) {
        const yearsToScan = Math.ceil(this.opts.count / (this.opts.byYearDay.length || 1)) * interval + 5;
        if (year > start.year + yearsToScan) {
          break;
        }
      }
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  _allDailyMinutelyHourlyWithBySetPos(iterator) {
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    let cursor;
    let duration;
    switch (this.opts.freq) {
      case "MINUTELY":
        cursor = start.with({ second: 0, microsecond: 0, nanosecond: 0 });
        duration = { minutes: this.opts.interval };
        break;
      case "HOURLY":
        cursor = start.with({ minute: 0, second: 0, microsecond: 0, nanosecond: 0 });
        duration = { hours: this.opts.interval };
        break;
      case "DAILY":
        cursor = start.with({ hour: 0, minute: 0, second: 0, microsecond: 0, nanosecond: 0 });
        duration = { days: this.opts.interval };
        break;
      default:
        return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    while (true) {
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      let periodOccs = this.expandByTime(cursor);
      periodOccs = periodOccs.filter((occ) => this.matchesAll(occ));
      periodOccs = this.applyBySetPos(periodOccs);
      const { shouldBreak } = this.processOccurrences(periodOccs, dates, start, iterator);
      if (shouldBreak) {
        break;
      }
      cursor = cursor.add(duration);
      if (this.opts.until && Temporal.ZonedDateTime.compare(cursor, this.opts.until) > 0) {
        break;
      }
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  _allFallback(iterator) {
    const dates = [];
    let iterationCount = 0;
    let current = this.computeFirst();
    if (this.includeDtstart && Temporal.ZonedDateTime.compare(current, this.originalDtstart) > 0) {
      if (iterator && this.isExcluded(this.originalDtstart)) {
      } else {
        if (iterator && !iterator(this.originalDtstart, dates.length)) {
          return this.applyCountLimitAndMergeRDates(dates, iterator);
        }
        dates.push(this.originalDtstart);
        if (this.shouldBreakForCountLimit(dates.length)) {
          return this.applyCountLimitAndMergeRDates(dates, iterator);
        }
      }
    }
    while (true) {
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      if (this.opts.until && Temporal.ZonedDateTime.compare(current, this.opts.until) > 0) {
        break;
      }
      if (this.matchesAll(current)) {
        if (iterator && this.isExcluded(current)) {
        } else {
          if (iterator && !iterator(current, dates.length)) {
            break;
          }
          dates.push(current);
          if (this.shouldBreakForCountLimit(dates.length)) {
            break;
          }
        }
      }
      current = this.nextCandidateSameDate(current);
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  /**
   * Returns all occurrences of the rule.
   * @param iterator - An optional callback iterator function that can be used to filter or modify the occurrences.
   * @returns An array of Temporal.ZonedDateTime objects representing all occurrences of the rule.
   */
  all(iterator) {
    if (this.opts.rscale && ["CHINESE", "HEBREW", "INDIAN"].includes(this.opts.rscale)) {
      if (["YEARLY", "MONTHLY", "WEEKLY"].includes(this.opts.freq) || !!this.opts.byYearDay || !!this.opts.byWeekNo || this.opts.byMonthDay && this.opts.byMonthDay.length > 0) {
        return this._allRscaleNonGregorian(iterator);
      }
    }
    if (this.opts.byWeekNo && this.opts.byYearDay) {
      const yearStart = this.originalDtstart.with({ month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 });
      const yearDays = this.opts.byYearDay.map((yd) => {
        const lastDayOfYear = yearStart.with({ month: 12, day: 31 }).dayOfYear;
        return yd > 0 ? yd : lastDayOfYear + yd + 1;
      });
      let possibleDate = false;
      for (const yd of yearDays) {
        const date = yearStart.add({ days: yd - 1 });
        if (this.matchesByWeekNo(date)) {
          possibleDate = true;
          break;
        }
      }
      if (!possibleDate) {
        return [];
      }
    }
    if (!this.opts.count && !this.opts.until && !iterator) {
      throw new Error("all() requires iterator when no COUNT/UNTIL");
    }
    if (this.opts.freq === "MONTHLY" && (this.opts.byDay || this.opts.byMonthDay) && !this.opts.byWeekNo) {
      return this._allMonthlyByDayOrMonthDay(iterator);
    }
    if (this.opts.freq === "WEEKLY" && !(this.opts.byYearDay && this.opts.byYearDay.length > 0) && !(this.opts.byWeekNo && this.opts.byWeekNo.length > 0)) {
      return this._allWeekly(iterator);
    }
    if (this.opts.freq === "MONTHLY" && this.opts.byMonth && !this.opts.byDay && !this.opts.byMonthDay && !this.opts.byYearDay) {
      return this._allMonthlyByMonth(iterator);
    }
    if (this.opts.freq === "YEARLY" && this.opts.byMonth && !this.opts.byDay && !this.opts.byMonthDay && !this.opts.byYearDay && !this.opts.byWeekNo) {
      return this._allYearlyByMonth(iterator);
    }
    if (this.opts.freq === "YEARLY" && (this.opts.byDay || this.opts.byMonthDay || this.opts.byYearDay || this.opts.byWeekNo) || this.opts.freq === "WEEKLY" && this.opts.byYearDay && this.opts.byYearDay.length > 0 || this.opts.freq === "WEEKLY" && this.opts.byWeekNo && this.opts.byWeekNo.length > 0) {
      return this._allYearlyComplex(iterator);
    }
    if ((this.opts.freq === "MINUTELY" || this.opts.freq === "SECONDLY") && (this.opts.byMonth || this.opts.byWeekNo || this.opts.byYearDay || this.opts.byMonthDay || this.opts.byDay)) {
      return this._allMinutelySecondlyComplex(iterator);
    }
    if (this.opts.freq === "MONTHLY" && this.opts.byWeekNo && this.opts.byWeekNo.length > 0) {
      return this._allMonthlyByWeekNo(iterator);
    }
    if (this.opts.freq === "MONTHLY" && this.opts.byYearDay && this.opts.byYearDay.length > 0 && !this.opts.byDay && !this.opts.byMonthDay) {
      return this._allMonthlyByYearDay(iterator);
    }
    if (this.opts.rscale && this.opts.freq === "MONTHLY" && !this.opts.byDay && !this.opts.byMonthDay && !this.opts.byWeekNo && !this.opts.byYearDay) {
      return this._allMonthlyRscaleSimple(iterator);
    }
    if ((this.opts.freq === "MINUTELY" || this.opts.freq === "HOURLY" || this.opts.freq === "DAILY") && this.opts.bySetPos) {
      return this._allDailyMinutelyHourlyWithBySetPos(iterator);
    }
    return this._allFallback(iterator);
  }
  /**
   * RFC 7529: RSCALE present, simple monthly iteration with SKIP behavior.
   * Handles month-to-month stepping from DTSTART's year/month aiming for DTSTART's day-of-month.
   * Applies SKIP=OMIT (skip invalid months), BACKWARD (clamp to last day), FORWARD (first day of next month).
   */
  _allMonthlyRscaleSimple(iterator) {
    var _a;
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    const interval = (_a = this.opts.interval) != null ? _a : 1;
    const targetDom = start.day;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    let cursor = start.with({ day: 1 });
    while (true) {
      if (++iterationCount > this.maxIterations) {
        throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
      }
      const lastDay = cursor.add({ months: 1 }).subtract({ days: 1 }).day;
      let occ = null;
      if (targetDom <= lastDay) {
        occ = cursor.with({ day: targetDom });
      } else {
        const skip = this.opts.skip || "OMIT";
        if (skip === "BACKWARD") {
          occ = cursor.with({ day: lastDay });
        } else if (skip === "FORWARD") {
          occ = cursor.add({ months: 1 }).with({ day: 1 });
        } else {
          occ = null;
        }
      }
      if (occ) {
        occ = occ.with({ hour: start.hour, minute: start.minute, second: start.second });
        if (!(iterator && this.isExcluded(occ))) {
          if (Temporal.ZonedDateTime.compare(occ, start) >= 0) {
            if (!iterator || iterator(occ, dates.length)) {
              dates.push(occ);
              if (this.shouldBreakForCountLimit(dates.length)) break;
            } else {
              break;
            }
          }
        }
      }
      cursor = cursor.add({ months: interval });
      if (this.opts.until && Temporal.ZonedDateTime.compare(cursor, this.opts.until) > 0) {
        break;
      }
    }
    return this.applyCountLimitAndMergeRDates(dates, iterator);
  }
  /**
   * Converts rDate entries to ZonedDateTime and merges with existing dates.
   * @param dates - Array of dates to merge with
   * @returns Merged and deduplicated array of dates
   */
  mergeAndDeduplicateRDates(dates) {
    if (this.opts.rDate) {
      dates.push(...this.opts.rDate);
    }
    dates.sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
    const dedup = [];
    for (const d of dates) {
      if (dedup.length === 0 || Temporal.ZonedDateTime.compare(d, dedup[dedup.length - 1]) !== 0) {
        dedup.push(d);
      }
    }
    return dedup;
  }
  /**
   * Checks if a date is in the exDate list.
   * @param date - Date to check
   * @returns True if the date is excluded
   */
  isExcluded(date) {
    if (!this.opts.exDate || this.opts.exDate.length === 0) return false;
    return this.opts.exDate.some((exDate) => Temporal.ZonedDateTime.compare(date, exDate) === 0);
  }
  /**
   * Excludes exDate entries from the given array of dates.
   * @param dates - Array of dates to filter
   * @returns Filtered array with exDate entries removed
   */
  excludeExDates(dates) {
    if (!this.opts.exDate || this.opts.exDate.length === 0) return dates;
    return dates.filter((date) => {
      return !this.isExcluded(date);
    });
  }
  /**
   * Applies count limit and merges rDates with the rule-generated dates.
   * @param dates - Array of dates generated by the rule
   * @param iterator - Optional iterator function
   * @returns Final array of dates after merging and applying count limit
   */
  applyCountLimitAndMergeRDates(dates, iterator) {
    const merged = this.mergeAndDeduplicateRDates(dates);
    const excluded = this.excludeExDates(merged);
    const hasCountLimit = this.opts.count !== void 0;
    if (!hasCountLimit && !iterator) {
      return excluded;
    }
    let emitted = 0;
    const max = hasCountLimit ? this.opts.count : Infinity;
    const finalDates = [];
    for (const d of excluded) {
      if (emitted >= max) break;
      if (iterator && !iterator(d, emitted)) break;
      finalDates.push(d);
      emitted++;
    }
    return finalDates;
  }
  /**
   * Checks if the count limit should break the loop based on rDate presence.
   * @param matchCount - Current number of matches
   * @returns true if the loop should break
   */
  shouldBreakForCountLimit(matchCount) {
    if (this.opts.count === void 0) return false;
    if (!this.opts.rDate) {
      return matchCount >= this.opts.count;
    }
    const rDateCount = this.opts.rDate.length;
    const targetRuleCount = Math.max(this.opts.count - rDateCount, 0);
    const safetyMargin = Math.min(targetRuleCount, 10);
    return matchCount >= targetRuleCount + safetyMargin;
  }
  /**
   * Returns all occurrences of the rule within a specified time window.
   * @param after - The start date or Temporal.ZonedDateTime object.
   * @param before - The end date or Temporal.ZonedDateTime object.
   * @param inc - Optional boolean flag to include the end date in the results.
   * @returns An array of Temporal.ZonedDateTime objects representing all occurrences of the rule within the specified time window.
   */
  between(after, before, inc = false) {
    var _a;
    const startInst = after instanceof Date ? Temporal.Instant.from(after.toISOString()) : after.toInstant();
    const endInst = before instanceof Date ? Temporal.Instant.from(before.toISOString()) : before.toInstant();
    const startZdt = Temporal.Instant.from(startInst).toZonedDateTimeISO(this.tzid);
    const beforeZdt = Temporal.Instant.from(endInst).toZonedDateTimeISO(this.tzid);
    const tempOpts = __spreadValues({}, this.opts);
    if (!tempOpts.until || Temporal.ZonedDateTime.compare(beforeZdt, tempOpts.until) < 0) {
      tempOpts.until = beforeZdt;
    }
    if (tempOpts.count === void 0) {
      const interval = (_a = tempOpts.interval) != null ? _a : 1;
      const aligned = startZdt.withPlainTime(this.originalDtstart.toPlainTime());
      let unit;
      switch (tempOpts.freq) {
        case "YEARLY":
          unit = "years";
          break;
        case "MONTHLY":
          unit = "months";
          break;
        case "WEEKLY":
          unit = "weeks";
          break;
        case "DAILY":
          unit = "days";
          break;
        case "HOURLY":
          unit = "hours";
          break;
        case "MINUTELY":
          unit = "minutes";
          break;
        default:
          unit = "seconds";
      }
      const diffDur = this.opts.dtstart.until(aligned, { largestUnit: unit });
      const unitsBetween = diffDur[unit];
      const steps = Math.floor(unitsBetween / interval);
      let toAdd;
      const jump = steps * interval;
      switch (unit) {
        case "years":
          toAdd = { years: jump };
          break;
        case "months":
          toAdd = { months: jump };
          break;
        case "weeks":
          toAdd = { weeks: jump };
          break;
        case "days":
          toAdd = { days: jump };
          break;
        case "hours":
          toAdd = { hours: jump };
          break;
        case "minutes":
          toAdd = { minutes: jump };
          break;
        default:
          toAdd = { seconds: jump };
      }
      let candidate = this.opts.dtstart.add(toAdd);
      if (Temporal.ZonedDateTime.compare(candidate, this.opts.dtstart) < 0) {
        candidate = this.opts.dtstart;
      }
      tempOpts.dtstart = candidate;
    }
    const tempRule = new _RRuleTemporal(tempOpts);
    const allDates = tempRule.all();
    return allDates.filter((date) => {
      const inst = date.toInstant();
      const afterStart = inc ? Temporal.Instant.compare(inst, startInst) >= 0 : Temporal.Instant.compare(inst, startInst) > 0;
      const beforeEnd = inc ? Temporal.Instant.compare(inst, endInst) <= 0 : Temporal.Instant.compare(inst, endInst) < 0;
      return afterStart && beforeEnd;
    });
  }
  /**
   * Convenience helper: true if the exact instant is an occurrence of the rule.
   * This checks full date-time equality (including time and time zone).
   */
  matches(date) {
    return this.between(date, date, true).length > 0;
  }
  /**
   * Convenience helper: true if any occurrence falls on the given calendar day
   * in the rule's time zone. This ignores time-of-day granularity.
   */
  occursOn(date) {
    const startOfDay = date.toZonedDateTime({
      timeZone: this.tzid,
      plainTime: Temporal.PlainTime.from("00:00")
    });
    const endOfDay = startOfDay.add({ days: 1 }).subtract({ nanoseconds: 1 });
    return this.between(startOfDay, endOfDay, true).length > 0;
  }
  /**
   * Returns the next occurrence of the rule after a specified date.
   * @param after - The start date or Temporal.ZonedDateTime object.
   * @param inc - Optional boolean flag to include occurrences on the start date.
   * @returns The next occurrence of the rule after the specified date or null if no occurrences are found.
   */
  next(after = /* @__PURE__ */ new Date(), inc = false) {
    const afterInst = after instanceof Date ? Temporal.Instant.from(after.toISOString()) : after.toInstant();
    let result = null;
    this.all((occ) => {
      const inst = occ.toInstant();
      const ok = inc ? Temporal.Instant.compare(inst, afterInst) >= 0 : Temporal.Instant.compare(inst, afterInst) > 0;
      if (ok) {
        if (!result || Temporal.ZonedDateTime.compare(occ, result) < 0) {
          result = occ;
        }
        return false;
      }
      return true;
    });
    return result;
  }
  /**
   * Returns the previous occurrence of the rule before a specified date.
   * @param before - The end date or Temporal.ZonedDateTime object.
   * @param inc - Optional boolean flag to include occurrences on the end date.
   * @returns The previous occurrence of the rule before the specified date or null if no occurrences are found.
   */
  previous(before = /* @__PURE__ */ new Date(), inc = false) {
    const beforeInst = before instanceof Date ? Temporal.Instant.from(before.toISOString()) : before.toInstant();
    let prev = null;
    this.all((occ) => {
      const inst = occ.toInstant();
      const beyond = inc ? Temporal.Instant.compare(inst, beforeInst) > 0 : Temporal.Instant.compare(inst, beforeInst) >= 0;
      if (beyond) return false;
      prev = occ;
      return true;
    });
    return prev;
  }
  toString() {
    const iso = this.originalDtstart.toString({ smallestUnit: "second" }).replace(/[-:]/g, "");
    const dtLine = `DTSTART;TZID=${this.tzid}:${iso.slice(0, 15)}`;
    const rule = [];
    const {
      freq,
      interval,
      count,
      until,
      byHour,
      byMinute,
      bySecond,
      byDay,
      byMonth,
      byMonthDay,
      bySetPos,
      byWeekNo,
      byYearDay,
      wkst,
      rDate,
      exDate
    } = this.opts;
    if (this.opts.rscale) rule.push(`RSCALE=${this.opts.rscale}`);
    if (this.opts.rscale && this.opts.skip) rule.push(`SKIP=${this.opts.skip}`);
    rule.push(`FREQ=${freq}`);
    if (interval !== 1) rule.push(`INTERVAL=${interval}`);
    if (count !== void 0) rule.push(`COUNT=${count}`);
    if (until) {
      rule.push(`UNTIL=${this.formatIcsDateTime(until)}`);
    }
    if (byHour) rule.push(`BYHOUR=${byHour.join(",")}`);
    if (byMinute) rule.push(`BYMINUTE=${byMinute.join(",")}`);
    if (bySecond) rule.push(`BYSECOND=${bySecond.join(",")}`);
    if (byDay) rule.push(`BYDAY=${byDay.join(",")}`);
    if (byMonth) rule.push(`BYMONTH=${byMonth.join(",")}`);
    if (byMonthDay) rule.push(`BYMONTHDAY=${byMonthDay.join(",")}`);
    if (bySetPos) rule.push(`BYSETPOS=${bySetPos.join(",")}`);
    if (byWeekNo) rule.push(`BYWEEKNO=${byWeekNo.join(",")}`);
    if (byYearDay) rule.push(`BYYEARDAY=${byYearDay.join(",")}`);
    if (wkst) rule.push(`WKST=${wkst}`);
    const lines = [dtLine, `RRULE:${rule.join(";")}`];
    if (rDate) {
      lines.push(`RDATE:${this.joinDates(rDate)}`);
    }
    if (exDate) {
      lines.push(`EXDATE:${this.joinDates(exDate)}`);
    }
    return lines.join("\n");
  }
  formatIcsDateTime(date) {
    return date.toInstant().toString().replace(/[-:]/g, "").slice(0, 15) + "Z";
  }
  joinDates(dates) {
    return dates.map((d) => this.formatIcsDateTime(d));
  }
  /**
   * Given any date in a month, return all the ZonedDateTimes in that month
   * matching your opts.byDay and opts.byMonth (or the single "same day" if no BYDAY).
   */
  generateMonthlyOccurrences(sample) {
    var _a;
    const { byDay, byMonth, byMonthDay } = this.opts;
    if (byMonth && !byMonth.includes(sample.month)) return [];
    const lastDay = sample.with({ day: 1 }).add({ months: 1 }).subtract({ days: 1 }).day;
    let byMonthDayHits = [];
    if (byMonthDay && byMonthDay.length > 0) {
      byMonthDayHits = byMonthDay.map((d) => d > 0 ? d : lastDay + d + 1).filter((d) => d >= 1 && d <= lastDay);
    }
    if (!byDay && byMonthDay && byMonthDay.length > 0) {
      if (byMonthDayHits.length === 0) {
        return [];
      }
      const dates = byMonthDayHits.map((d) => sample.with({ day: d }));
      return dates.flatMap((z) => this.expandByTime(z)).sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
    }
    if (!byDay) {
      return this.expandByTime(sample);
    }
    const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
    const tokens = byDay.map((tok) => {
      const m = tok.match(/^([+-]?\d{1,2})?(MO|TU|WE|TH|FR|SA|SU)$/);
      if (!m) return null;
      return { ord: m[1] ? parseInt(m[1], 10) : 0, wd: dayMap[m[2]] };
    }).filter((x) => x !== null);
    const buckets = {};
    let cursor = sample.with({ day: 1 });
    while (cursor.month === sample.month) {
      const dow = cursor.dayOfWeek;
      (buckets[dow] || (buckets[dow] = [])).push(cursor.day);
      cursor = cursor.add({ days: 1 });
    }
    const byDayHits = [];
    for (const { ord, wd } of tokens) {
      const list = (_a = buckets[wd]) != null ? _a : [];
      if (!list.length) continue;
      if (ord === 0) {
        for (const d of list) byDayHits.push(d);
      } else {
        const idx = ord > 0 ? ord - 1 : list.length + ord;
        const dayN = list[idx];
        if (dayN) byDayHits.push(dayN);
      }
    }
    let finalDays = byDayHits;
    if (byMonthDay && byMonthDay.length > 0) {
      if (byMonthDayHits.length === 0) {
        return [];
      }
      finalDays = finalDays.filter((d) => byMonthDayHits.includes(d));
    }
    const hits = finalDays.map((d) => sample.with({ day: d }));
    return hits.flatMap((z) => this.expandByTime(z)).sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
  }
  /**
   * Given any date in a year, return all ZonedDateTimes in that year matching
   * the BYDAY/BYMONTHDAY/BYMONTH constraints. Months default to DTSTART's month
   * if BYMONTH is not specified.
   */
  generateYearlyOccurrences(sample) {
    const months = this.opts.byMonth ? this.opts.byMonth.filter((v) => typeof v === "number").sort((a, b) => a - b) : this.opts.byMonthDay || this.opts.byDay ? [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] : [this.originalDtstart.month];
    let occs = [];
    const hasOrdinalByDay = this.opts.byDay && this.opts.byDay.some((t) => /^[+-]?\d/.test(t));
    if (hasOrdinalByDay && !this.opts.byMonth) {
      const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
      for (const tok of this.opts.byDay) {
        const m = tok.match(/^([+-]?\d{1,2})(MO|TU|WE|TH|FR|SA|SU)$/);
        if (!m) continue;
        const ord = parseInt(m[1], 10);
        const wd = dayMap[m[2]];
        let dt;
        if (ord > 0) {
          const jan1 = sample.with({ month: 1, day: 1 });
          const delta = (wd - jan1.dayOfWeek + 7) % 7;
          dt = jan1.add({ days: delta + 7 * (ord - 1) });
        } else {
          const dec31 = sample.with({ month: 12, day: 31 });
          const delta = (dec31.dayOfWeek - wd + 7) % 7;
          dt = dec31.subtract({ days: delta + 7 * (-ord - 1) });
        }
        occs.push(...this.expandByTime(dt));
      }
    } else if (!this.opts.byYearDay && !this.opts.byWeekNo) {
      occs = [];
      for (const m of months) {
        const monthSample = sample.with({ month: m, day: 1 });
        const monthOccs = this.generateMonthlyOccurrences(monthSample);
        if (monthOccs.length === 0 && this.opts.rscale && this.opts.byMonthDay && this.opts.byMonthDay.length > 0) {
          const lastDay = monthSample.add({ months: 1 }).subtract({ days: 1 }).day;
          const target = this.opts.byMonthDay[0];
          const absTarget = target > 0 ? target : lastDay + target + 1;
          if (absTarget > lastDay || absTarget <= 0) {
            const skip = this.opts.skip || "OMIT";
            if (skip === "BACKWARD") {
              occs.push(...this.expandByTime(monthSample.with({ day: lastDay })));
            } else if (skip === "FORWARD") {
              const nextMonth = monthSample.add({ months: 1 }).with({ day: 1 });
              occs.push(...this.expandByTime(nextMonth));
            } else {
            }
          }
        } else {
          occs.push(...monthOccs);
        }
      }
    }
    if (this.opts.byYearDay) {
      const last = sample.with({ month: 12, day: 31 }).dayOfYear;
      for (const d of this.opts.byYearDay) {
        const dayNum = d > 0 ? d : last + d + 1;
        if (dayNum <= 0 || dayNum > last) continue;
        const dt = this.opts.freq === "MINUTELY" ? sample.with({ month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 }).add({ days: dayNum - 1 }) : sample.with({ month: 1, day: 1 }).add({ days: dayNum - 1 });
        if (!this.opts.byMonth || this.opts.byMonth.includes(dt.month)) {
          occs.push(...this.expandByTime(dt));
        }
      }
    }
    if (this.opts.byWeekNo) {
      const { lastWeek, firstWeekStart, tokens } = this.isoWeekByDay(sample);
      for (const weekNo of this.opts.byWeekNo) {
        if (weekNo > 0 && weekNo > lastWeek || weekNo < 0 && -weekNo > lastWeek) {
          continue;
        }
        const weekIndex = weekNo > 0 ? weekNo - 1 : lastWeek + weekNo;
        const weekStart = firstWeekStart.add({ weeks: weekIndex });
        occs.push(...this.addByDay(tokens, weekStart));
      }
    }
    occs = occs.sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
    occs = this.applyBySetPos(occs);
    return occs;
  }
  addByDay(tokens, weekStart) {
    const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
    const wkst = dayMap[this.opts.wkst || "MO"];
    const entries = [];
    for (const tok of tokens) {
      if (!tok) continue;
      const targetDow = dayMap[tok];
      const inst = weekStart.add({ days: (targetDow - wkst + 7) % 7 });
      if (!this.opts.byMonth || this.opts.byMonth.includes(inst.month)) {
        entries.push(...this.expandByTime(inst));
      }
    }
    return entries;
  }
  /**
   * Helper to find the next valid value from a sorted array
   */
  findNextValidValue(currentValue, validValues, compare) {
    return validValues.find((v) => compare(v, currentValue) > 0) || null;
  }
  /**
   * Efficiently find the next valid date for MINUTELY and SECONDLY frequency by jumping over
   * large gaps when BYXXX constraints don't match.
   */
  findNextValidDate(current) {
    if (this.opts.byWeekNo && this.opts.byYearDay) {
      const yearStart = current.with({ month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 });
      const yearDays = this.opts.byYearDay.map((yd) => {
        const lastDayOfYear = yearStart.with({ month: 12, day: 31 }).dayOfYear;
        return yd > 0 ? yd : lastDayOfYear + yd + 1;
      });
      for (const yd of yearDays) {
        const date = yearStart.add({ days: yd - 1 });
        if (this.matchesByWeekNo(date)) {
          break;
        }
      }
    }
    if (this.opts.byMonth) {
      const numericMonths = this.opts.byMonth.filter((v) => typeof v === "number");
      if (numericMonths.length && !numericMonths.includes(current.month)) {
        const months = [...numericMonths].sort((a, b) => a - b);
        const nextMonth = this.findNextValidValue(current.month, months, (a, b) => a - b);
        if (nextMonth) {
          current = current.with({ month: nextMonth, day: 1, hour: 0, minute: 0, second: 0 });
        } else {
          current = current.add({ years: 1 }).with({ month: months[0], day: 1, hour: 0, minute: 0, second: 0 });
        }
        current = this.applyTimeOverride(current);
        return current;
      }
    }
    if (this.opts.byWeekNo && !this.matchesByWeekNo(current)) {
      current = current.add({ weeks: 1 }).with({ hour: 0, minute: 0, second: 0 });
      current = this.applyTimeOverride(current);
      return current;
    }
    if (this.opts.byYearDay && !this.matchesByYearDay(current)) {
      const yearDays = [...this.opts.byYearDay].sort((a, b) => a - b);
      const currentYearDay = current.dayOfYear;
      const lastDayOfYear = current.with({ month: 12, day: 31 }).dayOfYear;
      let nextYearDay = yearDays.find((d) => {
        const dayNum = d > 0 ? d : lastDayOfYear + d + 1;
        return dayNum > currentYearDay;
      });
      if (nextYearDay) {
        const dayNum = nextYearDay > 0 ? nextYearDay : lastDayOfYear + nextYearDay + 1;
        if (this.opts.freq === "MINUTELY" || this.opts.freq === "SECONDLY") {
          current = current.with({ month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 }).add({ days: dayNum - 1 });
        } else {
          current = current.with({ month: 1, day: 1 }).add({ days: dayNum - 1 });
        }
      } else {
        const nextYear = current.add({ years: 1 });
        const nextYearLastDay = nextYear.with({ month: 12, day: 31 }).dayOfYear;
        const firstYearDay = yearDays[0];
        if (firstYearDay !== void 0) {
          const dayNum = firstYearDay > 0 ? firstYearDay : nextYearLastDay + firstYearDay + 1;
          if (this.opts.freq === "MINUTELY" || this.opts.freq === "SECONDLY") {
            current = nextYear.with({ month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 }).add({ days: dayNum - 1 });
          } else {
            current = nextYear.with({ month: 1, day: 1 }).add({ days: dayNum - 1 });
          }
        }
      }
      current = this.applyTimeOverride(current);
      return current;
    }
    if (this.opts.byMonthDay && !this.matchesByMonthDay(current)) {
      const monthDays = [...this.opts.byMonthDay].sort((a, b) => a - b);
      const lastDayOfMonth = current.with({ day: 1 }).add({ months: 1 }).subtract({ days: 1 }).day;
      const currentDay = current.day;
      const validDays = monthDays.map((d) => d > 0 ? d : lastDayOfMonth + d + 1).filter((d) => d > 0 && d <= lastDayOfMonth).sort((a, b) => a - b);
      const nextDay = this.findNextValidValue(currentDay, validDays, (a, b) => a - b);
      if (nextDay) {
        current = current.with({ day: nextDay, hour: 0, minute: 0, second: 0 });
      } else {
        const nextMonth = current.add({ months: 1 }).with({ day: 1 });
        const nextMonthLastDay = nextMonth.add({ months: 1 }).subtract({ days: 1 }).day;
        const firstMonthDay = monthDays[0];
        if (firstMonthDay !== void 0) {
          const dayNum = firstMonthDay > 0 ? firstMonthDay : nextMonthLastDay + firstMonthDay + 1;
          current = nextMonth.with({
            day: Math.max(1, Math.min(dayNum, nextMonthLastDay)),
            hour: 0,
            minute: 0,
            second: 0
          });
        } else {
          current = current.add({ months: 1 }).with({ day: 1, hour: 0, minute: 0, second: 0 });
        }
      }
      current = this.applyTimeOverride(current);
      return current;
    }
    if (this.opts.byDay && !this.matchesByDay(current)) {
      const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
      const targetDays = this.opts.byDay.map((tok) => {
        var _a;
        return (_a = tok.match(/(MO|TU|WE|TH|FR|SA|SU)$/)) == null ? void 0 : _a[1];
      }).filter(Boolean).map((day) => dayMap[day]).filter(Boolean);
      const nextDayOfWeek = this.findNextValidValue(current.dayOfWeek, targetDays.sort(), (a, b) => a - b);
      if (nextDayOfWeek) {
        const delta = (nextDayOfWeek - current.dayOfWeek + 7) % 7;
        current = current.add({ days: delta }).with({ hour: 0, minute: 0, second: 0 });
      } else {
        const delta = (targetDays[0] - current.dayOfWeek + 7) % 7;
        current = current.add({ days: delta + 7 }).with({ hour: 0, minute: 0, second: 0 });
      }
      current = this.applyTimeOverride(current);
      return current;
    }
    switch (this.opts.freq) {
      case "SECONDLY":
      case "MINUTELY":
        current = current.add({ days: 1 }).with({ hour: 0, minute: 0, second: 0 });
        break;
      case "HOURLY":
        current = current.add({ days: 1 }).with({ hour: 0, minute: 0, second: 0 });
        break;
      case "DAILY":
      case "WEEKLY":
        current = current.add({ months: 1 }).with({ day: 1, hour: 0, minute: 0, second: 0 });
        break;
      case "MONTHLY":
      case "YEARLY":
        current = current.add({ years: 1 }).with({ month: 1, day: 1, hour: 0, minute: 0, second: 0 });
        break;
    }
    return this.applyTimeOverride(current);
  }
  applyBySetPos(list) {
    const { bySetPos } = this.opts;
    if (!bySetPos || !bySetPos.length) return list;
    const sorted = [...list].sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
    const out = [];
    const len = sorted.length;
    for (const pos of bySetPos) {
      const idx = pos > 0 ? pos - 1 : len + pos;
      if (idx >= 0 && idx < len) out.push(sorted[idx]);
    }
    return out.sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
  }
  isoWeekByDay(sample) {
    var _a;
    const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
    const wkst = dayMap[this.opts.wkst || "MO"];
    const jan1 = sample.with({ month: 1, day: 1 });
    const jan4 = sample.with({ month: 1, day: 4 });
    const delta = (jan4.dayOfWeek - wkst + 7) % 7;
    const firstWeekStart = jan4.subtract({ days: delta });
    const isLeapYear = jan1.inLeapYear;
    const lastWeek = jan1.dayOfWeek === 4 || isLeapYear && jan1.dayOfWeek === 3 ? 53 : 52;
    const tokens = ((_a = this.opts.byDay) == null ? void 0 : _a.length) ? this.opts.byDay.map((tok) => {
      var _a2;
      return (_a2 = tok.match(/(MO|TU|WE|TH|FR|SA|SU)$/)) == null ? void 0 : _a2[1];
    }) : [Object.entries(dayMap).find(([, d]) => d === this.originalDtstart.dayOfWeek)[0]];
    return { lastWeek, firstWeekStart, tokens };
  }
  /**
   * Generate occurrences for a specific week number in a given year
   */
  generateOccurrencesForWeekInYear(year, weekNo) {
    const occs = [];
    const sample = this.originalDtstart.with({ year, month: 1, day: 1 });
    const { lastWeek, firstWeekStart, tokens } = this.isoWeekByDay(sample);
    if (weekNo > 0 && weekNo > lastWeek || weekNo < 0 && -weekNo > lastWeek) {
      return occs;
    }
    const weekIndex = weekNo > 0 ? weekNo - 1 : lastWeek + weekNo;
    const weekStart = firstWeekStart.add({ weeks: weekIndex });
    occs.push(...this.addByDay(tokens, weekStart));
    return occs.sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
  }
  // ===== RSCALE (non-Gregorian) support: Chinese and Hebrew =====
  getRscaleCalendarId() {
    var _a;
    const map = {
      GREGORIAN: "gregory",
      CHINESE: "chinese",
      HEBREW: "hebrew",
      INDIAN: "indian"
    };
    const r = ((_a = this.opts.rscale) == null ? void 0 : _a.toUpperCase()) || "";
    return map[r] || null;
  }
  assertRscaleCalendarSupported(calId) {
    if (calId === "gregory" || calId === "iso8601") return;
    const cached = _RRuleTemporal.rscaleCalendarSupport[calId];
    if (cached === true) return;
    if (cached === false) {
      throw new Error(`RSCALE=${this.opts.rscale} is not supported by the current Temporal/Intl implementation`);
    }
    let supported = true;
    try {
      const probe = Temporal.ZonedDateTime.from("2000-01-01T00:00:00+00:00[UTC]").withCalendar(calId);
      void probe.year;
      void probe.monthCode;
      void probe.day;
    } catch (e) {
      supported = false;
    }
    _RRuleTemporal.rscaleCalendarSupport[calId] = supported;
    if (!supported) {
      throw new Error(`RSCALE=${this.opts.rscale} is not supported by the current Temporal/Intl implementation`);
    }
  }
  pad2(n) {
    return String(n).padStart(2, "0");
  }
  monthMatchesToken(monthCode, token) {
    if (typeof token === "number") {
      return monthCode === `M${this.pad2(token)}`;
    }
    if (/^\d+L$/i.test(token)) {
      const n = parseInt(token, 10);
      return monthCode === `M${this.pad2(n)}L`;
    }
    return false;
  }
  monthsOfYear(calId, year) {
    const out = [];
    for (let m = 1; m <= 20; m++) {
      try {
        const d = Temporal.PlainDate.from({ calendar: calId, year, month: m, day: 1 });
        out.push(d);
      } catch (e) {
        break;
      }
    }
    return out;
  }
  startOfYear(calId, year) {
    return Temporal.PlainDate.from({ calendar: calId, year, month: 1, day: 1 });
  }
  endOfYear(calId, year) {
    return this.startOfYear(calId, year + 1).subtract({ days: 1 });
  }
  rscaleFirstWeekStart(calId, year, wkst) {
    const jan4 = Temporal.PlainDate.from({ calendar: calId, year, month: 1, day: 4 });
    const delta = (jan4.dayOfWeek - wkst + 7) % 7;
    return jan4.subtract({ days: delta });
  }
  rscaleLastWeekCount(calId, year, wkst) {
    const firstWeekStart = this.rscaleFirstWeekStart(calId, year, wkst);
    const lastDay = this.endOfYear(calId, year);
    const diffDays = lastDay.since(firstWeekStart).days;
    return Math.floor(diffDays / 7) + 1;
  }
  lastDayOfMonth(pd) {
    return pd.with({ day: 1 }).add({ months: 1 }).subtract({ days: 1 }).day;
  }
  buildZdtFromPlainDate(pd) {
    const t = this.originalDtstart;
    const pdt = Temporal.PlainDateTime.from({
      calendar: pd.calendarId,
      year: pd.year,
      month: pd.month,
      day: pd.day,
      hour: t.hour,
      minute: t.minute,
      second: t.second
    });
    return pdt.toZonedDateTime(this.tzid);
  }
  rscaleMatchesByYearDay(calId, pd) {
    const list = this.opts.byYearDay;
    if (!list || list.length === 0) return true;
    const last = this.endOfYear(calId, pd.year).dayOfYear;
    return list.some((d) => d > 0 ? pd.dayOfYear === d : pd.dayOfYear === last + d + 1);
  }
  rscaleMatchesByWeekNo(calId, pd) {
    const list = this.opts.byWeekNo;
    if (!list || list.length === 0) return true;
    const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
    const wkst = dayMap[this.opts.wkst || "MO"];
    const weekStart = pd.subtract({ days: (pd.dayOfWeek - wkst + 7) % 7 });
    const thursday = weekStart.add({ days: (4 - wkst + 7) % 7 });
    const weekYear = thursday.year;
    const firstStart = this.rscaleFirstWeekStart(calId, weekYear, wkst);
    const lastWeek = this.rscaleLastWeekCount(calId, weekYear, wkst);
    const idx = Math.floor(pd.since(firstStart).days / 7) + 1;
    return list.some((wn) => wn > 0 ? idx === wn : idx === lastWeek + wn + 1);
  }
  rscaleMatchesByMonth(calId, pd) {
    const tokens = this.opts.byMonth;
    if (!tokens || tokens.length === 0) return true;
    return tokens.some((tok) => this.monthMatchesToken(pd.monthCode, tok));
  }
  rscaleMatchesByMonthDay(pd) {
    const list = this.opts.byMonthDay;
    if (!list || list.length === 0) return true;
    const last = pd.with({ day: 1 }).add({ months: 1 }).subtract({ days: 1 }).day;
    const value = pd.day;
    return list.some((d) => d > 0 ? value === d : value === last + d + 1);
  }
  rscaleMatchesByDayBasic(pd) {
    const byDay = this.opts.byDay;
    if (!byDay || byDay.length === 0) return true;
    const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
    const tokens = byDay.map((tok) => {
      var _a;
      return (_a = tok.match(/^(?:[+-]?\d{1,2})?(MO|TU|WE|TH|FR|SA|SU)$/)) == null ? void 0 : _a[1];
    }).filter((x) => !!x);
    if (tokens.length === 0) return true;
    return tokens.some((wd) => dayMap[wd] === pd.dayOfWeek);
  }
  rscaleDateMatches(calId, pd) {
    return this.rscaleMatchesByMonth(calId, pd) && this.rscaleMatchesByYearDay(calId, pd) && this.rscaleMatchesByWeekNo(calId, pd) && this.rscaleMatchesByMonthDay(pd) && this.rscaleMatchesByDayBasic(pd);
  }
  applySkipForDay(calId, year, monthStart, targetDay) {
    const last = this.lastDayOfMonth(monthStart);
    const skip = this.opts.skip || "OMIT";
    if (targetDay >= 1 && targetDay <= last) {
      return monthStart.with({ day: targetDay });
    }
    if (skip === "BACKWARD") {
      return monthStart.with({ day: last });
    }
    if (skip === "FORWARD") {
      const nextMonthStart = monthStart.add({ months: 1 });
      return nextMonthStart.with({ day: 1 });
    }
    return null;
  }
  generateMonthlyOccurrencesRscale(calId, year, monthStart) {
    const occs = [];
    const byMonthDay = this.opts.byMonthDay;
    const byDay = this.opts.byDay;
    if (!byDay && !byMonthDay) {
      const targetDay = this.originalDtstart.withCalendar(calId).day;
      const pd = this.applySkipForDay(calId, year, monthStart, targetDay);
      if (pd) occs.push(this.buildZdtFromPlainDate(pd));
      return occs;
    }
    const addZ = (pd) => {
      occs.push(this.buildZdtFromPlainDate(pd));
    };
    const last = this.lastDayOfMonth(monthStart);
    const resolveDay = (d) => d > 0 ? d : last + d + 1;
    if (byMonthDay && byMonthDay.length > 0) {
      for (const raw of byMonthDay) {
        const dayNum = resolveDay(raw);
        const pd = this.applySkipForDay(calId, year, monthStart, dayNum);
        if (pd) addZ(pd);
      }
    }
    if (byDay && byDay.length > 0) {
      const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
      const buckets = {};
      let cur = monthStart;
      while (cur.month === monthStart.month && cur.year === monthStart.year) {
        const wd = cur.dayOfWeek;
        (buckets[wd] || (buckets[wd] = [])).push(cur);
        cur = cur.add({ days: 1 });
      }
      for (const tok of byDay) {
        const m = tok.match(/^([+-]?\d{1,2})?(MO|TU|WE|TH|FR|SA|SU)$/);
        if (!m) continue;
        const ord = m[1] ? parseInt(m[1], 10) : 0;
        const wd = dayMap[m[2]];
        const list = buckets[wd] || [];
        if (list.length === 0) continue;
        if (ord === 0) {
          for (const pd of list) addZ(pd);
        } else {
          const idx = ord > 0 ? ord - 1 : list.length + ord;
          const pd = list[idx];
          if (pd) addZ(pd);
        }
      }
    }
    return this.applyBySetPos(occs).sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
  }
  _allRscaleNonGregorian(iterator) {
    var _a, _b, _c, _d, _e, _f, _g;
    const calId = this.getRscaleCalendarId();
    if (!calId) return this._allFallback(iterator);
    this.assertRscaleCalendarSupported(calId);
    const dates = [];
    let iterationCount = 0;
    const start = this.originalDtstart;
    const seed = start.withCalendar(calId);
    const interval = (_a = this.opts.interval) != null ? _a : 1;
    if (!this.addDtstartIfNeeded(dates, iterator)) {
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    if (this.opts.freq === "YEARLY") {
      let yearOffset = 0;
      while (true) {
        if (++iterationCount > this.maxIterations) {
          throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
        }
        const tgtYear = seed.year + yearOffset * interval;
        let occs = [];
        const monthsTokens = this.opts.byMonth;
        const months = this.monthsOfYear(calId, tgtYear);
        const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
        const wkst = dayMap[this.opts.wkst || "MO"];
        if (this.opts.byWeekNo && this.opts.byWeekNo.length > 0) {
          const firstStart = this.rscaleFirstWeekStart(calId, tgtYear, wkst);
          const lastWeek = this.rscaleLastWeekCount(calId, tgtYear, wkst);
          const tokens = ((_b = this.opts.byDay) == null ? void 0 : _b.length) ? this.opts.byDay.map((tok) => {
            var _a2;
            return (_a2 = tok.match(/(MO|TU|WE|TH|FR|SA|SU)$/)) == null ? void 0 : _a2[1];
          }) : [Object.entries(dayMap).find(([, d]) => d === this.originalDtstart.dayOfWeek)[0]];
          for (const wn of this.opts.byWeekNo) {
            let idx = wn > 0 ? wn - 1 : lastWeek + wn;
            if (idx < 0 || idx >= lastWeek) continue;
            const weekStart = firstStart.add({ weeks: idx });
            for (const tok of tokens) {
              const targetDow = dayMap[tok];
              const pd = weekStart.add({ days: (targetDow - wkst + 7) % 7 });
              if (monthsTokens && monthsTokens.length > 0) {
                if (!monthsTokens.some((t) => this.monthMatchesToken(pd.monthCode, t))) continue;
              }
              if (this.opts.byYearDay && this.opts.byYearDay.length > 0) {
                const lastDay = this.endOfYear(calId, tgtYear).dayOfYear;
                const matches = this.opts.byYearDay.some((d) => {
                  const target = d > 0 ? d : lastDay + d + 1;
                  return pd.dayOfYear === target;
                });
                if (!matches) continue;
              }
              occs.push(this.buildZdtFromPlainDate(pd));
            }
          }
        } else if (this.opts.byYearDay && this.opts.byYearDay.length > 0) {
          const startOfYear = this.startOfYear(calId, tgtYear);
          const lastDay = this.endOfYear(calId, tgtYear).dayOfYear;
          for (const d of this.opts.byYearDay) {
            const target = d > 0 ? d : lastDay + d + 1;
            if (target < 1 || target > lastDay) continue;
            let pd = startOfYear.add({ days: target - 1 });
            if (monthsTokens && monthsTokens.length > 0) {
              if (!monthsTokens.some((t) => this.monthMatchesToken(pd.monthCode, t))) continue;
            }
            occs.push(this.buildZdtFromPlainDate(pd));
          }
        } else if (!monthsTokens || monthsTokens.length === 0) {
          try {
            const pd = Temporal.PlainDate.from({
              calendar: calId,
              year: tgtYear,
              monthCode: seed.monthCode,
              day: seed.day
            });
            occs.push(this.buildZdtFromPlainDate(pd));
          } catch (e) {
            const skip = this.opts.skip || "OMIT";
            if (skip === "FORWARD" || skip === "BACKWARD") {
              const mapped = seed.with({ year: tgtYear });
              const adjusted = skip === "BACKWARD" ? mapped.subtract({ days: 1 }) : mapped;
              occs.push(adjusted.withCalendar("iso8601"));
            }
          }
        } else {
          const monthStarts = months.filter((m) => monthsTokens.some((tok) => this.monthMatchesToken(m.monthCode, tok)));
          for (const ms of monthStarts) {
            occs.push(...this.generateMonthlyOccurrencesRscale(calId, tgtYear, ms));
          }
        }
        if (occs.length > 0) {
          const expanded = occs.flatMap((z) => this.expandByTime(z));
          const sorted = expanded.sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
          const { shouldBreak } = this.processOccurrences(sorted, dates, start, iterator);
          if (shouldBreak) break;
        }
        yearOffset++;
        if (this.opts.until && tgtYear > this.opts.until.withCalendar(calId).year) break;
      }
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    if (this.opts.freq === "WEEKLY") {
      const dayMap = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
      const wkst = dayMap[this.opts.wkst || "MO"];
      const tokens = ((_c = this.opts.byDay) == null ? void 0 : _c.length) ? this.opts.byDay.map((tok) => {
        var _a2;
        return (_a2 = tok.match(/(MO|TU|WE|TH|FR|SA|SU)$/)) == null ? void 0 : _a2[1];
      }) : [Object.entries(dayMap).find(([, d]) => d === this.originalDtstart.dayOfWeek)[0]];
      let weekStart = seed.toPlainDate().subtract({ days: (seed.dayOfWeek - wkst + 7) % 7 });
      while (true) {
        if (++iterationCount > this.maxIterations) {
          throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
        }
        const occs = [];
        for (const tok of tokens) {
          const targetDow = dayMap[tok];
          const pd = weekStart.add({ days: (targetDow - wkst + 7) % 7 });
          if (Temporal.ZonedDateTime.compare(this.buildZdtFromPlainDate(pd), this.originalDtstart) < 0) {
            continue;
          }
          if (this.opts.byWeekNo && this.opts.byWeekNo.length > 0) {
            const thursday = weekStart.add({ days: (4 - wkst + 7) % 7 });
            const weekYear = thursday.year;
            const firstStart = this.rscaleFirstWeekStart(calId, weekYear, wkst);
            const lastWeek = this.rscaleLastWeekCount(calId, weekYear, wkst);
            const idx = Math.floor(pd.since(firstStart).days / 7) + 1;
            const match = this.opts.byWeekNo.some((wn) => wn > 0 ? idx === wn : idx === lastWeek + wn + 1);
            if (!match) continue;
          }
          if (this.opts.byYearDay && this.opts.byYearDay.length > 0) {
            const last = this.endOfYear(calId, pd.year).dayOfYear;
            const match = this.opts.byYearDay.some((d) => d > 0 ? pd.dayOfYear === d : pd.dayOfYear === last + d + 1);
            if (!match) continue;
          }
          const monthsTokens = this.opts.byMonth;
          if (monthsTokens && monthsTokens.length > 0) {
            if (!monthsTokens.some((t) => this.monthMatchesToken(pd.monthCode, t))) continue;
          }
          occs.push(this.buildZdtFromPlainDate(pd));
        }
        if (occs.length) {
          const expanded = occs.flatMap((z) => this.expandByTime(z));
          const sorted = expanded.sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
          const { shouldBreak } = this.processOccurrences(sorted, dates, start, iterator);
          if (shouldBreak) return this.applyCountLimitAndMergeRDates(dates, iterator);
        }
        weekStart = weekStart.add({ weeks: (_d = this.opts.interval) != null ? _d : 1 });
        if (this.opts.until) {
          const z = this.buildZdtFromPlainDate(weekStart.add({ days: 6 }));
          if (Temporal.ZonedDateTime.compare(z, this.opts.until) > 0) break;
        }
      }
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    if (this.opts.freq === "MONTHLY") {
      let cursor = seed.toPlainDate().with({ day: 1 });
      while (true) {
        if (++iterationCount > this.maxIterations) {
          throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
        }
        const year = cursor.year;
        const monthStart = cursor;
        let proceed = true;
        const monthsTokens = this.opts.byMonth;
        if (monthsTokens && monthsTokens.length > 0) {
          proceed = monthsTokens.some((tok) => this.monthMatchesToken(monthStart.monthCode, tok));
        }
        if (proceed) {
          const occs = this.generateMonthlyOccurrencesRscale(calId, year, monthStart);
          const expanded = occs.flatMap((z) => this.expandByTime(z));
          const sorted = expanded.sort((a, b) => Temporal.ZonedDateTime.compare(a, b));
          const { shouldBreak } = this.processOccurrences(sorted, dates, start, iterator);
          if (shouldBreak) break;
        }
        cursor = cursor.add({ months: (_e = this.opts.interval) != null ? _e : 1 });
        if (this.opts.until) {
          const z = this.buildZdtFromPlainDate(cursor);
          if (Temporal.ZonedDateTime.compare(z, this.opts.until) > 0) break;
        }
      }
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    if (this.opts.freq === "DAILY") {
      let pd = seed.toPlainDate();
      while (true) {
        if (++iterationCount > this.maxIterations) {
          throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
        }
        if (this.rscaleDateMatches(calId, pd)) {
          const base = this.buildZdtFromPlainDate(pd);
          let occs = this.expandByTime(base);
          occs = this.applyBySetPos(occs);
          const { shouldBreak } = this.processOccurrences(occs, dates, start, iterator);
          if (shouldBreak) break;
        }
        pd = pd.add({ days: (_f = this.opts.interval) != null ? _f : 1 });
        if (this.opts.until) {
          const z = this.buildZdtFromPlainDate(pd);
          if (Temporal.ZonedDateTime.compare(z, this.opts.until) > 0) break;
        }
      }
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    if (this.opts.freq === "HOURLY" || this.opts.freq === "MINUTELY") {
      const unit = this.opts.freq === "HOURLY" ? "hour" : "minute";
      const unitMs = this.opts.freq === "HOURLY" ? 36e5 : 6e4;
      const interval2 = (_g = this.opts.interval) != null ? _g : 1;
      let pd = seed.toPlainDate();
      const startInstantMs = this.originalDtstart.toInstant().epochMilliseconds;
      while (true) {
        if (++iterationCount > this.maxIterations) {
          throw new Error(`Maximum iterations (${this.maxIterations}) exceeded in all()`);
        }
        if (this.rscaleDateMatches(calId, pd)) {
          const base = this.buildZdtFromPlainDate(pd);
          let occs = this.expandByTime(base);
          occs = occs.filter((occ) => {
            const delta = occ.toInstant().epochMilliseconds - startInstantMs;
            const steps = Math.floor(delta / unitMs);
            return steps % interval2 === 0;
          });
          const { shouldBreak } = this.processOccurrences(occs, dates, start, iterator);
          if (shouldBreak) break;
        }
        pd = pd.add({ days: 1 });
        if (this.opts.until) {
          const z = this.buildZdtFromPlainDate(pd);
          if (Temporal.ZonedDateTime.compare(z, this.opts.until) > 0) break;
        }
      }
      return this.applyCountLimitAndMergeRDates(dates, iterator);
    }
    return this._allFallback(iterator);
  }
};
_RRuleTemporal.rscaleCalendarSupport = {};
var RRuleTemporal = _RRuleTemporal;

export {
  RRuleTemporal
};