Skip to content

Add observed holidays substitution support#3289

Merged
arkid15r merged 3 commits intovacanza:devfrom
KJhellico:upd-observed-transfer
Feb 24, 2026
Merged

Add observed holidays substitution support#3289
arkid15r merged 3 commits intovacanza:devfrom
KJhellico:upd-observed-transfer

Conversation

@KJhellico
Copy link
Copy Markdown
Collaborator

Proposed change

Some countries (in particular, Azerbaijan, Kazakhstan, Russia) have a practice of transferring an additional non-working day, which occurs when holiday falls on weekend, from its usual date (Monday after this weekend) to a completely different date. This PR adds support for such cases. In this case, the "source" date can be either the date of the observed holiday (Azerbaijan, March 10, 2025 - "observed" March 8) or the date of the holiday itself (Russia, any New Year Holidays date).

Type of change

  • New country/market holidays support (thank you!)
  • Supported country/market holidays update (calendar discrepancy fix, localization)
  • Existing code/documentation/test/process quality improvement (best practice, cleanup, refactoring, optimization)
  • Dependency update (version deprecation/pin/upgrade)
  • Bugfix (non-breaking change which fixes an issue)
  • Breaking change (a code change causing existing functionality to break)
  • New feature (new holidays functionality in general)

Checklist

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 21, 2026

Summary by CodeRabbit

  • New Features

    • Constitution Day added for Russia (1994–2004)
  • Improvements

    • Unified labeling and handling of substituted/observed holidays across Russia, Azerbaijan, and Kazakhstan
    • Updated substituted/observed calendar entries (notably Azerbaijan 2025 and Kazakhstan 2020)
    • Adjusted weekend/substitution interaction for substituted holidays
  • Localization

    • Updated translations for observed-day format and Constitution Day (English, Russian, Thai)
  • Tests

    • Updated test expectations to match revised substitution behavior and labels

Walkthrough

Refactors substituted/observed holiday handling for Azerbaijan, Kazakhstan and Russia; adds Russia Constitution Day (1994–2004); updates core substituted-holiday logic; adjusts tests and snapshots to match new labeling and date mappings.

Changes

Cohort / File(s) Summary
Azerbaijan
holidays/countries/azerbaijan.py, tests/countries/test_azerbaijan.py, snapshots/countries/AZ_COMMON.json
Always add Women's Day and Eid al‑Fitr via helper calls; remove static observed attributes; expand 2025 special_public_holidays; update tests and snapshot labels for substituted/observed dates.
Kazakhstan
holidays/countries/kazakhstan.py, tests/countries/test_kazakhstan.py, snapshots/countries/KZ_COMMON.json
Always add Victory Day (removed year-based conditional); add MAY 8–11 substitution for 2020; remove 2020 observed mapping; update test expectation and snapshot label.
Russia
holidays/countries/russia.py, tests/countries/test_russia.py, snapshots/countries/RU_COMMON.json
Add observed_label; introduce Constitution Day (1994–2004); add many static holiday constants; extensively rework substituted/observed mappings (1991–2025); update tests and localized snapshot strings to use observed labels.
Core holiday handling
holidays/holiday_base.py
Change _add_special_holidays: only add source date to weekend_workdays when source is weekend and year/holiday conditions met; conditionally remove non-weekend substituted dates for current year.
Localization
holidays/locale/en_US/LC_MESSAGES/RU.po, holidays/locale/ru/LC_MESSAGES/RU.po, holidays/locale/th/LC_MESSAGES/RU.po
Add translation for observed format ("%s (выходной)" → "%s (observed)"); add Constitution Day translations; update PO metadata.
Tests & stubs
tests/common.py, tests/test_holiday_base.py
Remove weekend assertion in WorkingDayTests (retain is_working_day); add substituted Columbus Day test stub and _add_holiday_oct_12; update expectations for substituted dates.
Snapshots
snapshots/countries/AZ_COMMON.json, snapshots/countries/KZ_COMMON.json, snapshots/countries/RU_COMMON.json
Relabel several entries to use substituted-day wording or observed labels; AZ/KZ specific date label updates; RU mass relabeling and many inserted Constitution Day entries.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • arkid15r
  • PPsyrius
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding support for observed holidays substitution across multiple countries.
Description check ✅ Passed The description clearly explains the PR's purpose: supporting holiday substitutions when holidays fall on weekends in specific countries.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (322a1a3) to head (0643c53).
⚠️ Report is 2 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff            @@
##               dev     #3289   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          307       307           
  Lines        18373     18384   +11     
  Branches      2352      2353    +1     
=========================================
+ Hits         18373     18384   +11     

☔ View full report in Codecov by Sentry.
📢 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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@holidays/countries/russia.py`:
- Around line 127-155: The issue is a missing blank line between the constant
definition constitution_day and the following symbol special_public_holidays;
insert a single blank line after the constitution_day declaration (the tr("День
Конституции Российской Федерации") assignment) so it matches the surrounding
spacing style and separates it from the special_public_holidays block.

In `@holidays/holiday_base.py`:
- Around line 860-867: The current removal uses self.pop(from_date) which
deletes all holiday entries on that date; change it to only remove the
substituted holiday entry or pop the date only if it's the sole entry. Locate
the block with self._is_weekend(from_date) and the else branch that calls
self.pop(from_date), then replace the unconditional pop with logic that: (a)
inspects the existing entries for from_date (via self.get(from_date) or indexing
like self[from_date]) to determine if multiple holidays are present, (b) removes
only the specific holiday name/entry associated with the substitution, and (c)
falls back to self.pop(from_date) only when there is a single entry left; keep
use of self.weekend_workdays and existing year checks intact.

Co-authored-by: Panpakorn Siripanich <[email protected]>
Signed-off-by: ~Jhellico <[email protected]>
Copy link
Copy Markdown
Collaborator

@PPsyrius PPsyrius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🛠️

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
holidays/locale/th/LC_MESSAGES/RU.po (1)

88-91: Constitution Day translation already matches the prior suggestion.

msgstr "วันรัฐธรรมนูญสหพันธรัฐรัสเซีย" aligns with the existing reviewer suggestion and is a faithful translation of the Russian msgid.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@holidays/locale/th/LC_MESSAGES/RU.po` around lines 88 - 91, The translation
for the string with msgid "День Конституции Российской Федерации" already
matches the suggested translation and should be left unchanged: keep msgstr
"วันรัฐธรรมนูญสหพันธรัฐรัสเซีย" as-is and mark the change approved; also remove
the duplicate review comment to avoid redundant approvals.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@holidays/locale/th/LC_MESSAGES/RU.po`:
- Around line 88-91: The translation for the string with msgid "День Конституции
Российской Федерации" already matches the suggested translation and should be
left unchanged: keep msgstr "วันรัฐธรรมนูญสหพันธรัฐรัสเซีย" as-is and mark the
change approved; also remove the duplicate review comment to avoid redundant
approvals.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2282ef5 and 0643c53.

📒 Files selected for processing (1)
  • holidays/locale/th/LC_MESSAGES/RU.po

Copy link
Copy Markdown
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks cleaner 👍

@arkid15r arkid15r added this pull request to the merge queue Feb 24, 2026
Merged via the queue into vacanza:dev with commit 3120947 Feb 24, 2026
32 checks passed
@KJhellico KJhellico deleted the upd-observed-transfer branch February 24, 2026 09:57
@KJhellico KJhellico mentioned this pull request Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants