# Changelog of US & Puerto Rico Holidays + Business Days API (`jbstudio/openday-api`) Actor

- **URL**: https://apify.com/jbstudio/openday-api/changelog.md
- **Full Actor documentation**: https://apify.com/jbstudio/openday-api.md

## Changelog

All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
[Semantic Versioning](https://semver.org/).

### \[Unreleased]

### \[0.8.0] - 2026-10-15

#### Added

- Puerto Rico toolkit:
  - `GET /v1/pr/municipios`: the 78 municipios (code, name, nameAscii, slug), from the US Census Bureau 2020 county FIPS codes.
  - `GET /v1/pr/municipios/{id}`: one municipio by code, name or slug. Accents and case do not matter.
  - `GET /v1/pr/zip/{zip}`: municipio(s) of a ZIP code, with the land-area share and the primary one marked, from the 2020 Census ZCTA to County relationship file.
  - `GET /v1/pr/ivu`: IVU rates citing the Código de Rentas Internas de 2011 (Sec. 4020.01(b), 4210.01(b), 4210.01(c) and 6080.14(a)), with a "not tax advice" note.
  - Batch names: `pr/municipios`, `pr/municipio`, `pr/zip`, `pr/ivu`. One `api-request` event per success, as with every endpoint.
- `scripts/build-pr-data.js` rebuilds `src/data/pr/` from the Census files.
- `meta.dataset` on Puerto Rico toolkit responses, with `verificationStatus: "official"`.

### \[0.7.2] - 2026-10-15

#### Fixed

- Actor batch mode: an empty input (`{}`), no `requests` or an empty list now runs the default sample (Puerto Rico 2027 holidays and one business-day check) instead of failing with an empty dataset. The input schema has a real `default` and no required fields. Invalid input still fails, but saves one `INVALID_INPUT` item first, so the dataset is never empty.

### \[0.7.0] - 2026-10-15

#### Added

- Actor output schema (batch results and live Standby API) and dataset schema with a "Results overview" view; batch items include a one-line `summary`.

### \[0.6.0] - 2026-10-15 (pre-release)

#### Added

- Apify Actor (`.actor/`): Standby mode serves the same Express app on the port Apify provides (readiness probe answered with a fast `200`); a normal run is batch mode over `input.requests` (up to 1,000 requests, one dataset item each, invalid items return the normal error shape).
- Pay-per-event billing (`src/services/billing.js`): one `api-request` event per successful request in both modes; never for errors, `/v1/health`, `/docs` or the readiness probe. No-op outside Apify. When the spending limit is reached, Standby returns `402 LIMIT_REACHED` and batch mode stops and marks the remaining items.
- Store listing (`.actor/README.md`), input schema with a sample input, and Dockerfile on the official Apify Node 24 image (non-root).
- `npm run start:actor` and a "Running on Apify" section in the README.

#### Changed

- Rebrand: **OpenDay API by JB Studio** ("OpenDay API: US & Puerto Rico Holidays + Business Days"). Package name `openday-api`, author JB Studio, new taglines (EN/ES), OpenAPI title, docs page title, and `service: "OpenDay API"` in `/v1/health`. Endpoint paths and response shapes are unchanged.
- Endpoint logic moved to shared handlers (`src/controllers/endpoints.js`) used by both the HTTP API and batch mode.
- Indiana's official May 4, 2027 Primary Election Day cites the official 2027 schedule; the README "Known gaps / notes" section (renamed) explains the 2027 date and the even-year rule from 2028.
- The patched `basic-ftp` 6.2.1 is pinned through npm `overrides` (a dependency of the Apify SDK); `npm audit` reports no vulnerabilities.

### \[0.5.1] - 2026-10-15 (pre-release)

#### Changed

- Data accuracy policy: years based on a practice shown on an official calendar (for example, Saturday holidays observed Friday) are now `projected`, with a note naming the official year: Alaska, Colorado, District of Columbia, Hawaii, Illinois, Missouri, North Carolina, Pennsylvania and Wyoming. Louisiana years after 2026 are `projected` (several days are set by yearly proclamation).
- Arkansas and Kansas: when Christmas falls on a Saturday, it rolls forward to Monday (Christmas Eve keeps Friday); those years are `projected` (2027: Monday, December 27).
- South Carolina: when Christmas falls on a Sunday, Christmas Eve moves to Friday, Christmas to Monday and the Day after Christmas to Tuesday; those years are `projected`.
- Indiana: Primary Election Day follows Indiana Code 3-10-1-3 (first Tuesday after the first Monday in May, even years), plus the official May 4, 2027 date.
- Mississippi Saturday holidays note that the Governor designates the observed day; New Jersey notes that Lincoln's Birthday is pending confirmation.

#### Added

- README sections "Data accuracy policy" and "Known gaps / pending research".
- Monday-to-Tuesday weekend action and a helper for years when Christmas falls on a given weekday.

### \[0.5.0] - 2026-10-15 (pre-release)

#### Added

- The remaining 40 states and the District of Columbia (`US-DC`): all 50 states and DC are now served, each with `state` (default) and `banking` calendars, 2026-2100.
- Jurisdiction rules from the research notes, including: Rhode Island (Saturday or Sunday to Monday), Massachusetts and Wisconsin (Saturday not moved), Arizona, Nevada, Minnesota, North Dakota and South Dakota (only listed fixed holidays move), Indiana (Monday-Friday dates), Utah's 2026-2027 Juneteenth and 4-hour Good Friday changes, Colorado's corrected MLK Day, South Carolina's year-end roll-forward, and unique days such as Seward's Day, Alaska Day, Prince Kuhio Day, Kamehameha Day, Statehood Day, Pioneer Day, Nevada Day, Family Day, Patriots' Day, Victory Day, Town Meeting Day, Bennington Battle Day, Truman Day, Arbor Day and D.C. Emancipation Day.
- Verification status `projected` for lists set each year by a governor or executive order (Georgia, Indiana, Kansas, New Mexico, Oklahoma), with a note; `GET /v1/regions` shows `verificationDefault` and `verificationDefaultNote` and a `yearsNote` for states and DC.
- Hebrew-calendar rule (Rosh Hashanah 1 Tishri, Yom Kippur 10 Tishri) using the built-in Intl Hebrew calendar; responses note that the observance begins at sundown the evening before.
- `halfDay` field and `category: "unit-specific"`; both are listed but do not change business-day math.
- Weekend actions Sunday to Tuesday and Tuesday-Friday to the preceding Monday; per-rule `lastYear`.

#### Changed (Step 3A review)

- Texas Rosh Hashanah and Yom Kippur are calculated for every year; Cesar Chavez Day added as optional.
- Florida legal-only days add Washington's Birthday, Columbus Day and Farmers' Day and General Election Day (even years); Mardi Gras stays out (local).
- North Carolina legal-only days add Washington's Birthday, Columbus Day, Election Day (even years) and Yom Kippur; after 2027 only Christmas Day is included, with an OSHR note.
- Illinois no longer moves a Saturday New Year's Day into the previous year (no Dec 31, 2027).
- Georgia years after 2027 are `projected`; Washington's Birthday moves back to Friday when the day before Christmas is a Sunday (also Indiana).
- Pennsylvania legal-only days cite 44 P.S. § 11.

### \[0.4.0] - 2026-10-15 (pre-release)

#### Added

- US state regions (`US-XX`, ISO 3166-2 style) for the 10 largest states: `US-CA`, `US-TX`, `US-FL`, `US-NY`, `US-PA`, `US-IL`, `US-OH`, `US-GA`, `US-NC`, `US-MI`. Each has a `state` calendar (default; state government employees) and a `banking` calendar (Federal Reserve schedule). State data covers 2026-2100.
- State data model, one file per state (`src/data/states/US-XX.js`): per-state weekend policy (`previousFriday` / `nextMonday` / `notMoved`) with per-holiday exceptions, year-specific official overrides, and verification status by year.
- New rule kinds: relative to another holiday (Georgia's Washington's Birthday, the day before observed Christmas) and listed dates (Texas Hebrew-calendar optional days).
- Weekend actions: Saturday to Monday, Sunday not moved, Sunday to Friday, Friday to Thursday (Michigan Christmas Eve / New Year's Eve).
- Holiday fields `paidDayOff`, `category` (`skeleton-crew`, `optional`, `floating`) and `hours` (partial day). These holidays are listed but do not change business-day math.
- `include=legal-only` for legal holidays that are not employee days off.
- `meta.verificationStatus` (`official` / `computed`) and `meta.verificationNote` on holiday and business-day endpoints.
- `GET /v1/regions`: every supported region with calendars, years, sources and verification status by year.
- `country` and `region` are accepted interchangeably on every endpoint.

#### Changed

- `GET /v1/is-business-day`: `holidays` lists every holiday on the date, including ones that do not close offices; `reason` is `holiday` only when a listed holiday closes offices.

### \[0.3.2] - 2026-10-15 (pre-release)

#### Changed

- Código Político Art. 387 (1 LPRA § 71) sources resolved. There is no free official online copy of the current consolidated text, so:
  - Ley 111-2014 (official enactment that amended Art. 387) keeps its OGP library link, with the note "amendment text; consolidated article omitted in this copy".
  - The full current text is cited from an unofficial reproduction (law.justia.com), `sourceType: "secondary-copy"`, note "unofficial reproduction of 1 LPRA § 71".
- PR legal holidays that rest on Art. 387 (and Election Day on the government calendar) now link to the 1 LPRA § 71 reproduction instead of having no link.
- The dead Código Político link was removed.
- Each entry in `meta.references` now has a `note` (or `null`).

### \[0.3.1] - 2026-10-15 (pre-release)

#### Breaking

- `GET /v1/is-business-day`: the single `holiday` field is removed. Use `holidays` (array of every holiday on the date; empty when none). No customers yet, so this is done before launch.

#### Added

- `sourceType` on every holiday: `official` or `secondary-copy`. The 2025 Puerto Rico memo (OATRH ME 23-2024) is a `secondary-copy`, because no official copy is online.
- `meta.sourceType` and `meta.references` (every document behind the calendar) on holiday and business-day endpoints.
- Official Puerto Rico law links from the OGP law library (bvirtualogp.pr.gov): Ley 26-2017 (Art. 2.05), Ley 111-2014 (amends Art. 387) and Ley 88-1969. The Código Político link is pending (the provided link returns 404).
- Central list of sources in `src/data/sources.js`.
- PR closures (July 3 and 24, 2026, still inactive) now carry `sourceType: "secondary-copy"` and a note with a second report.

#### Changed

- General Election Day on the PR government calendar cites Código Político Art. 387 (it is not in the Art. 2.05 list).
- `type` labels documented: `legal` for Puerto Rico legal holidays (on both PR calendars), `government` for days only Executive Branch employees get.

### \[0.3.0] - 2026-10-15

#### Added

- Puerto Rico (`region=PR` / `country=PR`) with three calendars:
  - `government` (default): Executive Branch holidays (Ley 26-2017 Art. 2.05 as amended; annual OATRH memo): all legal holidays plus American Citizenship Day, Juneteenth and José Celso Barbosa Day.
  - `legal`: legal holidays (Código Político Art. 387, 1 LPRA § 71; Ley 88-1969 for Día de la Raza), including Good Friday and General Election Day in election years.
  - `banking`: Federal Reserve settlement schedule, with a note that branches may also close on local holidays.
  - Weekend rule for `legal` and `government`: Sunday to the following Monday (Art. 387); Saturday not moved.
- Yearly official confirmations in `src/data/prOverrides.js`: OATRH ME 23-2024 (2025), ME 12-2026 (full 2027 calendar, 18 days). ME 14-2025 (2026) is recorded as unverified; the affected date carries the note "Pending official confirmation".
- Two Puerto Rico closures (July 3 and July 24, 2026) recorded as unverified and inactive.
- Easter calculation (Anonymous Gregorian algorithm) for Good Friday.
- `holidays` array in `GET /v1/is-business-day` listing every holiday on the date.
- `meta.calendarNote` on holiday and business-day endpoints.

#### Changed

- US banking calendar: Juneteenth starts in 2022, when the Federal Reserve first observed it (federal calendar unchanged, from 2021).
- US banking source link now points to the Federal Reserve Financial Services holiday schedule.
- Yearly overrides use one format: `{ year, calendar, holidayId, observedDate, source, sourceUrl, verified }`.

### \[0.2.0] - 2026-10-15

#### Added

- `calendar` parameter on all holiday and business-day endpoints:
  - `federal` (default): unchanged behavior.
  - `banking`: Federal Reserve Board holiday schedule. A Saturday holiday is not moved (`observedDate` is `null`, with a `note`); a Sunday holiday is observed Monday.
- `dateBasis` parameter on `GET /v1/holidays`: `actual` (default) or `observed` (holidays whose observed date falls in the year).
- `include=inauguration` (federal calendar only): Inauguration Day per 5 U.S.C. 6103(c), January 20 of every fourth year after 1965, Sunday moved to Monday, scoped to Washington, DC area federal employees. Counted in business-day math only when included.
- One-time closures (`src/data/closures.js`, type `closure`), applied to holiday lists and business-day math once verified against an official order. The list is empty in this release.
- Holiday fields `scope`, `sourceUrl` and `note`. Business-day responses include `calendar`. `meta` includes `calendar` and `sourceUrl` on holiday and business-day endpoints.
- Region data model with per-calendar rule membership, configurable weekend rules (including Sunday -> following Monday) and verified yearly overrides, ready for Puerto Rico (not public yet).

#### Changed

- Holiday rules moved from `src/data/federalHolidays.js` to `src/data/regions/us.js`; calculation moved to `src/services/calendarEngine.js`.
- `observedDate` can now be `null` (banking calendar Saturday holidays; Inauguration Day on a Saturday).
- ETags now also depend on the calendar and its sources.

### \[0.1.0] - 2026-10-15

#### Added

- Rule-based US federal holiday engine (5 U.S.C. 6103) for years 2000-2100: fixed-date and nth-weekday rules, Juneteenth from 2021.
- Observed-date rule (5 U.S.C. 6103(b); Executive Order 11582): Saturday to Friday, Sunday to Monday, including observed dates that fall in the previous year.
- English and Spanish holiday names.
- Business-day service: `isBusinessDay`, `addBusinessDays` (negative values supported), `businessDaysBetween`, `nextBusinessDay`, `previousBusinessDay`.
- Endpoints: `GET /v1/holidays`, `/v1/is-business-day`, `/v1/business-days/add`, `/v1/business-days/between`, `/v1/health`.
- Standard success (`data` / `meta`) and error (`error.code` / `message` / `details`) response formats, with input validation on every endpoint.
- `ETag` and `Cache-Control` headers on holiday lists, with `304 Not Modified` support.
- OpenAPI 3.1 spec (`openapi.yaml`) and interactive docs at `/docs`.
- Helmet security headers, CORS, 10 KB request body limit, structured JSON request logs with request IDs.
- Test suite (Node.js test runner) with coverage thresholds, ESLint, Prettier, and a GitHub Actions CI workflow.
