Business-Day and Holiday-Aware Scheduling Automation: The Fix That Scheduled Its Own First Run on a National Holiday

A fix that only handles weekends looks complete until a holiday falls on a weekday
Handling Saturday and Sunday correctly covers the overwhelming majority of calendar days by definition — five out of seven — which is exactly what makes a weekend-only fix look finished the moment it ships. The gap only becomes visible on the specific weekday, a handful of times a year, when a real holiday sits where a business day is otherwise assumed, and by then the fix has already scheduled something for a day nobody is actually working.
How the underlying problem shows up before you fix it
A date-shifting rule correctly rewrites `Saturday` to `Monday` and `Sunday` to `Monday`, and nothing in that logic has any awareness that a Tuesday can be just as unworkable as a Sunday.
A timestamp computed as a bare date, with no time zone or time-of-day attached, gets interpreted at midnight UTC — which a screen in a different time zone can display as the evening of the PREVIOUS calendar day, compounding a scheduling bug with a display bug.
A scheduling fix is written, tested against the two weekend days, and shipped, without anyone checking the fix against the specific calendar week it will actually run in first.
Multiple independent code paths each compute their own version of "the next reasonable date to act," so a fix applied to one of them leaves every other path carrying the exact same defect, undetected.
A handful of records already written under the old, incorrect logic keep their bad timestamps indefinitely, because a forward-looking fix corrects new writes but does nothing about what already exists.
How the gap was caught the same day, and how the fix became a shared platform primitive
The first version of this fix, shipped the morning of 2026-09-05, replaced a bare `(now() + interval '2 days')::date` — a calculation with two separate real defects of its own: a Friday lead landed its next action on a Sunday, and a date with no time attached rendered on screen as 9pm the day before, because a plain date defaults to midnight UTC. That first fix corrected both: it resolved Saturday to the following Monday and Sunday to the following Monday, and it explicitly attached 9am São Paulo time to the result.
That version's own first live run, the same morning, computed a next-action date of 2026-09-07 for a batch of real leads and tasks — Brazil's Independence Day, a national holiday nobody works. The owner caught it before it caused a missed approach, and a second migration shipped later the same day replacing the weekend-only check with a genuine calendar: a function listing nine holidays that fall on the same calendar date every year (New Year's Day, Tiradentes, Labor Day, Independence Day, Our Lady of Aparecida, All Souls' Day, Proclamation of the Republic, Black Consciousness Day, Christmas) plus eight specific moveable-holiday dates already published for 2026 and 2027 (Carnival and Corpus Christi, which shift with the liturgical calendar and cannot be expressed as a fixed month-and-day).
The resolver itself changed from a single Saturday/Sunday branch into a loop: starting from the requested date, it steps forward one day at a time — capped at ten iterations as a safety bound — checking each candidate day against both the weekend condition and the holiday-lookup function, and stops on the first day that is neither. The final timestamp is always fixed at 9am São Paulo time, replacing the earlier bare-date approach entirely. Because this resolver lives in the database as one shared function, every place across Orbit that writes a "next action" timestamp — a new lead's first-approach date, a salesperson's own follow-up entered through the record-updating tool, a nurture-sequence step — now calls the identical calendar-aware logic, rather than each write path carrying its own copy of a business-day rule that could drift out of sync with the others. A corrective data migration in the same change moved the specific handful of real tasks and deals already miscalculated by the first version's weekend-only logic onto their correct next business day.
What is actually built today
A shared database function resolves any timestamp to the next real business day — skipping Saturday, Sunday, AND any of seventeen specifically listed Brazilian national holiday dates across 2026-2027.
The resolver distinguishes fixed-date holidays (checked by month-and-day, recurring every year) from moveable ones (checked against explicit published dates, since their calendar position shifts year to year).
Every resolved timestamp is anchored to 9am São Paulo time, replacing an earlier bare-date calculation whose lack of a time zone caused it to display as the previous evening on screen.
Every 'next action' timestamp Orbit writes — a new lead's first approach, a salesperson's follow-up, a nurture-sequence step — now calls this identical shared function.
A same-day corrective migration moved the specific real records miscalculated by the fix's own first, weekend-only version onto their correct business-day timestamp.
Every recurring or daily routine belonging to a sales-facing role was separately updated to only run on weekdays, so scheduled outreach cannot itself fire on a day the underlying dates already skip.
A fix that almost scheduled its own mistake (illustrative framing of the actual measured finding)
A lead is registered on a Friday afternoon. Under the very first version of this fix, its first-approach date correctly skips the coming weekend and lands on Monday — except that Monday happens to be a national holiday nobody works, and the batch of real records computed that same morning did exactly that. Under the corrected version, the identical Friday-afternoon lead resolves past both the weekend AND the holiday, landing on the next day someone is genuinely at their desk.
What changes operationally
No next-action timestamp written anywhere in Orbit can land on a weekend or on one of seventeen specifically listed Brazilian national holidays through 2027, closing a gap that, in its own first version, had already scheduled a real batch of client contact for a day the entire team was off.
When this is not the right fit
This automation governs which calendar day a computed timestamp lands on — it does not decide whether a given day off should count as a holiday for a specific client or region outside the listed national dates, and it does not automatically extend past 2027 without the holiday list itself being updated.
A fix that handles two-sevenths of the calendar vs. one that handles all of it
A weekend-only rule is a reasonable-sounding shortcut precisely because it is correct five days out of seven — which is exactly the trap: a partial fix that is right the overwhelming majority of the time still fails predictably on the handful of days that matter most for looking careless. Centriu's corrected version treats "is this a real business day" as a genuine calendar question, with an explicit, auditable list of the days that don't count, rather than a shortcut that happens to work most weeks.
Related systems
Main system: Centriu Axis. Complementary when relevant: Centriu Orbit.
What it does NOT do
- Does not account for regional or client-specific holidays outside the seventeen listed Brazilian national dates — a client observing a state or municipal holiday is not automatically skipped.
- Does not extend the holiday calendar automatically past 2027 — the moveable-holiday dates are explicit, published values that need updating as new years are published.
- Does not change how or when a person or agent chooses to act on a given day — it only governs where a computed "next action" timestamp lands.
- Does not retroactively correct every historical timestamp ever written before this fix — the corrective migration moved only the specific batch of records affected by the first version's own weekend-only logic.
- Does not prevent a person from manually entering a weekend or holiday date on purpose — the automatic resolver applies to computed next-action dates, not every date field in the system.
- Does not guarantee every scheduling defect across the platform has been found — this fix closes the specific, measured weekend-and-holiday gap found in this audit.
Security and governance
The scheduling function operates on timestamps only and reads no client-identifying data beyond what the calling write path already has permission to touch; every write it supports remains scoped to the calling organization. Any business data referenced remains subject to Brazil's LGPD (Law No. 13,709/2018). Full detail on access control lives at /governanca and /iso.
Pricing and contracting
Included at no extra cost with any Centriu contract. Values and terms come from the official pricing table at /precos (Centriu's central source — never restated here).
Frequently asked questions
Why did the first version of this fix schedule something on a holiday?
It only checked for Saturday and Sunday. Its own first live calculation, the same morning it shipped, computed a next-action date that happened to fall on Brazil's Independence Day — caught the same day and corrected with a real holiday calendar hours later.
Which holidays does the calendar actually list?
Nine fixed-date national holidays (New Year's Day, Tiradentes, Labor Day, Independence Day, Our Lady of Aparecida, All Souls' Day, Proclamation of the Republic, Black Consciousness Day, Christmas) plus eight explicit moveable-holiday dates already published for 2026 and 2027 (Carnival and Corpus Christi).
What time does a resolved date land on?
9am, São Paulo time — replacing an earlier bare-date calculation that had no time zone attached and could display as the previous evening on screen.
Does every part of Orbit use this same calendar logic?
Yes — it is a single shared database function, and every place that writes a next-action timestamp calls it, rather than each write path carrying its own separate business-day rule.
What happened to the records miscalculated by the first version?
A same-day corrective migration moved the specific handful of real tasks and deals affected by the weekend-only logic onto their correct business-day timestamp.
What does Centriu Axis cost?
It is sold by subscription with a published starting price — exact current values are on the central pricing page.
See how Centriu Axis keeps every scheduled action on a real business day
Reach our commercial team directly, or leave your details below — we'll follow up with guidance for your case.