Skip to content

feat(business-days): count Saturday with includeSaturday - #573

Open
hyanmandian wants to merge 1 commit into
claude/business-day-helpersfrom
claude/business-day-saturdays
Open

hyanmandian wants to merge 1 commit into
claude/business-day-helpersfrom
claude/business-day-saturdays

Conversation

@hyanmandian

@hyanmandian hyanmandian commented Sep 19, 2026

Copy link
Copy Markdown
Member

Stacked on #561. The base of this PR is claude/business-day-helpers, not main, because it also touches getNthBusinessDay, getNextBusinessDay and getLastBusinessDayOfMonth, which #561 adds. Merge #561 first; GitHub will retarget this one to main afterwards.

What

Today isBusinessDay and the whole family count Monday to Friday minus holidays. That is the banking count, and it is the wrong one for the payroll deadline of CLT art. 459 § 1º ("até o quinto dia útil do mês subsequente ao vencido"): labour inspection reads that deadline through Instrução Normativa MTP nº 2/2021, art. 14, I, which says verbatim "na contagem dos dias será incluído o sábado, excluindo-se o domingo e o feriado, inclusive o municipal". So the labour "quinto dia útil" can fall a day earlier than the banking one: in March 2024 it is Wednesday the 6th (Saturday 2 March counts), while the banking one is Thursday the 7th.

This PR adds includeSaturday to the shared BusinessDayOptions. It defaults to false, which is exactly today's behaviour, so nothing existing changes. Every utility of the family honours it, since they all evaluate days through isBusinessDay with the caller's options.

With the option on, Sunday and holidays are still excluded, exactly as the article says, so a holiday that falls on a Saturday is still not a business day (Finados on Saturday 2 November 2024, Independência on Saturday 7 September 2024, Dia do Evangélico on Saturday 30 November 2024 in the DF).

On top of #561's shared day walk

#561 now also replaces the setDate day walk of addBusinessDays, differenceInBusinessDays and getNthBusinessDay with one internal, _internals/each-local-day, which walks integer day offsets and yields each day at noon, so it cannot hang in Pacific/Apia, Pacific/Fakaofo, Pacific/Kwajalein, Pacific/Kiritimati or Pacific/Enderbury. This PR is rebased on that. includeSaturday needs no code in the walk: every util calls isBusinessDay(candidate, options) on the days eachLocalDay yields, so the option goes through the shared walk unchanged. Tests pin it under TZ=Pacific/Apia across the missing Friday 30 December 2011, against the same calls under UTC:

  • getNthBusinessDay(new Date(2011, 11, 15), -2, { includeSaturday: true }) is Thu 2011-12-29 in Apia (Fri 30th skipped, Sat 31st counted) and Fri 2011-12-30 in UTC; December 2011 has 26 such business days in Apia and 27 in UTC.
  • differenceInBusinessDays(new Date(2011, 11, 1), new Date(2011, 11, 31), { includeSaturday: true }) is -25 in Apia and -26 in UTC.
  • subBusinessDays(new Date(2012, 0, 2, 12), 2, { includeSaturday: true }) is Thu 2011-12-29 12:00 in Apia.

Why includeSaturday and not something else

  • It is the same shape and the same prefix as the option already on the type, includeOptional: a boolean that widens what counts, named after what it includes. saturdays: boolean does not say what setting it does; includeSaturday does.
  • Singular, because it is one weekday, not a set.
  • It deliberately does not name the law (clt, laborLaw, payroll, in2/2021). A name like that would promise the whole rule of art. 14, I, and this library cannot deliver the "inclusive o municipal" half of it (see Open points). includeSaturday promises exactly what it does.
  • false is the default, so the existing Monday-to-Friday answer is what every current call keeps getting.

API

No signature changes. One new optional key on the existing shared type:

export type BusinessDayOptions = {
	stateCode?: StateCode;
	includeOptional?: boolean;
	/** Whether Saturday counts as a business day, the labour law count of Instrução Normativa MTP nº 2/2021, art. 14, I (default: `false`, the Monday to Friday banking count). */
	includeSaturday?: boolean;
};
isBusinessDay(new Date(2024, 0, 6)); // false (Saturday, banking count)
isBusinessDay(new Date(2024, 0, 6), { includeSaturday: true }); // true
isBusinessDay(new Date(2024, 0, 7), { includeSaturday: true }); // false (Sunday is never included)
isBusinessDay(new Date(2024, 8, 7), { includeSaturday: true }); // false (Independência, a holiday on a Saturday)

