// Google Calendar Synchronization, build on 2026-08-30 // Source: https://github.com/scriptPilot/google-calendar-synchronization function start() { const lock = LockService.getScriptLock(); if (!lock.tryLock(1)) { Logger.log("start() is already running - skipping this invocation"); return; } // Check onStart function if (typeof onStart !== "function") { throw new Error( "onStart() function is missing - please check the documentation", ); } // Set the script invocation check to true onStart.calledByStartFunction = true; // Set default values setSyncInterval(); setMaxExecutionTime(); setSingleEvents(); // Create or update the fallback trigger based on the max execution time (fallback if script is exeeding Google Script limits) createTrigger("startFallback", onStart.maxExecutionTime); // Remove any stop note from previous stop() call PropertiesService.getUserProperties().deleteProperty("stopNote"); // Wrap the sync to catch any error and ensure the next trigger creation try { // Run the onStart function onStart(); } catch (err) { Logger.log("An error occured during the synchronization"); Logger.log(`Message: ${err.message}`); } // Check stop note (if stop() was called during the script run) if (PropertiesService.getUserProperties().getProperty("stopNote") !== null) { Logger.log(`Synchronization stopped.`); return; } // Create a trigger based on the sync interval createTrigger("start", onStart.syncInterval); // Update the fallback trigger // sync interval + 1 minute to allow fallback trigger update on the next regular script run createTrigger("startFallback", onStart.syncInterval + 1); } function stop() { // Remove all existing triggers deleteTrigger("start"); deleteTrigger("startFallback"); // Set a stop note (to stop any running script to create a new trigger) PropertiesService.getUserProperties().setProperty("stopNote", true); // Log script stop Logger.log(`The synchronization will not run again`); Logger.log(`If the script is currently running, it will complete`); Logger.log(`You might want to delete all synchronized events with clean()`); } function clean() { // Log start Logger.log(`Cleanup started`); // Get saved sync pairs const syncPairs = PropertiesService.getUserProperties() .getProperty("syncPairs") ?.split(";") || []; // Loop sync pairs let totalExistingTargetEvents = 0; syncPairs.forEach((syncPair) => { // Extract calendar ids [sourceCalendarId, targetCalendarId] = syncPair.split(":"); // Get relevant target events const existingTargetEvents = getEvents({ calendarId: targetCalendarId, sourceCalendarId: sourceCalendarId, }); // Delete relevant target events deleteEvents(targetCalendarId, existingTargetEvents); // Sum-up target event count totalExistingTargetEvents = totalExistingTargetEvents + existingTargetEvents.length; }); // Reset sync pairs property // - not all properties are deleted to keep script stop notice PropertiesService.getUserProperties().deleteProperty("syncPairs"); // Log completion Logger.log( `${totalExistingTargetEvents} obsolete target event${totalExistingTargetEvents !== 1 ? "s" : ""} deleted`, ); Logger.log("Cleanup completed"); Logger.log("You can now remove the Google Apps Script project"); } function sync( sourceCalendarName, targetCalendarName, pastDays = 7, nextDays = 28, correction = (targetEvent) => targetEvent, ) { // Check script invocation if (!onStart.calledByStartFunction) { throw new Error( "Please select the Code.gs file and run the start() script.", ); } // Check options if (!sourceCalendarName) throw new Error("sourceCalendarName is missing"); if (!targetCalendarName) throw new Error("targetCalendarName is missing"); // Log start Logger.log( `Synchronization started from "${sourceCalendarName}" to "${targetCalendarName}"`, ); // Get calendar details const sourceCalendar = getCalendar({ calendarName: sourceCalendarName }); const targetCalendar = getCalendar({ calendarName: targetCalendarName }); // Remember sync pair for later cleanup const syncPair = `${sourceCalendar.id}:${targetCalendar.id}`; const syncPairs = PropertiesService.getUserProperties() .getProperty("syncPairs") ?.split(";") || []; if (!syncPairs.includes(syncPair)) syncPairs.push(syncPair); PropertiesService.getUserProperties().setProperty( "syncPairs", syncPairs.join(";"), ); // Calculate timeframe const { dateMin, dateMax } = createTimeframe(pastDays, nextDays); // Get source events let sourceEvents = getEvents({ calendarId: sourceCalendar.id, dateMin, dateMax, }); sourceEvents = correctExdates(sourceEvents, sourceCalendar.timeZone); sourceEvents = cutEventsSeries( sourceEvents, dateMin, dateMax, sourceCalendar.timeZone, ); sourceEvents = cutSingleEvents(sourceEvents, dateMin, dateMax); Logger.log( `${sourceEvents.length} source event${sourceEvents.length !== 1 ? "s" : ""} found between ${createLocalDateStr(dateMin)} and ${createLocalDateStr(dateMax)}`, ); // Get existing target events let existingTargetEvents = getEvents({ calendarId: targetCalendar.id, sourceCalendarId: sourceCalendar.id, }); existingTargetEvents = correctExdates( existingTargetEvents, targetCalendar.timeZone, ); // Create target events const targetEvents = sourceEvents .map((sourceEvent) => { let targetEvent = createTargetEvent({ sourceEvent, sourceCalendar }); targetEvent = correction(targetEvent, sourceEvent); targetEvent = correctUndefinedProps(targetEvent); return targetEvent; }) .filter((e) => e.status !== "cancelled"); // Calculate obsolete existing target events const obsoleteExistingTargetEvents = []; existingTargetEvents.forEach((existingTargetEvent) => { const targetEventFound = targetEvents.filter((e) => isEventEqual(e, existingTargetEvent), ).length; const duplicatedExistingTargetEventFound = existingTargetEvents.filter( (e) => isEventEqual(e, existingTargetEvent) && e.id < existingTargetEvent.id, ).length; if (!targetEventFound || duplicatedExistingTargetEventFound) obsoleteExistingTargetEvents.push(existingTargetEvent); }); // Calculate missing target events const missingTargetEvents = targetEvents.filter((targetEvent) => { return !existingTargetEvents.filter((e) => isEventEqual(e, targetEvent)) .length; }); // Remove obsolete existing target events deleteEvents(targetCalendar.id, obsoleteExistingTargetEvents); // Create missing target events missingTargetEvents.forEach((targetEvent) => { retryOnRateLimit(() => Calendar.Events.insert(targetEvent, targetCalendar.id), ); Logger.log( `Created event "${targetEvent.summary || "(no title)"}" at ${createLocalDateStr(targetEvent.start)}`, ); // Pause between the requests to avoid exceeding the Google Calendar API quota Utilities.sleep(250); }); // Log completion Logger.log( `${obsoleteExistingTargetEvents.length} obsolete target event${obsoleteExistingTargetEvents.length !== 1 ? "s" : ""} deleted`, ); Logger.log( `${missingTargetEvents.length} missing target event${missingTargetEvents.length !== 1 ? "s" : ""} created`, ); Logger.log("Synchronization completed"); } function pastDays(dateTime) { const duration = DateTimeInterval.fromDateTimes(dateTime, DateTime.now()); return Math.floor(duration.length("days")); } function nextDays(dateTime) { const duration = DateTimeInterval.fromDateTimes(DateTime.now(), dateTime); return Math.floor(duration.length("days")); } function startOfWeek(offset = 0) { return pastDays(DateTime.now().startOf("week").minus({ weeks: offset })); } function endOfWeek(offset = 0) { return nextDays(DateTime.now().endOf("week").plus({ weeks: offset })); } function startOfMonth(offset = 0) { return pastDays(DateTime.now().startOf("month").minus({ months: offset })); } function endOfMonth(offset = 0) { return nextDays( DateTime.now().startOf("month").plus({ months: offset }).endOf("month"), ); } function startOfQuarter(offset = 0) { const now = DateTime.now(); const monthsToStartOfQuarter = (now.month - 1) % 3; return pastDays( now .startOf("month") .minus({ months: monthsToStartOfQuarter }) .minus({ months: offset * 3 }), ); } function endOfQuarter(offset = 0) { const now = DateTime.now(); const monthsToEndOfQuarter = Math.ceil(now.month / 3) * 3 - now.month; return nextDays( now .startOf("month") .plus({ months: monthsToEndOfQuarter }) .plus({ months: offset * 3 }) .endOf("month"), ); } function startOfHalfyear(offset = 0) { const now = DateTime.now(); const monthsToStartOfHalfyear = (now.month - 1) % 6; return pastDays( now .startOf("month") .minus({ months: monthsToStartOfHalfyear }) .minus({ months: offset * 6 }), ); } function endOfHalfyear(offset = 0) { const now = DateTime.now(); const monthsToEndOfHalfyear = Math.ceil(now.month / 6) * 6 - now.month; return nextDays( now .startOf("month") .plus({ months: monthsToEndOfHalfyear }) .plus({ months: offset * 6 }) .endOf("month"), ); } function startOfYear(offset = 0) { return pastDays(DateTime.now().startOf("year").minus({ years: offset })); } function endOfYear(offset = 0) { return nextDays( DateTime.now().startOf("year").plus({ years: offset }).endOf("year"), ); } function isSynchronizedEvent(event) { return event.extendedProperties?.private?.sourceCalendarId !== undefined; } function isRecurringEvent(event) { return event.recurrence || event.recurringEventId; } function isOOOEvent(event) { return event.eventType === "outOfOffice"; } function isAlldayEvent(event) { const start = new Date(event.start.dateTime || event.start.date); const end = new Date(event.end.dateTime || event.end.date); return (end - start) % (24 * 60 * 60 * 1000) === 0; } function isOnWeekend(event) { const startDate = new Date(event.start.dateTime || event.start.date); return startDate.getDay() === 6 || startDate.getDay() === 0; } function isBusyEvent(event) { return event.transparency !== "transparent" && !isOOOEvent(event); } function isOpenByMe(event) { return ( event.attendees?.filter( (attendee) => attendee.email === Session.getEffectiveUser().getEmail(), )[0]?.responseStatus === "needsAction" ); } function isAcceptedByMe(event) { return ( event.attendees?.filter( (attendee) => attendee.email === Session.getEffectiveUser().getEmail(), )[0]?.responseStatus === "accepted" ); } function isTentativeByMe(event) { return ( event.attendees?.filter( (attendee) => attendee.email === Session.getEffectiveUser().getEmail(), )[0]?.responseStatus === "tentative" ); } function isDeclinedByMe(event) { return ( event.attendees?.filter( (attendee) => attendee.email === Session.getEffectiveUser().getEmail(), )[0]?.responseStatus === "declined" ); } function setMaxExecutionTime(minutes = 6) { // Check script invocation if (!onStart.calledByStartFunction) { throw new Error( "Please select the Code.gs file and run the start() script.", ); } // Set the new max execution time onStart.maxExecutionTime = minutes; } function setSingleEvents(singleEvents = false) { // Check script invocation if (!onStart.calledByStartFunction) { throw new Error( "Please select the Code.gs file and run the start() script.", ); } // Set the new single events option onStart.singleEvents = singleEvents; } function setSyncInterval(minutes = 1) { // Check script invocation if (!onStart.calledByStartFunction) { throw new Error( "Please select the Code.gs file and run the start() script.", ); } // Set the new sync interval onStart.syncInterval = minutes; } // Correction for retrieved Google Calendar events // - add cancelled instances as exdate to the main event // - remove cancelled instances from the events array function correctExdates(events, calendarTimeZone) { // Add missing exdates events = events.map((event) => { // Return any non-event-series unchanged if (!event.recurrence) return event; // Create array with exdates; keep existing ones const existingExdates = event.recurrence.filter( (r) => r.substr(0, 6) === "EXDATE", )[0]; const exdates = existingExdates ? existingExdates.split(":")[1].split(",") : []; // Filter events for instances of this event series const instances = events.filter((e) => e.recurringEventId === event.id); // Add instances to the exdates array instances.forEach((instance) => { const instanceExdate = DateTime.fromISO( instance.originalStartTime.dateTime || instance.originalStartTime.date, { zone: instance.originalStartTime.timeZone || calendarTimeZone }, ); exdates.push( instance.originalStartTime.dateTime ? instanceExdate.toFormat("yMMdd'T'HHmmss") : instanceExdate.toFormat("yMMdd"), ); }); // Add exdates to the event if (exdates.length) { event.recurrence = event.recurrence.filter( (r) => r.substr(0, 6) !== "EXDATE", ); event.recurrence.push(`EXDATE:${exdates.sort().join(",")}`); } // Return the event return event; }); // Remove cancelled instances (listed in exdates) events = events.filter( (e) => !(e.recurringEventId && e.status === "cancelled"), ); // Return corrected events return events; } function correctUndefinedProps(event) { // Remove undefined props Object.keys(event).forEach((key) => { if (event[key] === undefined) delete event[key]; }); // Return event return event; } function createBareEvent(event) { const keep = [ "attachments", "attendees", "colorId", "description", "end", "extendedProperties", "location", "recurrence", "start", "summary", "transparency", ]; const bareEvent = {}; keep.forEach((k) => { if (event[k] !== undefined) bareEvent[k] = event[k]; }); return bareEvent; } function createLocalDateStr(dateTime) { // Create the date object let date; if (dateTime instanceof Date) date = new Date(dateTime.getTime()); else if (typeof dateTime === "string") date = new Date(dateTime); else date = new Date(dateTime.dateTime || dateTime.date); // Format the date and time components const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, "0"); const day = String(date.getDate()).padStart(2, "0"); const hours = String(date.getHours()).padStart(2, "0"); const minutes = String(date.getMinutes()).padStart(2, "0"); const seconds = String(date.getSeconds()).padStart(2, "0"); // Combine the components into the desired format const formattedDateStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; // Return formatted date string return formattedDateStr; } function createSortedEvent(obj) { if (Array.isArray(obj)) return obj.sort(); if (typeof obj === "object" && obj !== null) { const sortedObj = {}; const sortedKeys = Object.keys(obj).sort(); sortedKeys.forEach((key) => { // Harmonize dateTime string if (key === "dateTime") { sortedObj[key] = new Date(obj[key]).toISOString(); // Sort recurrence elements properly } else if (key === "recurrence") { sortedObj[key] = obj[key].map((el) => { let [elKey, elValue] = el.split(":"); elValue = elValue.split(";").sort().join(";"); return [elKey, elValue].join(":"); }); // Any other property } else { sortedObj[key] = createSortedEvent(obj[key]); } }); return sortedObj; } return obj; } function createTargetEvent({ sourceEvent, sourceCalendar }) { // Create target event const targetEvent = {}; // Keep only time-based properties to avoid any unwanted data exposure const defaultProps = ["start", "end", "recurrence"]; defaultProps.forEach((prop) => { if (sourceEvent[prop] !== undefined) targetEvent[prop] = sourceEvent[prop]; }); // Use default summary const defaultSummary = "Busy"; if (!defaultProps.includes("summary")) targetEvent.summary = defaultSummary; // Add source calendar id and source event id targetEvent.extendedProperties = { private: { sourceCalendarId: sourceCalendar.id, sourceEventId: sourceEvent.id, }, }; // Return target event return targetEvent; } function createTimeframe(pastDays, nextDays) { // Calculate timeframe const today = new Date(); const todayMorning = new Date( today.getFullYear(), today.getMonth(), today.getDate(), ); const dateMin = new Date( todayMorning.getTime() - pastDays * 24 * 60 * 60 * 1000, ); const dateMax = new Date( todayMorning.getTime() + (nextDays + 1) * 24 * 60 * 60 * 1000, ); return { dateMin, dateMax }; } function createTrigger(functionName, minutes) { if (functionName === "startFallback") { // Ceil to next valid interval (1, 5, 10, 15 or 30) minutes = minutes >= 30 ? minutes : minutes > 15 ? 30 : minutes > 10 ? 15 : minutes > 5 ? 10 : 5; let newTrigger = null; if (minutes <= 30) { newTrigger = ScriptApp.newTrigger(functionName) .timeBased() .everyMinutes(minutes) .create(); } else { newTrigger = ScriptApp.newTrigger(functionName) .timeBased() .everyHours(1) .create(); } deleteTrigger(functionName, newTrigger.getUniqueId()); } else { deleteTrigger(functionName); ScriptApp.newTrigger(functionName) .timeBased() .after(minutes * 60 * 1000) .create(); } Logger.log( `Trigger created for the ${functionName}() function ${functionName === "startFallback" ? "every" : "in"} ${minutes} minute${minutes !== 1 ? "s" : ""}`, ); } // Cut event series according to the specified timerange function cutEventsSeries(events, dateMin, dateMax, calendarTimeZone) { return events .map((event) => { if (event.recurrence) { // Create rule object (including DTSTART, RRULE and EXDATE) const eventStartTimeZone = event.start.timeZone || calendarTimeZone; const eventStart = DateTime.fromISO( event.start.dateTime || event.start.date, { zone: eventStartTimeZone }, ); const rrule = RRuleStr( `DTSTART:${eventStart.toFormat("yMMdd'T'HHmmss")}\n${event.recurrence.join("\n")}`, ); // Get instances const correctedDateMin = DateTime.fromJSDate(dateMin).toJSDate(); const correctedDateMax = DateTime.fromJSDate(dateMax) .minus({ seconds: 1 }) .toJSDate(); const instances = rrule .between(correctedDateMin, correctedDateMax, true) .map((i) => DateTime.fromJSDate(i) .toUTC() .setZone(eventStartTimeZone, { keepLocalTime: true }) .toJSDate(), ); // No valid instances const exdates = typeof rrule.exdates === "function" ? rrule.exdates().map((exdate) => exdate.toISOString()) : []; const instancesWithoutExdates = instances.filter( (instance) => !exdates.includes(instance.toISOString()), ); if (!instancesWithoutExdates.length) return { ...event, status: "cancelled" }; // Update start date const newEventStart = DateTime.fromJSDate(instances[0]); event.start = { ...event.start, ...(event.start.dateTime ? { dateTime: newEventStart.toISO() } : { date: newEventStart.toISODate() }), }; // Update end date const eventEndTimeZone = event.end.timeZone || calendarTimeZone; const eventEnd = DateTime.fromISO( event.end.dateTime || event.end.date, { zone: eventEndTimeZone }, ); const eventDuration = eventEnd - eventStart; const newEventEnd = newEventStart.plus({ seconds: eventDuration / 1000, }); event.end = { ...event.end, ...(event.end.dateTime ? { dateTime: newEventEnd.toISO() } : { date: newEventEnd.toISODate() }), }; // Remove COUNT, update UNTIL const lastInstanceEndOfDay = DateTime.fromJSDate( instances.slice(-1)[0], ).endOf("day"); const timeframeEndDate = DateTime.fromJSDate(dateMax); const newUntilDate = DateTime.min( lastInstanceEndOfDay, timeframeEndDate, ); event.recurrence = event.recurrence.map((arrEl) => { if (arrEl.substr(0, 6) === "RRULE:") { let [rulePrefix, ruleStr] = arrEl.split(":"); let ruleStrParts = ruleStr.split(";"); ruleStrParts = ruleStrParts.filter( (rsp) => rsp.substr(0, 6) !== "COUNT=", ); ruleStrParts = ruleStrParts.filter( (rsp) => rsp.substr(0, 6) !== "UNTIL=", ); ruleStrParts.push( `UNTIL=${newUntilDate.toUTC().toFormat("yMMdd'T'HHmmss'Z'")}`, ); ruleStr = ruleStrParts.join(";"); return [rulePrefix, ruleStr].join(":"); } else { return arrEl; } }); } return event; }) .filter((e) => e.status !== "cancelled"); } // Cut single events according to the specified timeframe function cutSingleEvents(events, dateMin, dateMax) { const dateTimeMin = DateTime.fromJSDate(dateMin); const dateTimeMax = DateTime.fromJSDate(dateMax); return events .map((event) => { if (!event.recurrence) { let dateTimeStart = DateTime.fromISO( event.start.dateTime || event.start.date, ); let dateTimeEnd = DateTime.fromISO( event.end.dateTime || event.end.date, ); if (dateTimeStart < dateTimeMin) dateTimeStart = dateTimeMin; if (dateTimeEnd > dateTimeMax) dateTimeEnd = dateTimeMax; if (dateTimeEnd <= dateTimeStart) return { ...event, status: "cancelled" }; return { ...event, start: { ...event.start, ...(event.start.dateTime ? { dateTime: dateTimeStart.toISO() } : { date: dateTimeStart.toISODate() }), }, end: { ...event.end, ...(event.end.dateTime ? { dateTime: dateTimeEnd.toISO() } : { date: dateTimeEnd.toISODate() }), }, }; } return event; }) .filter((e) => e.status !== "cancelled"); } function deleteEvents(calendarId, events) { events.forEach((event) => { retryOnRateLimit(() => Calendar.Events.remove(calendarId, event.id)); Logger.log( `Deleted event "${event.summary || "(no title)"}" at ${createLocalDateStr(event.start)}`, ); // Pause between the requests to avoid exceeding the Google Calendar API quota Utilities.sleep(250); }); } function deleteTrigger(functionName, exclude = null) { let triggers = ScriptApp.getProjectTriggers(); for (let trigger of triggers) { if ( trigger.getHandlerFunction() === functionName && trigger.getUniqueId() !== exclude ) { ScriptApp.deleteTrigger(trigger); Logger.log(`Existing trigger deleted for the ${functionName}() function`); } } } // Returns calendar resource // https://developers.google.com/calendar/api/v3/reference/calendarList#resource function getCalendar({ calendarName }) { // Check input if (typeof calendarName !== "string") throw new Error("calendarName should be a string"); // Retrieve and filter calendar list const calendarList = retryOnRateLimit(() => Calendar.CalendarList.list({ showHidden: true }), ).items; const filteredList = calendarList.filter((c) => c.summary === calendarName); // Throw error if no calendar is found if (filteredList.length < 1) throw new Error(`Calendar "${calendarName}" not found`); // Throw error if multiple calendar are found if (filteredList.length > 1) throw new Error(`Multiple calendar found for name "${calendarName}"`); // Return calendar resource const calendar = filteredList[0]; return calendar; } // Returns array with events resources // https://developers.google.com/calendar/api/v3/reference/events#resource function getEvents({ calendarId, dateMin, dateMax, sourceCalendarId }) { // Check the input if (!calendarId) throw new Error("calendarId is missing"); // Define options const options = { maxResults: 2500, ...(dateMin ? { timeMin: dateMin.toISOString() } : {}), ...(dateMax ? { timeMax: dateMax.toISOString() } : {}), ...(onStart.singleEvents && dateMin && dateMax ? { singleEvents: true } : {}), ...(sourceCalendarId ? { privateExtendedProperty: `sourceCalendarId=${sourceCalendarId}` } : {}), }; // Retrieve all events with pagination let events = []; let pageToken = null; while (pageToken !== undefined) { const { nextPageToken, items } = retryOnRateLimit(() => Calendar.Events.list( calendarId, pageToken ? { ...options, pageToken } : { ...options }, ), ); events = [...events, ...items]; pageToken = nextPageToken; } // Return the events array return events; } function isEventEqual(firstEvent, secondEvent) { firstEvent = JSON.stringify(createSortedEvent(createBareEvent(firstEvent))); secondEvent = JSON.stringify(createSortedEvent(createBareEvent(secondEvent))); return firstEvent === secondEvent; } // Retry an API call with exponential backoff in case of rate limit errors // https://developers.google.com/calendar/api/guides/handle-errors function retryOnRateLimit(action) { const maxAttempts = 5; for (let attempt = 1; ; attempt++) { try { return action(); } catch (err) { const isRateLimitError = /rate limit|rateLimitExceeded|quota|backend error/i.test( err.message || "", ); if (!isRateLimitError || attempt >= maxAttempts) throw err; Utilities.sleep(2 ** (attempt - 1) * 1000); } } } // Dedicated function to be called by a fallback trigger // Workaround for script timeout function startFallback() { // Run the start function start(); } // https://moment.github.io/luxon/ eval(` var luxon=function(e){"use strict";function L(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[n++]}};throw new TypeError("Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var t=function(e){function t(){return e.apply(this,arguments)||this}return o(t,e),t}(q(Error)),P=function(t){function e(e){return t.call(this,"Invalid DateTime: "+e.toMessage())||this}return o(e,t),e}(t),Y=function(t){function e(e){return t.call(this,"Invalid Interval: "+e.toMessage())||this}return o(e,t),e}(t),H=function(t){function e(e){return t.call(this,"Invalid Duration: "+e.toMessage())||this}return o(e,t),e}(t),w=function(e){function t(){return e.apply(this,arguments)||this}return o(t,e),t}(t),J=function(t){function e(e){return t.call(this,"Invalid unit "+e)||this}return o(e,t),e}(t),u=function(e){function t(){return e.apply(this,arguments)||this}return o(t,e),t}(t),n=function(e){function t(){return e.call(this,"Zone is an abstract class")||this}return o(t,e),t}(t),t="numeric",r="short",a="long",G={year:t,month:t,day:t},$={year:t,month:r,day:t},B={year:t,month:r,day:t,weekday:r},Q={year:t,month:a,day:t},K={year:t,month:a,day:t,weekday:a},X={hour:t,minute:t},ee={hour:t,minute:t,second:t},te={hour:t,minute:t,second:t,timeZoneName:r},ne={hour:t,minute:t,second:t,timeZoneName:a},re={hour:t,minute:t,hourCycle:"h23"},ie={hour:t,minute:t,second:t,hourCycle:"h23"},oe={hour:t,minute:t,second:t,hourCycle:"h23",timeZoneName:r},ae={hour:t,minute:t,second:t,hourCycle:"h23",timeZoneName:a},se={year:t,month:t,day:t,hour:t,minute:t},ue={year:t,month:t,day:t,hour:t,minute:t,second:t},le={year:t,month:r,day:t,hour:t,minute:t},ce={year:t,month:r,day:t,hour:t,minute:t,second:t},fe={year:t,month:r,day:t,weekday:r,hour:t,minute:t},de={year:t,month:a,day:t,hour:t,minute:t,timeZoneName:r},he={year:t,month:a,day:t,hour:t,minute:t,second:t,timeZoneName:r},me={year:t,month:a,day:t,weekday:a,hour:t,minute:t,timeZoneName:a},ye={year:t,month:a,day:t,weekday:a,hour:t,minute:t,second:t,timeZoneName:a},s=function(){function e(){}var t=e.prototype;return t.offsetName=function(e,t){throw new n},t.formatOffset=function(e,t){throw new n},t.offset=function(e){throw new n},t.equals=function(e){throw new n},i(e,[{key:"type",get:function(){throw new n}},{key:"name",get:function(){throw new n}},{key:"ianaName",get:function(){return this.name}},{key:"isUniversal",get:function(){throw new n}},{key:"isValid",get:function(){throw new n}}]),e}(),ve=null,ge=function(e){function t(){return e.apply(this,arguments)||this}o(t,e);var n=t.prototype;return n.offsetName=function(e,t){return bt(e,t.format,t.locale)},n.formatOffset=function(e,t){return Nt(this.offset(e),t)},n.offset=function(e){return-new Date(e).getTimezoneOffset()},n.equals=function(e){return"system"===e.type},i(t,[{key:"type",get:function(){return"system"}},{key:"name",get:function(){return(new Intl.DateTimeFormat).resolvedOptions().timeZone}},{key:"isUniversal",get:function(){return!1}},{key:"isValid",get:function(){return!0}}],[{key:"instance",get:function(){return ve=null===ve?new t:ve}}]),t}(s),pe={};var ke={year:0,month:1,day:2,era:3,hour:4,minute:5,second:6};var we={},c=function(n){function r(e){var t=n.call(this)||this;return t.zoneName=e,t.valid=r.isValidZone(e),t}o(r,n),r.create=function(e){return we[e]||(we[e]=new r(e)),we[e]},r.resetCache=function(){we={},pe={}},r.isValidSpecifier=function(e){return this.isValidZone(e)},r.isValidZone=function(e){if(!e)return!1;try{return new Intl.DateTimeFormat("en-US",{timeZone:e}).format(),!0}catch(e){return!1}};var e=r.prototype;return e.offsetName=function(e,t){return bt(e,t.format,t.locale,this.name)},e.formatOffset=function(e,t){return Nt(this.offset(e),t)},e.offset=function(e){var t,n,r,i,o,a,s,u,e=new Date(e);return isNaN(e)?NaN:(i=this.name,pe[i]||(pe[i]=new Intl.DateTimeFormat("en-US",{hour12:!1,timeZone:i,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",era:"short"})),a=(i=(i=pe[i]).formatToParts?function(e,t){for(var n=e.formatToParts(t),r=[],i=0;ikt(i,t,n)?(r=i+1,a=1):r=i,l({weekYear:r,weekNumber:a,weekday:o},Dt(e))}function tt(e,t,n){void 0===n&&(n=1);var r,i=e.weekYear,o=e.weekNumber,a=e.weekday,n=Xe(Be(i,1,t=void 0===t?4:t),n),s=yt(i),o=7*o+a-n-7+t,a=(o<1?o+=yt(r=i-1):sO.twoDigitCutoffYear?1900+e:2e3+e}function bt(e,t,n,r){void 0===r&&(r=null);var e=new Date(e),i={hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"},r=(r&&(i.timeZone=r),l({timeZoneName:t},i)),t=new Intl.DateTimeFormat(n,r).formatToParts(e).find(function(e){return"timezonename"===e.type.toLowerCase()});return t?t.value:null}function St(e,t){e=parseInt(e,10),Number.isNaN(e)&&(e=0),t=parseInt(t,10)||0;return 60*e+(e<0||Object.is(e,-0)?-t:t)}function Ot(e){var t=Number(e);if("boolean"==typeof e||""===e||Number.isNaN(t))throw new u("Invalid unit value "+e);return t}function Tt(e,t){var n,r,i={};for(n in e)g(e,n)&&null!=(r=e[n])&&(i[t(n)]=Ot(r));return i}function Nt(e,t){var n=Math.trunc(Math.abs(e/60)),r=Math.trunc(Math.abs(e%60)),i=0<=e?"+":"-";switch(t){case"short":return i+m(n,2)+":"+m(r,2);case"narrow":return i+n+(0e},t.isBefore=function(e){return!!this.isValid&&this.e<=e},t.contains=function(e){return!!this.isValid&&this.s<=e&&this.e>e},t.set=function(e){var e=void 0===e?{}:e,t=e.start,e=e.end;return this.isValid?l.fromDateTimes(t||this.s,e||this.e):this},t.splitAt=function(){var t=this;if(!this.isValid)return[];for(var e=arguments.length,n=new Array(e),r=0;r+this.e?this.e:u;o.push(l.fromDateTimes(a,u)),a=u,s+=1}return o},t.splitBy=function(e){var t=x.fromDurationLike(e);if(!this.isValid||!t.isValid||0===t.as("milliseconds"))return[];for(var n=this.s,r=1,i=[];n+this.e?this.e:o;i.push(l.fromDateTimes(n,o)),n=o,r+=1}return i},t.divideEqually=function(e){return this.isValid?this.splitBy(this.length()/e).slice(0,e):[]},t.overlaps=function(e){return this.e>e.s&&this.s=e.e},t.equals=function(e){return!(!this.isValid||!e.isValid)&&this.s.equals(e.s)&&this.e.equals(e.e)},t.intersection=function(e){var t;return this.isValid?(t=(this.s>e.s?this:e).s,(e=(this.ee.e?this:e).e,l.fromDateTimes(t,e)):this},l.merge=function(e){var e=e.sort(function(e,t){return e.s-t.s}).reduce(function(e,t){var n=e[0],e=e[1];return e?e.overlaps(t)||e.abutsStart(t)?[n,e.union(t)]:[n.concat([e]),t]:[n,t]},[[],null]),t=e[0],e=e[1];return e&&t.push(e),t},l.xor=function(e){for(var t,n=null,r=0,i=[],e=e.map(function(e){return[{time:e.s,type:"s"},{time:e.e,type:"e"}]}),o=R((t=Array.prototype).concat.apply(t,e).sort(function(e,t){return e.time-t.time}));!(a=o()).done;)var a=a.value,n=1===(r+="s"===a.type?1:-1)?a.time:(n&&+n!=+a.time&&i.push(l.fromDateTimes(n,a.time)),null);return l.merge(i)},t.difference=function(){for(var t=this,e=arguments.length,n=new Array(e),r=0;rthis.valueOf())?this:e,r?e:this,t,n),r?e.negate():e):x.invalid("created by diffing an invalid DateTime")},t.diffNow=function(e,t){return void 0===e&&(e="milliseconds"),void 0===t&&(t={}),this.diff(k.now(),e,t)},t.until=function(e){return this.isValid?xn.fromDateTimes(this,e):this},t.hasSame=function(e,t,n){var r;return!!this.isValid&&(r=e.valueOf(),(e=this.setZone(e.zone,{keepLocalTime:!0})).startOf(t,n)<=r)&&r<=e.endOf(t,n)},t.equals=function(e){return this.isValid&&e.isValid&&this.valueOf()===e.valueOf()&&this.zone.equals(e.zone)&&this.loc.equals(e.loc)},t.toRelative=function(e){var t,n,r,i;return this.isValid?(t=(e=void 0===e?{}:e).base||k.fromObject({},{zone:this.zone}),n=e.padding?thisthis.set({month:1,day:1}).offset||this.offset>this.set({month:5}).offset)}},{key:"isInLeapYear",get:function(){return mt(this.year)}},{key:"daysInMonth",get:function(){return vt(this.year,this.month)}},{key:"daysInYear",get:function(){return this.isValid?yt(this.year):NaN}},{key:"weeksInWeekYear",get:function(){return this.isValid?kt(this.weekYear):NaN}},{key:"weeksInLocalWeekYear",get:function(){return this.isValid?kt(this.localWeekYear,this.loc.getMinDaysInFirstWeek(),this.loc.getStartOfWeek()):NaN}}],[{key:"DATE_SHORT",get:function(){return G}},{key:"DATE_MED",get:function(){return $}},{key:"DATE_MED_WITH_WEEKDAY",get:function(){return B}},{key:"DATE_FULL",get:function(){return Q}},{key:"DATE_HUGE",get:function(){return K}},{key:"TIME_SIMPLE",get:function(){return X}},{key:"TIME_WITH_SECONDS",get:function(){return ee}},{key:"TIME_WITH_SHORT_OFFSET",get:function(){return te}},{key:"TIME_WITH_LONG_OFFSET",get:function(){return ne}},{key:"TIME_24_SIMPLE",get:function(){return re}},{key:"TIME_24_WITH_SECONDS",get:function(){return ie}},{key:"TIME_24_WITH_SHORT_OFFSET",get:function(){return oe}},{key:"TIME_24_WITH_LONG_OFFSET",get:function(){return ae}},{key:"DATETIME_SHORT",get:function(){return se}},{key:"DATETIME_SHORT_WITH_SECONDS",get:function(){return ue}},{key:"DATETIME_MED",get:function(){return le}},{key:"DATETIME_MED_WITH_SECONDS",get:function(){return ce}},{key:"DATETIME_MED_WITH_WEEKDAY",get:function(){return fe}},{key:"DATETIME_FULL",get:function(){return de}},{key:"DATETIME_FULL_WITH_SECONDS",get:function(){return he}},{key:"DATETIME_HUGE",get:function(){return me}},{key:"DATETIME_HUGE_WITH_SECONDS",get:function(){return ye}}]),k}(Symbol.for("nodejs.util.inspect.custom"));function kr(e){if(W.isDateTime(e))return e;if(e&&e.valueOf&&v(e.valueOf()))return W.fromJSDate(e);if(e&&"object"==typeof e)return W.fromObject(e);throw new u("Unknown datetime argument: "+e+", of type "+typeof e)}return e.DateTime=W,e.Duration=x,e.FixedOffsetZone=f,e.IANAZone=c,e.Info=Fn,e.Interval=xn,e.InvalidZone=Le,e.Settings=O,e.SystemZone=ge,e.VERSION="3.5.0",e.Zone=s,Object.defineProperty(e,"__esModule",{value:!0}),e}({}); `); const DateTime = luxon.DateTime; const DateTimeInterval = luxon.Interval; // https://github.com/jkbrzt/rrule eval(` !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.rrule=e():t.rrule=e()}("undefined"!=typeof self?self:this,(()=>(()=>{"use strict";var t={d:(e,n)=>{for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{ALL_WEEKDAYS:()=>n,Frequency:()=>Z,RRule:()=>Pt,RRuleSet:()=>Gt,Weekday:()=>r,datetime:()=>b,rrulestr:()=>Kt});var n=["MO","TU","WE","TH","FR","SA","SU"],r=function(){function t(t,e){if(0===e)throw new Error("Can't create weekday with n == 0");this.weekday=t,this.n=e}return t.fromStr=function(e){return new t(n.indexOf(e))},t.prototype.nth=function(e){return this.n===e?this:new t(this.weekday,e)},t.prototype.equals=function(t){return this.weekday===t.weekday&&this.n===t.n},t.prototype.toString=function(){var t=n[this.weekday];return this.n&&(t=(this.n>0?"+":"")+String(this.n)+t),t},t.prototype.getJsWeekday=function(){return 6===this.weekday?0:this.weekday+1},t}(),i=function(t){return null!=t},o=function(t){return"number"==typeof t},a=function(t){return"string"==typeof t&&n.includes(t)},s=Array.isArray,u=function(t,e){void 0===e&&(e=t),1===arguments.length&&(e=t,t=0);for(var n=[],r=t;r>=0,r.length>e?String(r):((e-=r.length)>n.length&&(n+=h(n,e/n.length)),n.slice(0,e)+String(r))}var c=function(t,e){var n=t%e;return n*e<0?n+e:n},d=function(t,e){return{div:Math.floor(t/e),mod:c(t,e)}},l=function(t){return!i(t)||0===t.length},f=function(t){return!l(t)},p=function(t,e){return f(t)&&-1!==t.indexOf(e)},b=function(t,e,n,r,i,o){return void 0===r&&(r=0),void 0===i&&(i=0),void 0===o&&(o=0),new Date(Date.UTC(t,e-1,n,r,i,o))},m=[31,28,31,30,31,30,31,31,30,31,30,31],w=864e5,v=b(1970,1,1),g=[6,0,1,2,3,4,5],k=function(t){return t%4==0&&t%100!=0||t%400==0},E=function(t){return t instanceof Date},T=function(t){return E(t)&&!isNaN(t.getTime())},x=function(t){return e=v,n=t.getTime()-e.getTime(),Math.round(n/w);var e,n},D=function(t){return new Date(v.getTime()+t*w)},O=function(t){var e=t.getUTCMonth();return 1===e&&k(t.getUTCFullYear())?29:m[e]},S=function(t){return g[t.getUTCDay()]},U=function(t,e){var n=b(t,e+1,1);return[S(n),O(n)]},Y=function(t,e){return e=e||t,new Date(Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()))},L=function(t){return new Date(t.getTime())},M=function(t){for(var e=[],n=0;nthis.maxDate;if("between"===this.method){if(e)return!0;if(n)return!1}else if("before"===this.method){if(n)return!1}else if("after"===this.method)return!!e||(this.add(t),!1);return this.add(t)},t.prototype.add=function(t){return this._result.push(t),!0},t.prototype.getValue=function(){var t=this._result;switch(this.method){case"all":case"between":return t;default:return t.length?t[t.length-1]:null}},t.prototype.clone=function(){return new t(this.method,this.args)},t}();var I=function(t,e){return I=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},I(t,e)};function j(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function n(){this.constructor=t}I(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}var W=function(){return W=Object.assign||function(t){for(var e,n=1,r=arguments.length;nt[0].length)&&(t=r,e=n)}if(null!=t&&(this.text=this.text.substr(t[0].length),""===this.text&&(this.done=!0)),null==t)return this.done=!0,this.symbol=null,void(this.value=null)}while("SKIP"===e);return this.symbol=e,this.value=t,!0},t.prototype.accept=function(t){if(this.symbol===t){if(this.value){var e=this.value;return this.nextSymbol(),e}return this.nextSymbol(),!0}return!1},t.prototype.acceptNumber=function(){return this.accept("number")},t.prototype.expect=function(t){if(this.accept(t))return!0;throw new Error("expected "+t+" but found "+this.symbol)},t}();function G(t,e){void 0===e&&(e=P);var n={},r=new X(e.tokens);return r.start(t)?(function(){r.expect("every");var t=r.acceptNumber();t&&(n.interval=parseInt(t[0],10));if(r.isDone())throw new Error("Unexpected end");switch(r.symbol){case"day(s)":n.freq=Pt.DAILY,r.nextSymbol()&&(o(),h());break;case"weekday(s)":n.freq=Pt.WEEKLY,n.byweekday=[Pt.MO,Pt.TU,Pt.WE,Pt.TH,Pt.FR],r.nextSymbol(),o(),h();break;case"week(s)":n.freq=Pt.WEEKLY,r.nextSymbol()&&(i(),o(),h());break;case"hour(s)":n.freq=Pt.HOURLY,r.nextSymbol()&&(i(),h());break;case"minute(s)":n.freq=Pt.MINUTELY,r.nextSymbol()&&(i(),h());break;case"month(s)":n.freq=Pt.MONTHLY,r.nextSymbol()&&(i(),h());break;case"year(s)":n.freq=Pt.YEARLY,r.nextSymbol()&&(i(),h());break;case"monday":case"tuesday":case"wednesday":case"thursday":case"friday":case"saturday":case"sunday":n.freq=Pt.WEEKLY;var e=r.symbol.substr(0,2).toUpperCase();if(n.byweekday=[Pt[e]],!r.nextSymbol())return;for(;r.accept("comma");){if(r.isDone())throw new Error("Unexpected end");var y=s();if(!y)throw new Error("Unexpected symbol "+r.symbol+", expected weekday");n.byweekday.push(Pt[y]),r.nextSymbol()}o(),function(){r.accept("on"),r.accept("the");var t=u();if(!t)return;n.bymonthday=[t],r.nextSymbol();for(;r.accept("comma");){if(!(t=u()))throw new Error("Unexpected symbol "+r.symbol+"; expected monthday");n.bymonthday.push(t),r.nextSymbol()}}(),h();break;case"january":case"february":case"march":case"april":case"may":case"june":case"july":case"august":case"september":case"october":case"november":case"december":if(n.freq=Pt.YEARLY,n.bymonth=[a()],!r.nextSymbol())return;for(;r.accept("comma");){if(r.isDone())throw new Error("Unexpected end");var c=a();if(!c)throw new Error("Unexpected symbol "+r.symbol+", expected month");n.bymonth.push(c),r.nextSymbol()}i(),h();break;default:throw new Error("Unknown symbol")}}(),n):null;function i(){var t=r.accept("on"),e=r.accept("the");if(t||e)do{var i=u(),o=s(),h=a();if(i)o?(r.nextSymbol(),n.byweekday||(n.byweekday=[]),n.byweekday.push(Pt[o].nth(i))):(n.bymonthday||(n.bymonthday=[]),n.bymonthday.push(i),r.accept("day(s)"));else if(o)r.nextSymbol(),n.byweekday||(n.byweekday=[]),n.byweekday.push(Pt[o]);else if("weekday(s)"===r.symbol)r.nextSymbol(),n.byweekday||(n.byweekday=[Pt.MO,Pt.TU,Pt.WE,Pt.TH,Pt.FR]);else if("week(s)"===r.symbol){r.nextSymbol();var y=r.acceptNumber();if(!y)throw new Error("Unexpected symbol "+r.symbol+", expected week number");for(n.byweekno=[parseInt(y[0],10)];r.accept("comma");){if(!(y=r.acceptNumber()))throw new Error("Unexpected symbol "+r.symbol+"; expected monthday");n.byweekno.push(parseInt(y[0],10))}}else{if(!h)return;r.nextSymbol(),n.bymonth||(n.bymonth=[]),n.bymonth.push(h)}}while(r.accept("comma")||r.accept("the")||r.accept("on"))}function o(){if(r.accept("at"))do{var t=r.acceptNumber();if(!t)throw new Error("Unexpected symbol "+r.symbol+", expected hour");for(n.byhour=[parseInt(t[0],10)];r.accept("comma");){if(!(t=r.acceptNumber()))throw new Error("Unexpected symbol "+r.symbol+"; expected hour");n.byhour.push(parseInt(t[0],10))}}while(r.accept("comma")||r.accept("at"))}function a(){switch(r.symbol){case"january":return 1;case"february":return 2;case"march":return 3;case"april":return 4;case"may":return 5;case"june":return 6;case"july":return 7;case"august":return 8;case"september":return 9;case"october":return 10;case"november":return 11;case"december":return 12;default:return!1}}function s(){switch(r.symbol){case"monday":case"tuesday":case"wednesday":case"thursday":case"friday":case"saturday":case"sunday":return r.symbol.substr(0,2).toUpperCase();default:return!1}}function u(){switch(r.symbol){case"last":return r.nextSymbol(),-1;case"first":return r.nextSymbol(),1;case"second":return r.nextSymbol(),r.accept("last")?-2:2;case"third":return r.nextSymbol(),r.accept("last")?-3:3;case"nth":var t=parseInt(r.value[1],10);if(t<-366||t>366)throw new Error("Nth out of range: "+t);return r.nextSymbol(),r.accept("last")?-t:t;default:return!1}}function h(){if("until"===r.symbol){var t=Date.parse(r.text);if(!t)throw new Error("Cannot parse until date:"+r.text);n.until=new Date(t)}else r.accept("for")&&(n.count=parseInt(r.value[0],10),r.expect("number"))}}function Q(t){return t12){var e=Math.floor(this.month/12),n=c(this.month,12);this.month=n,this.year+=e,0===this.month&&(this.month=12,--this.year)}},e.prototype.addWeekly=function(t,e){e>this.getWeekday()?this.day+=-(this.getWeekday()+1+(6-e))+7*t:this.day+=-(this.getWeekday()-e)+7*t,this.fixDay()},e.prototype.addDaily=function(t){this.day+=t,this.fixDay()},e.prototype.addHours=function(t,e,n){for(e&&(this.hour+=Math.floor((23-this.hour)/t)*t);;){this.hour+=t;var r=d(this.hour,24),i=r.div,o=r.mod;if(i&&(this.hour=o,this.addDaily(i)),l(n)||p(n,this.hour))break}},e.prototype.addMinutes=function(t,e,n,r){for(e&&(this.minute+=Math.floor((1439-(60*this.hour+this.minute))/t)*t);;){this.minute+=t;var i=d(this.minute,60),o=i.div,a=i.mod;if(o&&(this.minute=a,this.addHours(o,!1,n)),(l(n)||p(n,this.hour))&&(l(r)||p(r,this.minute)))break}},e.prototype.addSeconds=function(t,e,n,r,i){for(e&&(this.second+=Math.floor((86399-(3600*this.hour+60*this.minute+this.second))/t)*t);;){this.second+=t;var o=d(this.second,60),a=o.div,s=o.mod;if(a&&(this.second=s,this.addMinutes(a,!1,n,r)),(l(n)||p(n,this.hour))&&(l(r)||p(r,this.minute))&&(l(i)||p(i,this.second)))break}},e.prototype.fixDay=function(){if(!(this.day<=28)){var t=U(this.year,this.month-1)[1];if(!(this.day<=t))for(;this.day>t;){if(this.day-=t,++this.month,13===this.month&&(this.month=1,++this.year,this.year>9999))return;t=U(this.year,this.month-1)[1]}}},e.prototype.add=function(t,e){var n=t.freq,r=t.interval,i=t.wkst,o=t.byhour,a=t.byminute,s=t.bysecond;switch(n){case Z.YEARLY:return this.addYears(r);case Z.MONTHLY:return this.addMonths(r);case Z.WEEKLY:return this.addWeekly(r,i);case Z.DAILY:return this.addDaily(r);case Z.HOURLY:return this.addHours(r,e,o);case Z.MINUTELY:return this.addMinutes(r,e,o,a);case Z.SECONDLY:return this.addSeconds(r,e,o,a,s)}},e}(tt);function nt(t){for(var e=[],n=0,r=Object.keys(t);n=-366&&y<=366))throw new Error("bysetpos must be between 1 and 366, or between -366 and -1")}}if(!(Boolean(e.byweekno)||f(e.byweekno)||f(e.byyearday)||Boolean(e.bymonthday)||f(e.bymonthday)||i(e.byweekday)||i(e.byeaster)))switch(e.freq){case Pt.YEARLY:e.bymonth||(e.bymonth=e.dtstart.getUTCMonth()+1),e.bymonthday=e.dtstart.getUTCDate();break;case Pt.MONTHLY:e.bymonthday=e.dtstart.getUTCDate();break;case Pt.WEEKLY:e.byweekday=[S(e.dtstart)]}if(i(e.bymonth)&&!s(e.bymonth)&&(e.bymonth=[e.bymonth]),i(e.byyearday)&&!s(e.byyearday)&&o(e.byyearday)&&(e.byyearday=[e.byyearday]),i(e.bymonthday))if(s(e.bymonthday)){var u=[],h=[];for(n=0;n0?u.push(y):y<0&&h.push(y)}e.bymonthday=u,e.bynmonthday=h}else e.bymonthday<0?(e.bynmonthday=[e.bymonthday],e.bymonthday=[]):(e.bynmonthday=[],e.bymonthday=[e.bymonthday]);else e.bymonthday=[],e.bynmonthday=[];if(i(e.byweekno)&&!s(e.byweekno)&&(e.byweekno=[e.byweekno]),i(e.byweekday))if(o(e.byweekday))e.byweekday=[e.byweekday],e.bynweekday=null;else if(a(e.byweekday))e.byweekday=[r.fromStr(e.byweekday).weekday],e.bynweekday=null;else if(e.byweekday instanceof r)!e.byweekday.n||e.freq>Pt.MONTHLY?(e.byweekday=[e.byweekday.weekday],e.bynweekday=null):(e.bynweekday=[[e.byweekday.weekday,e.byweekday.n]],e.byweekday=null);else{var c=[],d=[];for(n=0;nPt.MONTHLY?c.push(l.weekday):d.push([l.weekday,l.n])}e.byweekday=f(c)?c:null,e.bynweekday=f(d)?d:null}else e.bynweekday=null;return i(e.byhour)?o(e.byhour)&&(e.byhour=[e.byhour]):e.byhour=e.freq=4?(d=0,r=y.yearlen+c(u-e.wkst,7)):r=o-d;for(var f=Math.floor(r/7),m=c(r,7),w=Math.floor(f+m/4),v=0;v0&&g<=w){var E=void 0;g>1?(E=d+7*(g-1),d!==n&&(E-=7-n)):E=d;for(var T=0;T<7&&(y.wnomask[E]=1,E++,y.wdaymask[E]!==e.wkst);T++);}}if(p(e.byweekno,1)){E=d+7*w;if(d!==n&&(E-=7-n),E=4?(U=0,L=Y+c(O-e.wkst,7)):L=o-d,D=Math.floor(52+c(L,7)/4)}if(p(e.byweekno,D))for(E=0;E=Pt.HOURLY&&f(i)&&!p(i,e.hour)||r>=Pt.MINUTELY&&f(o)&&!p(o,e.minute)||r>=Pt.SECONDLY&&f(a)&&!p(a,e.second))return[];return t.gettimeset(r)(e.hour,e.minute,e.second,e.millisecond)}(y,h,e);;){var d=y.getdayset(r)(h.year,h.month,h.day),l=d[0],b=d[1],m=d[2],w=jt(l,b,m,y,e);if(f(s))for(var v=Rt(s,c,b,m,y,l),g=0;ga)return It(t);if(k>=n){var E=Ct(k,e);if(!t.accept(E))return It(t);if(u&&!--u)return It(t)}}else for(g=b;ga)return It(t);if(k>=n){E=Ct(k,e);if(!t.accept(E))return It(t);if(u&&!--u)return It(t)}}}if(0===e.interval)return It(t);if(h.add(e,w),h.year>9999)return It(t);Q(r)||(c=y.gettimeset(r)(h.hour,h.minute,h.second,0)),y.rebuild(h.year,h.month)}}function At(t,e,n){var r=n.bymonth,i=n.byweekno,o=n.byweekday,a=n.byeaster,s=n.bymonthday,u=n.bynmonthday,h=n.byyearday;return f(r)&&!p(r,t.mmask[e])||f(i)&&!t.wnomask[e]||f(o)&&!p(o,t.wdaymask[e])||f(t.nwdaymask)&&!t.nwdaymask[e]||null!==a&&!p(t.eastermask,e)||(f(s)||f(u))&&!p(s,t.mdaymask[e])&&!p(u,t.nmdaymask[e])||f(h)&&(e=t.yearlen&&!p(h,e+1-t.yearlen)&&!p(h,-t.nextyearlen+e-t.yearlen))}function Ct(t,e){return new ht(t,e.tzid).rezonedDate()}function It(t){return t.getValue()}function jt(t,e,n,r,i){for(var o=!1,a=e;a0&&" "===i[0]?(n[r-1]+=i.slice(1),n.splice(r,1)):r+=1:n.splice(r,1)}return n}(t,e.unfold);return h.forEach((function(t){var e;if(t){var a=function(t){var e=function(t){if(-1===t.indexOf(":"))return{name:"RRULE",value:t};var e=(i=t,o=":",a=1,s=i.split(o),a?s.slice(0,a).concat([s.slice(a).join(o)]):s),n=e[0],r=e[1];var i,o,a,s;return{name:n,value:r}}(t),n=e.name,r=e.value,i=n.split(";");if(!i)throw new Error("empty property name");return{name:i[0].toUpperCase(),parms:i.slice(1),value:r}}(t),s=a.name,h=a.parms,y=a.value;switch(s.toUpperCase()){case"RRULE":if(h.length)throw new Error("unsupported RRULE parm: ".concat(h.join(",")));n.push(it(t));break;case"RDATE":var c=(null!==(e=/RDATE(?:;TZID=([^:=]+))?/i.exec(t))&&void 0!==e?e:[])[1];c&&!u&&(u=c),r=r.concat(Zt(y,h));break;case"EXRULE":if(h.length)throw new Error("unsupported EXRULE parm: ".concat(h.join(",")));i.push(it(y));break;case"EXDATE":o=o.concat(Zt(y,h));break;case"DTSTART":break;default:throw new Error("unsupported property: "+s)}}})),{dtstart:s,tzid:u,rrulevals:n,rdatevals:r,exrulevals:i,exdatevals:o}}function Kt(t,e){return void 0===e&&(e={}),function(t,e){var n=zt(t,e),r=n.rrulevals,i=n.rdatevals,o=n.exrulevals,a=n.exdatevals,s=n.dtstart,u=n.tzid,h=!1===e.cache;if(e.compatible&&(e.forceset=!0,e.unfold=!0),e.forceset||r.length>1||i.length||o.length||a.length){var y=new Gt(h);return y.dtstart(s),y.tzid(u||void 0),r.forEach((function(t){y.rrule(new Pt(Bt(t,s,u),h))})),i.forEach((function(t){y.rdate(t)})),o.forEach((function(t){y.exrule(new Pt(Bt(t,s,u),h))})),a.forEach((function(t){y.exdate(t)})),e.compatible&&e.dtstart&&y.rdate(s),y}var c=r[0]||{};return new Pt(Bt(c,c.dtstart||e.dtstart||s,c.tzid||e.tzid||u),h)}(t,function(t){var e=[],n=Object.keys(t),r=Object.keys(Ft);if(n.forEach((function(t){p(r,t)||e.push(t)})),e.length)throw new Error("Invalid options: "+e.join(", "));return W(W({},Ft),t)}(e))}function Bt(t,e,n){return W(W({},t),{dtstart:e,tzid:n})}function Zt(t,e){return function(t){t.forEach((function(t){if(!/(VALUE=DATE(-TIME)?)|(TZID=)/.test(t))throw new Error("unsupported RDATE/EXDATE parm: "+t)}))}(e),t.split(",").map((function(t){return N(t)}))}function Xt(t){var e=this;return function(n){if(void 0!==n&&(e["_".concat(t)]=n),void 0!==e["_".concat(t)])return e["_".concat(t)];for(var r=0;r