The calendar rules behind every target the plugin calculates — including the awkward cases: daylight saving, month ends, leap days and disallowed weekdays.
Who Owns a Schedule #
An active recurring feed starts one series per parent/feed pair when its initial conditional logic passes.
At that moment, the feed’s settings are copied into a normalized schedule snapshot on the series. From then on:
| Action | Effect on existing series |
|---|---|
| Ordinary feed save | None. New series only. |
| Change next submission | Moves that one series’ target; the cadence continues from it. |
| Apply saved feed schedule | Copies schedule settings to the series you select, after a preview and confirmation. |
Recurrence changes belong in feed settings. Date moves belong in Queue. The separation is the point: neither one can surprise you with the other’s effect.
Local Time, Stored as UTC #
Calendar intervals are calculated in the schedule’s selected local timezone, and stored as UTC epoch targets.
That combination is what makes “every day at 11:00” mean 11:00 all year, while the stored value remains unambiguous.
Daylight Saving #
| Case | Behaviour |
|---|---|
| Ordinary DST change | A daily 11:00 schedule stays at 11:00. |
| Spring-forward gap | A time that doesn’t exist moves to the first valid instant after the gap. |
| Autumn overlap | A time that happens twice uses the first occurrence. |
| Fixed UTC offset | Cannot follow DST at all. An 11:00 schedule effectively shifts by an hour for half the year. |
Use an IANA timezone name — America/New_York, Europe/London — rather than an offset. The feed editor links to your WordPress timezone settings when it detects an offset.
Month and Year Recurrence #
Monthly and yearly recurrence keeps an anchor day.
- If the anchor day doesn’t exist in a given period, the target clamps to the last day of that period.
- When the anchor day exists again, the schedule returns to it.
| Anchor | January | February | March |
|---|---|---|---|
| 31st | Jan 31 | Feb 28 (clamped) | Mar 31 (restored) |
| 29th | Jan 29 | Feb 29 in a leap year, Feb 28 otherwise | Mar 29 |
Clamping never permanently drags a schedule earlier.
Allowed Weekdays #
The Monday–Sunday checkboxes filter when a slot may land, without changing the underlying calendar anchor.
- A slot landing on a disallowed weekday moves forward to the next allowed weekday.
- The anchor itself is unchanged, so the schedule doesn’t drift permanently.
- If multiple slots coincide on the same eligible day, they produce one occurrence — never a burst.
At least one weekday must remain selected.
End Conditions #
| Condition | Rule |
|---|---|
| Number of successful submissions | Counts successful children only. The parent isn’t counted; failures, conditional skips and skipped missed runs don’t count. |
| End date | Inclusive upper bound, evaluated in the schedule’s timezone. |
| Number from parent form field | The same counting rule, with the limit read from a Number field on the parent. |
The First Occurrence #
A new schedule applies the interval first, then the clock time.
Daily feed. Parent submitted September 14 at 01:14. Specified time 01:20. First run: September 15 at 01:20.
Not six minutes later — a full day later, at the specified time.
This avoids a surprise submission moments after someone fills in a form. When you want the earlier first run, Change next submission sets it explicitly.
Run Time Modes #
| Mode | Behaviour |
|---|---|
| Preserve original submission local time | Each occurrence uses the parent’s own submission time-of-day. Feeds saved before this setting existed behave this way. |
| Specified local time | Every occurrence uses the HH:MM you set, in the schedule’s timezone. |
In preserve mode, the feed preview has to estimate — it uses “a parent submitted now”. Once a series actually starts, it uses that parent’s real timestamp.
One Target at a Time #
The single most consequential rule in the plugin:
A series holds one next target. It never accumulates a queue.
The next target is calculated after each attempt resolves. There is no list of pending occurrences, so there is nothing that could ever replay.
This is why:
- downtime never produces a backlog,
- lateness never compounds,
- and moving one target simply re-anchors everything after it.
Manual Actions and the Anchor #
| Action | Effect on the rhythm |
|---|---|
| Run Next Submission Now | Consumes the next slot, preserving the long-term anchor. |
| Retry Failed Submission | Re-runs the failed target. The anchor is unchanged. |
| Change next submission | Re-anchors the cadence to the date and time you chose. |
| Resume | Picks the next eligible future slot; the paused interval is skipped entirely. |
Optionally shifting the cadence based on a manual run’s time is on the roadmap.