// The payroll deadline of CLT art. 459 § 1º, March 2024
getNthBusinessDay(new Date(2024, 2, 1), 5); // Thu 2024-03-07 (banking count)
getNthBusinessDay(new Date(2024, 2, 1), 5, { includeSaturday: true }); // Wed 2024-03-06 (labour count)

// November 2024: both counts give Thursday the 7th, because Saturday the 2nd is Finados
getNthBusinessDay(new Date(2024, 10, 1), 5, { includeSaturday: true }); // Thu 2024-11-07

addBusinessDays(new Date(2024, 0, 5, 12), 1, { includeSaturday: true }); // Sat 2024-01-06 12:00
subBusinessDays(new Date(2024, 0, 8, 12), 1, { includeSaturday: true }); // Sat 2024-01-06 12:00
getNextBusinessDay(new Date(2024, 0, 5, 12), { includeSaturday: true }); // Sat 2024-01-06 12:00
differenceInBusinessDays(new Date(2024, 0, 8), new Date(2024, 0, 1)); // 4
differenceInBusinessDays(new Date(2024, 0, 8), new Date(2024, 0, 1), { includeSaturday: true }); // 5
getLastBusinessDayOfMonth(new Date(2024, 7, 1), { includeSaturday: true }); // Sat 2024-08-31

Sources

Read in full, not from memory:

  • CLT (Decreto-Lei 5.452/1943), art. 459 § 1º — the deadline itself: "Quando o pagamento houver sido estipulado por mês, deverá ser efetuado, o mais tardar, até o quinto dia útil do mês subsequente ao vencido" (Redação dada pela Lei nº 7.855, de 24.10.1989). Note that the article's original parágrafo único, still shown struck through on the Planalto page, said "décimo dia útil"; the § 1º wording is the one in force.
  • Instrução Normativa MTP nº 2, de 8 de novembro de 2021 (gov.br PDF, DOU 28/11/2021, Edição 213, Seção 1, Página 153), art. 14: "Para efeito de orientação quanto ao prazo para o pagamento dos salários, os Auditores-Fiscais do Trabalho deverão observar o seguinte: I - na contagem dos dias será incluído o sábado, excluindo-se o domingo e o feriado, inclusive o municipal". This is the rule the option implements. Its § 2º ties the infraction back to § 1º do art. 459 da CLT, which is why the two sources belong together.
  • Lei 9.093/1995, art. 2º — "São feriados religiosos os dias de guarda, declarados em lei municipal, de acordo com a tradição local e em número não superior a quatro". This is why the municipal half of art. 14, I cannot be implemented here: those holidays live in each municipality's own law and getHolidays does not carry them.

The national and state holidays the count subtracts are unchanged and keep the sources already cited in getHolidays/isBusinessDay.

Verification

  • npm run check — pass (format, lint, types).
  • npm run test -- --run — 6277 passed (after the rebase on feat(business-days): add getNthBusinessDay, getNextBusinessDay and getLastBusinessDayOfMonth, and fix the day walk that hangs in five time zones #561).
  • npm run test:coverage — 100% statements/branches/functions/lines.
  • npm run test:bun / npm run test:deno — passed before the rebase (6244); after it, left to CI.
  • npm run build — pass, attw and publint clean.
  • npm run check:api:update — the report gains exactly one line, includeSaturday?: boolean;; committed.
  • npm run check:unused — pass. npm run check:duplication — 0 clones. npm run check:tree-shaking — pass. npm run check:commits — 0 problems.
  • npm run test:mutation on each touched source file (before the rebase; the rebase changed no line of this PR's source, only its tests): is-business-day.ts 100% (55 killed), add-business-days.ts 100%, sub-business-days.ts 100%, difference-in-business-days.ts 100%, get-nth-business-day.ts 100%, get-next-business-day.ts 100%, get-last-business-day-of-month.ts 100%. No survivors, no new Stryker disables.
  • npm run build:llms run, docs/llms.txt and docs/llms-full.txt committed.

Tests

Every expectation is a literal date counted by hand against the holiday tables, including:

  • A Saturday that changes the answer: 6 January 2024 (isBusinessDay), Friday 5 January + 1 landing on it, Monday 8 January - 1 landing on it, 31 August 2024 as the last business day of August, the 26 business days January 2024 has with Saturdays (22 + the Saturdays 6, 13, 20 and 27) against the 22 without them.
  • A holiday that falls on a Saturday, which the option must not promote: Finados on 2 November 2024, Independência on 7 September 2024, Dia do Evangélico on 30 November 2024 with stateCode: "DF". September 2024 exercises both at once: the 11th business day is Saturday the 14th with the option (Saturday the 7th skipped as Independência) and Monday the 16th without it.
  • Sunday, which the option must never touch, both as a literal case and as a fast-check property over the whole supported year range.
  • A describe("no breaking change") block pinning that an absent, false or undefined includeSaturday, and an options carrying only stateCode or includeOptional, all still answer false for a Saturday.
  • The should agree with getHolidays and the weekend rule property now ranges over includeSaturday too.

Open points

  • Municipal holidays are not covered. Art. 14, I excludes "o feriado, inclusive o municipal". getHolidays has national and state holidays only, so with includeSaturday: true a municipal holiday is counted here as an ordinary business day while the labour inspection would exclude it. A count that has to be exact for one municipality still needs those days removed on top of this option. This is stated in the JSDoc of isBusinessDay and getNthBusinessDay and in both docs/utilities.md files rather than glossed over. Adding a municipal holiday dataset is a separate piece of work.
  • The IN was later amended (by IN MTP nº 2 de 22/12/2022 and IN MTP nº 3 de 28/12/2022, both listed on the header of the PDF above). Neither touches art. 14; the wording quoted here is the one in the consolidated PDF the ministry publishes.
  • A non-boolean truthy includeSaturday (for example the string "false") enables the option, the same way a non-boolean truthy includeOptional behaves today. That is existing house behaviour for these flags, not something this PR changes; the never-throws property covers hostile values.
  • isBusinessDay no longer builds a module level new Set([0, 6]) for the weekend check, replaced by two plain number constants, which is what the tree-shaking rule in CONTRIBUTING.md asks modules to do. Behaviour is identical.

CI

Rebased onto the current tip of #561 and force-pushed: every check green on 5619d05 (Build, Check, Stryker, Node 20/22/24/26, Bun, Deno, the four browsers). The first Check run failed in Audit dependencies with audit-ci exiting on code undefined before any project code ran, a registry hiccup; the rerun passed.

Summary by CodeRabbit

  • New Features

    • Added an includeSaturday option to business-day utilities.
    • When enabled, Saturdays count as business days unless they are holidays; Sundays and holidays remain excluded.
    • The option defaults to false, preserving existing banking-day behavior.
    • Supports forward and backward calculations, differences, next and nth business days, and month-end calculations.
  • Documentation

    • Added examples covering labor-law counts, banking-day counts, state holidays, and Saturday holidays.

@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 74914beb-6c90-4fc2-b9d8-34cb06275d8b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 8c334969-9aa3-49a2-9ec5-c0f21977014d

📥 Commits

Reviewing files that changed from the base of the PR and between 3a4bb06 and 5619d05.

📒 Files selected for processing (10)
  • docs/llms-full.txt
  • docs/pt-br/utilities.md
  • docs/utilities.md
  • src/add-business-days/add-business-days.ts
  • src/difference-in-business-days/difference-in-business-days.test.ts
  • src/difference-in-business-days/difference-in-business-days.ts
  • src/get-last-business-day-of-month/get-last-business-day-of-month.ts
  • src/get-nth-business-day/get-nth-business-day.test.ts
  • src/get-nth-business-day/get-nth-business-day.ts
  • src/sub-business-days/sub-business-days.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/get-last-business-day-of-month/get-last-business-day-of-month.ts
  • src/get-nth-business-day/get-nth-business-day.ts
  • src/add-business-days/add-business-days.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

Added the optional includeSaturday setting to business-day handling. Saturdays count when enabled. Sundays and holidays remain excluded. Tests and documentation cover the affected utilities.

Changes

Business-day Saturday option

Layer / File(s) Summary
Business-day contract and predicate
src/is-business-day/*, src/_internals/test/arbitraries.ts, reports/api/brazilian-utils.api.md
BusinessDayOptions now includes includeSaturday. isBusinessDay conditionally accepts Saturdays while continuing to reject Sundays and holidays.
Business-day utility coverage
src/add-business-days/*, src/sub-business-days/*, src/difference-in-business-days/*, src/get-next-business-day/*, src/get-nth-business-day/*, src/get-last-business-day-of-month/*
Utility documentation and tests cover Saturday-inclusive counting, Saturday holidays, reverse calculations, time zones, and state-holiday handling.
Reference documentation updates
docs/utilities.md, docs/pt-br/utilities.md, docs/llms.txt, docs/llms-full.txt
Reference documentation describes the option, its default, examples, holiday rules, and municipal-holiday limitations.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 15 files. (3 skipped: 3… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding optional Saturday counting through includeSaturday for business-day utilities.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 15 files. (3 skipped: 3 unsupported.)

✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Tree-shaking report

No size regression. 7 grew out of 158 exports.

Base Head Δ
Pre-existing exports, all imported 649.7 KB 649.8 KB (gzip 166.4 KB) +43 B (+0.0%)
Full import 649.7 KB 649.8 KB (gzip 166.4 KB) +43 B (+0.0%)
Exports 158 158 0

What changed (7)

Export Base Head Δ gzip
🟡 addBusinessDays 7.3 KB 7.3 KB +43 B (+0.6%) 3.0 KB
🟡 differenceInBusinessDays 7.1 KB 7.1 KB +43 B (+0.6%) 3.0 KB
🟡 getLastBusinessDayOfMonth 7.2 KB 7.2 KB +43 B (+0.6%) 3.0 KB
🟡 getNextBusinessDay 7.3 KB 7.3 KB +43 B (+0.6%) 3.0 KB
🟡 getNthBusinessDay 7.2 KB 7.2 KB +43 B (+0.6%) 3.0 KB
🟡 subBusinessDays 7.3 KB 7.4 KB +43 B (+0.6%) 3.0 KB
🟡 isBusinessDay 6.5 KB 6.6 KB +42 B (+0.6%) 2.8 KB
All exports (158)
Export Base Head Δ gzip
GetAddressInfoByCepError 966 B 966 B 0 B 600 B
GetAddressInfoByCepNotFoundError 1.0 KB 1.0 KB 0 B 618 B
GetAddressInfoByCepServiceError 1.0 KB 1.0 KB 0 B 617 B
GetAddressInfoByCepValidationError 1.0 KB 1.0 KB 0 B 620 B
GetCepInfoByAddressError 966 B 966 B 0 B 600 B
GetCepInfoByAddressNotFoundError 1.0 KB 1.0 KB 0 B 618 B
GetCepInfoByAddressValidationError 1.0 KB 1.0 KB 0 B 620 B
🟡 addBusinessDays 7.3 KB 7.3 KB +43 B (+0.6%) 3.0 KB
capitalize 2.5 KB 2.5 KB 0 B 1.3 KB
convertCurrencyToWords 2.8 KB 2.8 KB 0 B 1.5 KB
convertDateToWords 3.2 KB 3.2 KB 0 B 1.7 KB
convertLicensePlateToMercosul 1.3 KB 1.3 KB 0 B 807 B
convertNumberToWords 2.4 KB 2.4 KB 0 B 1.3 KB
🟡 differenceInBusinessDays 7.1 KB 7.1 KB +43 B (+0.6%) 3.0 KB
formatBoleto 1.4 KB 1.4 KB 0 B 837 B
formatCEP 1.2 KB 1.2 KB 0 B 778 B
formatCNPJ 1.4 KB 1.4 KB 0 B 855 B
formatCPF 1.3 KB 1.3 KB 0 B 807 B
formatCaepf 1.3 KB 1.3 KB 0 B 787 B
formatCei 1.3 KB 1.3 KB 0 B 785 B
formatCep 1.2 KB 1.2 KB 0 B 778 B
formatCertidao 1.3 KB 1.3 KB 0 B 789 B
formatCnae 1.2 KB 1.2 KB 0 B 782 B
formatCnh 1.3 KB 1.3 KB 0 B 780 B
formatCno 1.3 KB 1.3 KB 0 B 786 B
formatCnpj 1.4 KB 1.4 KB 0 B 855 B
formatCns 1.3 KB 1.3 KB 0 B 780 B
formatCpf 1.3 KB 1.3 KB 0 B 807 B
formatCurrency 1.8 KB 1.8 KB 0 B 1.0 KB
formatIban 1.1 KB 1.1 KB 0 B 696 B
formatLegalNature 1.2 KB 1.2 KB 0 B 777 B
formatLicensePlate 1.2 KB 1.2 KB 0 B 738 B
formatNcm 1.2 KB 1.2 KB 0 B 780 B
formatNfeKey 1.3 KB 1.3 KB 0 B 783 B
formatPassport 1.0 KB 1.0 KB 0 B 643 B
formatPhone 2.8 KB 2.8 KB 0 B 1.5 KB
formatPis 1.3 KB 1.3 KB 0 B 781 B
formatProcessoJuridico 1.3 KB 1.3 KB 0 B 785 B
formatVoterId 1.3 KB 1.3 KB 0 B 821 B
generateBoleto 2.0 KB 2.0 KB 0 B 1.1 KB
generateCNPJ 1.6 KB 1.6 KB 0 B 965 B
generateCPF 1.4 KB 1.4 KB 0 B 878 B
generateCep 984 B 984 B 0 B 610 B
generateCnh 1.4 KB 1.4 KB 0 B 829 B
generateCnpj 1.6 KB 1.6 KB 0 B 965 B
generateCpf 1.4 KB 1.4 KB 0 B 878 B
generateLegalNature 5.9 KB 5.9 KB 0 B 2.1 KB
generateLicensePlate 1.1 KB 1.1 KB 0 B 692 B
generatePassport 1.1 KB 1.1 KB 0 B 656 B
generatePhone 1.5 KB 1.5 KB 0 B 900 B
generatePis 1.2 KB 1.2 KB 0 B 744 B
generatePixPayload 6.3 KB 6.3 KB 0 B 2.8 KB
generateProcessoJuridico 1.4 KB 1.4 KB 0 B 870 B
generateRenavam 1.2 KB 1.2 KB 0 B 760 B
generateVoterId 1.7 KB 1.7 KB 0 B 1021 B
getAddressInfoByCep 4.1 KB 4.1 KB 0 B 1.9 KB
getAreaCodeInfo 3.9 KB 3.9 KB 0 B 1.4 KB
getAreaCodesByState 1.6 KB 1.6 KB 0 B 917 B
getBankByCode 38.6 KB 38.6 KB 0 B 9.8 KB
getBankByIspb 38.6 KB 38.6 KB 0 B 9.8 KB
getBanks 38.4 KB 38.4 KB 0 B 9.6 KB
getBoletoInfo 3.1 KB 3.1 KB 0 B 1.6 KB
getCbo 119.1 KB 119.1 KB 0 B 30.7 KB
getCepInfoByAddress 2.7 KB 2.7 KB 0 B 1.4 KB
getCertidaoInfo 1.8 KB 1.8 KB 0 B 1.0 KB
getCfop 68.9 KB 68.9 KB 0 B 6.9 KB
getCities 154.3 KB 154.3 KB 0 B 49.9 KB
getCnae 93.9 KB 93.9 KB 0 B 21.2 KB
getFormatLicensePlate 1.1 KB 1.1 KB 0 B 692 B
getHolidays 6.1 KB 6.1 KB 0 B 2.6 KB
getIbanInfo 1.6 KB 1.6 KB 0 B 955 B
🟡 getLastBusinessDayOfMonth 7.2 KB 7.2 KB +43 B (+0.6%) 3.0 KB
getLegalNature 6.3 KB 6.3 KB 0 B 2.3 KB
getLegalNatures 5.9 KB 5.9 KB 0 B 2.1 KB
getLegalNaturesByCategory 6.5 KB 6.5 KB 0 B 2.4 KB
getMunicipalities 156.4 KB 156.4 KB 0 B 50.3 KB
getMunicipality 154.9 KB 154.9 KB 0 B 50.3 KB
getMunicipalityByCode 156.5 KB 156.5 KB 0 B 50.4 KB
🟡 getNextBusinessDay 7.3 KB 7.3 KB +43 B (+0.6%) 3.0 KB
getNfeKeyInfo 2.7 KB 2.7 KB 0 B 1.5 KB
🟡 getNthBusinessDay 7.2 KB 7.2 KB +43 B (+0.6%) 3.0 KB
getPixKeyInfo 4.5 KB 4.5 KB 0 B 2.0 KB
getPixPayloadInfo 2.9 KB 2.9 KB 0 B 1.4 KB
getStateByIbgeCode 3.2 KB 3.2 KB 0 B 1.1 KB
getStateCodeByName 3.2 KB 3.2 KB 0 B 1.1 KB
getStateNameByCode 3.1 KB 3.1 KB 0 B 1.0 KB
getStates 3.0 KB 3.0 KB 0 B 1017 B
getTimezoneByState 1.6 KB 1.6 KB 0 B 809 B
🟡 isBusinessDay 6.5 KB 6.6 KB +42 B (+0.6%) 2.8 KB
isHoliday 6.4 KB 6.4 KB 0 B 2.7 KB
isValidBankAccount 7.4 KB 7.4 KB 0 B 2.8 KB
isValidBoleto 2.4 KB 2.4 KB 0 B 1.3 KB
isValidCEP 984 B 984 B 0 B 610 B
isValidCNPJ 1.6 KB 1.6 KB 0 B 914 B
isValidCPF 1.3 KB 1.3 KB 0 B 805 B
isValidCaepf 1.5 KB 1.5 KB 0 B 913 B
isValidCbo 119.2 KB 119.2 KB 0 B 30.7 KB
isValidCei 1.5 KB 1.5 KB 0 B 898 B
isValidCep 984 B 984 B 0 B 610 B
isValidCertidao 1.6 KB 1.6 KB 0 B 938 B
isValidCfop 68.9 KB 68.9 KB 0 B 6.9 KB
isValidCnae 94.0 KB 94.0 KB 0 B 21.2 KB
isValidCnh 1.4 KB 1.4 KB 0 B 856 B
isValidCno 1.5 KB 1.5 KB 0 B 901 B
isValidCnpj 1.6 KB 1.6 KB 0 B 914 B
isValidCns 1.5 KB 1.5 KB 0 B 925 B
isValidCpf 1.3 KB 1.3 KB 0 B 805 B
isValidCreditCard 1.4 KB 1.4 KB 0 B 868 B
isValidCsosn 1.2 KB 1.2 KB 0 B 737 B
isValidCst 1.8 KB 1.8 KB 0 B 1.0 KB
isValidEmail 1.0 KB 1.0 KB 0 B 622 B
isValidIE 5.7 KB 5.7 KB 0 B 2.1 KB
isValidIban 1.3 KB 1.3 KB 0 B 836 B
isValidIe 5.7 KB 5.7 KB 0 B 2.1 KB
isValidLandlinePhone 1.5 KB 1.5 KB 0 B 932 B
isValidLegalNature 5.8 KB 5.8 KB 0 B 2.1 KB
isValidLicensePlate 1.1 KB 1.1 KB 0 B 702 B
isValidMobilePhone 1.6 KB 1.6 KB 0 B 971 B
isValidNcm 114.2 KB 114.2 KB 0 B 24.6 KB
isValidNfeKey 2.7 KB 2.7 KB 0 B 1.5 KB
isValidPIS 1.2 KB 1.2 KB 0 B 784 B
isValidPassport 1.0 KB 1.0 KB 0 B 654 B
isValidPhone 2.6 KB 2.6 KB 0 B 1.3 KB
isValidPis 1.2 KB 1.2 KB 0 B 784 B
isValidPixKey 4.6 KB 4.6 KB 0 B 2.1 KB
isValidPixPayload 2.9 KB 2.9 KB 0 B 1.5 KB
isValidProcessoJuridico 1.3 KB 1.3 KB 0 B 787 B
isValidRegistroProfissional 1.6 KB 1.6 KB 0 B 964 B
isValidRenavam 1.3 KB 1.3 KB 0 B 814 B
isValidServicePhone 1.5 KB 1.5 KB 0 B 846 B
isValidVin 1.6 KB 1.6 KB 0 B 995 B
isValidVoterId 1.6 KB 1.6 KB 0 B 900 B
parseBoleto 1020 B 1020 B 0 B 634 B
parseCaepf 1003 B 1003 B 0 B 621 B
parseCbo 1002 B 1002 B 0 B 620 B
parseCei 1003 B 1003 B 0 B 619 B
parseCep 1002 B 1002 B 0 B 620 B
parseCertidao 1003 B 1003 B 0 B 620 B
parseCfop 1002 B 1002 B 0 B 620 B
parseCnae 1002 B 1002 B 0 B 620 B
parseCnh 1003 B 1003 B 0 B 621 B
parseCno 1003 B 1003 B 0 B 619 B
parseCnpj 1.1 KB 1.1 KB 0 B 669 B
parseCns 1003 B 1003 B 0 B 621 B
parseCpf 1003 B 1003 B 0 B 621 B
parseCurrency 1.4 KB 1.4 KB 0 B 881 B
parseIban 1.0 KB 1.0 KB 0 B 638 B
parseLegalNature 1002 B 1002 B 0 B 620 B
parseLicensePlate 1.0 KB 1.0 KB 0 B 638 B
parseNcm 1002 B 1002 B 0 B 620 B
parseNfeKey 1.0 KB 1.0 KB 0 B 659 B
parsePassport 1.0 KB 1.0 KB 0 B 637 B
parsePhone 1.1 KB 1.1 KB 0 B 707 B
parsePis 1003 B 1003 B 0 B 621 B
parseProcessoJuridico 1003 B 1003 B 0 B 621 B
parseVoterId 1.0 KB 1.0 KB 0 B 649 B
removeAccents 953 B 953 B 0 B 593 B
🟡 subBusinessDays 7.3 KB 7.4 KB +43 B (+0.6%) 3.0 KB
How this is measured

Every export is imported alone into an esbuild consumer bundle (minified, tree-shaken) built from the head and from the base of this pull request; the sizes are the resulting bundles, gzip is their gzipped size. 🔴 marks a regression: a pre-existing export that grew more than 20% and more than 256 B, or the bundle importing every pre-existing export growing more than 5%. 🟡 is growth under the threshold, 🟢 a decrease, ⚪ no change, 🆕 an export that does not exist on the base (never a regression), 🗑️ an export that was removed. An intentional increase is accepted with the tree-shaking: accepted label.

@codecov

codecov Bot commented Sep 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (4a29787) to head (5619d05).

Additional details and impacted files
@@                      Coverage Diff                      @@
##           claude/business-day-helpers      #573   +/-   ##
=============================================================
  Coverage                       100.00%   100.00%           
=============================================================
  Files                              187       187           
  Lines                             2093      2097    +4     
  Branches                           622       624    +2     
=============================================================
+ Hits                              2093      2097    +4     
Flag Coverage Δ
node 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@hyanmandian
hyanmandian force-pushed the claude/business-day-saturdays branch from be1f445 to 3a4bb06 Compare September 19, 2026 14:43
@hyanmandian

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@hyanmandian

Copy link
Copy Markdown
Member Author

The Docstring Coverage pre-merge warning is a false positive here, declining it.

The one function it analysed is getHolidaysFor in src/is-business-day/is-business-day.test.ts. It is a test helper, it pre-dates this PR (the diff only moves lines around it), and this repository deliberately does not put JSDoc on test helpers: CONTRIBUTING.md says comments are "JSDoc on exported functions only", and vite.config.ts relaxes the oxlint jsdoc rules inside test files for exactly that reason.

Every exported function and every key of the exported type this PR touches does carry full JSDoc, including the new BusinessDayOptions.includeSaturday; the jsdoc plugin in npm run check and the API Extractor gate in npm run check:api both enforce that and both pass.

The business day family counts Monday to Friday minus holidays, which is the
banking count. The payroll deadline of CLT art. 459 § 1º ("até o quinto dia útil
do mês subsequente ao vencido") is not counted that way: labour inspection reads
it through Instrução Normativa MTP nº 2/2021, art. 14, I, "na contagem dos dias
será incluído o sábado, excluindo-se o domingo e o feriado, inclusive o
municipal", so the fifth business day of the labour count can fall a day before
the banking one.

includeSaturday is a new key on the shared BusinessDayOptions, so isBusinessDay,
addBusinessDays, subBusinessDays, differenceInBusinessDays, getNextBusinessDay,
getNthBusinessDay and getLastBusinessDayOfMonth all honour it. It defaults to
false, the current behaviour, so no existing call changes. With it on, Sunday
and holidays are still excluded, which means a holiday that falls on a Saturday
is still not a business day.

The one part of the article it cannot cover is "inclusive o municipal":
getHolidays carries national and state holidays only, and Lei 9.093/1995 art. 2º
leaves the municipal feriados religiosos to each municipality's own law. The
JSDoc and both docs say so instead of implying the option gives the full rule.

The weekday test also stops going through a module level Set, which the
tree-shaking rule in CONTRIBUTING.md asks modules to avoid.
@hyanmandian
hyanmandian force-pushed the claude/business-day-saturdays branch from 3a4bb06 to 5619d05 Compare September 19, 2026 17:35
@hyanmandian

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@hyanmandian
hyanmandian added this pull request to stack #577 September 19, 2026 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant