+
Skip to content

Conversation

PPsyrius
Copy link
Collaborator

@PPsyrius PPsyrius commented Oct 4, 2025

Proposed change

Note: Awaiting #2986 's merge.

  • Add Zurich's HALF_DAY, OPTIONAL category holidays.
  • Fixed up incorrect it l10n entries.
  • Add th l10n support for Switzerland.

Resolves #784 .

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

Copy link
Contributor

coderabbitai bot commented Oct 4, 2025

Summary by CodeRabbit

  • New Features

    • Added Zurich-specific holidays: Sechseläuten and Knabenschiessen (with historical rules and half-day/optional variants).
    • Introduced pre-holiday and bridge days (e.g., Day before Good Friday/Ascension, Bridge Holiday, Christmas Eve, New Year’s Eve) where applicable.
    • Enabled Thai (th) locale for Switzerland and expanded translations in de, en_US, fr, it, and uk.
  • Documentation

    • Updated Switzerland language support table to include Thai.
  • Tests

    • Added test coverage for new holidays and localizations.

Walkthrough

Adds Thai (th) to Switzerland supported languages; implements Zurich-specific holidays Sechseläuten and Knabenschiessen with public/half-day/optional handling and historical rules; updates README, snapshots, tests, and multiple locale PO files accordingly.

Changes

Cohort / File(s) Summary of changes
Core logic: Switzerland
holidays/countries/switzerland.py
Added th to supported_languages; introduced Zurich-specific holiday logic (Sechseläuten, Knabenschiessen), historical vernal equinox handling (1902–1951), new helper methods for ZH public/half-day/optional holidays, and added imports for observed-day helpers.
Tests
tests/countries/test_switzerland.py
Replaced CH(...) usage with Switzerland(...); added subdiv_half_day_holidays and subdiv_optional_holidays; added tests for Knabenschiessen and Sechseläuten (including historical cases) and Thai localization checks; updated assertions and test mappings.
Localizations (PO files)
holidays/locale/de/LC_MESSAGES/CH.po, holidays/locale/en_US/LC_MESSAGES/CH.po, holidays/locale/fr/LC_MESSAGES/CH.po, holidays/locale/it/LC_MESSAGES/CH.po, holidays/locale/th/LC_MESSAGES/CH.po, holidays/locale/uk/LC_MESSAGES/CH.po
Bumped PO metadata versions; added msgids/msgstrs for Knabenschiessen, Sechseläuten, several eve/bridge-day entries; added Thai translations in th PO.
Snapshots
snapshots/countries/CH_ZH.json
Large augmentation of Zurich snapshot data: many Sechseläuten and Knabenschiessen entries across years, Day-before and Bridge Holiday entries, and some consolidated multi-holiday labels.
Documentation
README.md
Added th to Switzerland supported languages row.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • KJhellico

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning Although issue #784 focused solely on introducing Zurich half-day holidays, this pull request also includes Thai localization support and corrections to Italian translation entries that exceed that scope. In addition the PR bumps metadata across all PO files, updates snapshots extensively, and adds broad test coverage for new locales unrelated to the original objective. These ancillary changes diverge from the half-day holiday feature requested in the linked issue. Consider splitting the Thai localization and bulk PO file updates into a separate pull request or referencing additional issues to keep the Zurich half-day holiday feature isolated to issue #784.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly and concisely states the primary updates to Switzerland’s holiday module by highlighting the addition of Zurich’s HALF_DAY and OPTIONAL categories and Thai localization support, which matches the core changes in the pull request.
Linked Issues Check ✅ Passed The implementation adds Sechseläuten and Knabenschiessen as HALF_DAY holidays for Zurich and correctly maps company holidays to the OPTIONAL category, fully satisfying the objectives laid out in issue #784.
Description Check ✅ Passed The description accurately outlines the key changes including adding Zurich’s HALF_DAY and OPTIONAL holidays, fixing Italian localization entries, and adding Thai language support, and these points directly reflect the changes in the pull request.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5603ded and a4a98c5.

📒 Files selected for processing (1)
  • holidays/countries/switzerland.py (3 hunks)
🧰 Additional context used
🧠 Learnings (23)
📚 Learning: 2025-03-19T16:54:58.657Z
Learnt from: PPsyrius
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:146-159
Timestamp: 2025-03-19T16:54:58.657Z
Learning: In the holidays library implementation, explicit holiday dates (like Diwali in Fiji) are only defined for historical years with official sources (2016-2025). Future dates beyond the explicitly defined range are automatically calculated by methods like `_add_diwali`, which provide approximations when official dates aren't yet available.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-07-09T20:27:37.760Z
Learnt from: KJhellico
PR: vacanza/holidays#2623
File: holidays/countries/christmas_island.py:110-112
Timestamp: 2025-07-09T20:27:37.760Z
Learning: In Christmas Island, ANZAC Day (April 25) follows the same observed holiday rules as other holidays, using the SAT_SUN_TO_NEXT_MON rule to move to Monday when it falls on a weekend. The implementation correctly uses `_add_observed` wrapper around `_add_anzac_day`.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-19T16:53:00.375Z
Learnt from: PPsyrius
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:185-188
Timestamp: 2025-03-19T16:53:00.375Z
Learning: In the Fiji holidays implementation, the `special_public_holidays_observed` dictionary in `FijiStaticHolidays` is only used for exceptions to the normal observance rules, not for documenting all holidays. Only 2019's Constitution Day needed a special entry as it didn't follow the standard patterns.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-28T05:42:12.777Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_indonesia.py:221-223
Timestamp: 2025-09-28T05:42:12.777Z
Learning: In tests/countries/test_indonesia.py, the manual set inclusion checks using get_named and years_found for Lunar New Year (test_lunar_new_year) and Vesak Day (test_vesak_day) are intentional and should remain until both holidays get their own `{insert}_no_estimated` flags implemented, rather than using standard harness assertions like assertHolidayName/assertNoHolidayName.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-29T15:15:05.919Z
Learnt from: KJhellico
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:171-183
Timestamp: 2025-03-29T15:15:05.919Z
Learning: In the Fiji holidays implementation, the maintainers are aware of the need to extend the MAWLID_DATES dictionary beyond 2025 when future official references become available, and will do so when appropriate. No suggestions about extending this dictionary should be made in future reviews.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-18T07:01:12.236Z
Learnt from: PPsyrius
PR: vacanza/holidays#2942
File: holidays/countries/south_africa.py:91-98
Timestamp: 2025-09-18T07:01:12.236Z
Learning: In the holidays library South Africa implementation, inline ternary operators for holiday name selection (like "Republic Day" if self._year >= 1961 else "Union Day") are intentionally kept inline rather than extracted to separate variables, as this structure is designed in preparation for future localization (l10n) support where the contextual relationship between conditions and translatable strings needs to be preserved.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T07:26:25.431Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: holidays/countries/south_africa.py:69-75
Timestamp: 2025-09-14T07:26:25.431Z
Learning: When reviewing historical holiday implementations in the vacanza/holidays repository, trust the maintainers' research and implementation decisions for specific historical edge cases, especially when they can provide sources like Wikipedia or other historical documentation that supports unusual or complex date calculation rules during specific time periods.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-08-03T13:48:11.910Z
Learnt from: KJhellico
PR: vacanza/holidays#2777
File: holidays/countries/gambia.py:120-122
Timestamp: 2025-08-03T13:48:11.910Z
Learning: When reviewing holiday implementations in the holidays library, defer to the maintainers' choice of start years for specific holiday policies, as they likely have access to more reliable primary sources and official documentation than what can be found through web searches.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T04:41:10.139Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_south_africa.py:22-22
Timestamp: 2025-09-14T04:41:10.139Z
Learning: South Africa's observed holiday system only started in 1995, so in tests/countries/test_south_africa.py, using years_non_observed=range(1995, 2050) is intentional to limit testing to years where observed holidays actually exist, improving both correctness and performance.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-07-09T21:16:35.145Z
Learnt from: KJhellico
PR: vacanza/holidays#2623
File: tests/countries/test_christmas_island.py:136-146
Timestamp: 2025-07-09T21:16:35.145Z
Learning: In Christmas Island's holiday implementation, the test_christmas_day method cannot use assertNoNonObservedHoliday because in some years observed Christmas Day overlaps with Boxing Day when both holidays are moved due to weekend conflicts, causing the standard non-observed holiday check to fail inappropriately.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-06-16T12:28:31.641Z
Learnt from: PPsyrius
PR: vacanza/holidays#2632
File: holidays/countries/solomon_islands.py:95-98
Timestamp: 2025-06-16T12:28:31.641Z
Learning: Library-wide holiday patterns and their optimizations should be handled at the base class level (like InternationalHolidays) rather than documenting workarounds in individual country modules. This maintains separation of concerns and avoids documentation duplication.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-07-02T18:17:53.342Z
Learnt from: KJhellico
PR: vacanza/holidays#2608
File: tests/countries/test_saint_vincent_and_the_grenadines.py:162-178
Timestamp: 2025-07-02T18:17:53.342Z
Learning: In the Saint Vincent and the Grenadines holidays implementation, New Year's Day is added without observed rules using `_add_new_years_day()` and should not include observed rule testing in its test method. Only holidays explicitly wrapped with `_add_observed()` have observed behavior.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-08-26T09:43:38.329Z
Learnt from: PPsyrius
PR: vacanza/holidays#2821
File: holidays/countries/tanzania.py:145-163
Timestamp: 2025-08-26T09:43:38.329Z
Learning: In the Tanzania holidays implementation, when multiple holidays fall on the same date (like Eid al-Fitr and Mwalimu Nyerere Day on 2007-10-14), the observed rule logic correctly applies to all holidays on that date. The SAT_SUN_TO_NEXT_MON_TUE rule for the first Eid day doesn't create issues with co-occurring holidays because in practice, such collisions occur on Sundays where both SAT_SUN_TO_NEXT_MON and SAT_SUN_TO_NEXT_MON_TUE rules yield identical results (both move to Monday).

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T04:36:25.108Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: holidays/countries/chile.py:121-123
Timestamp: 2025-09-14T04:36:25.108Z
Learning: In the Chile holidays implementation, the MON_ONLY observance rule correctly implements Law 20.983 for January 2. MON_ONLY is defined as ObservedRule({TUE: None, WED: None, THU: None, FRI: None, SAT: None, SUN: None}), which means when _add_observed() is called with MON_ONLY, it removes holidays that fall on Tuesday through Sunday (via self.pop(dt)) and only keeps holidays that fall on Monday. This perfectly implements the law that January 2 is only a holiday when January 1 falls on Sunday.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-23T10:11:50.465Z
Learnt from: KJhellico
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:63-70
Timestamp: 2025-03-23T10:11:50.465Z
Learning: In the holidays library, the `SAT_SUN_TO_NEXT_MON_TUE` rule is specifically used for consecutive holidays (like Christmas Day and Boxing Day) to ensure they're observed on separate weekdays (Monday and Tuesday) when they fall on weekends, while `SAT_SUN_TO_NEXT_MON` is used as the default rule for other holidays.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-06-18T10:26:50.180Z
Learnt from: PPsyrius
PR: vacanza/holidays#2642
File: holidays/countries/france.py:178-180
Timestamp: 2025-06-18T10:26:50.180Z
Learning: In the France holidays implementation, the _populate_subdiv_57_public_holidays() (Moselle) and _populate_subdiv_6ae_public_holidays() (Alsace) methods are functionally identical, both adding Good Friday (≥1893) and Saint Stephen's Day (≥1892) with the same legal references from August 16th, 1892. Therefore, for the deprecated "Alsace-Moselle" subdivision, calling either method produces the same result.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-06-18T10:58:28.058Z
Learnt from: PPsyrius
PR: vacanza/holidays#2642
File: holidays/countries/france.py:184-206
Timestamp: 2025-06-18T10:58:28.058Z
Learning: In the holidays library France implementation, creating shared private methods between subdivision-specific holiday population methods (like _populate_subdiv_57_public_holidays and _populate_subdiv_6ae_public_holidays) is not supported by the current framework architecture, so duplicate code between functionally identical subdivision methods should be left as-is.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-06-18T10:07:58.780Z
Learnt from: PPsyrius
PR: vacanza/holidays#2642
File: holidays/countries/french_southern_territories.py:41-44
Timestamp: 2025-06-18T10:07:58.780Z
Learning: Territorial holiday classes that inherit from parent countries (like HolidaysAX from Finland, HolidaysSJ from Norway, HolidaysTF from France) follow a standard pattern of silently overriding self.subdiv in their _populate_public_holidays() method without validation, as this ensures they always use the correct subdivision code for their territory regardless of user input.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-06-18T10:18:59.447Z
Learnt from: PPsyrius
PR: vacanza/holidays#2642
File: holidays/countries/france.py:178-182
Timestamp: 2025-06-18T10:18:59.447Z
Learning: In the France holidays implementation, deprecated subdivision names like "Alsace-Moselle" and "Saint-Barthélémy" are handled through explicit conditionals in _populate_public_holidays() that map them to their corresponding new subdivision-specific holiday population methods, providing backward compatibility while users transition to the new ISO codes.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T17:17:14.387Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py:209-209
Timestamp: 2025-09-14T17:17:14.387Z
Learning: In tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py, the explicit loop iteration pattern for subdivision-specific holiday checks (like Anniversary Day for TA subdivision) is intentionally preferred over using assertSubdivTa helper methods, as confirmed by PPsyrius.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-06-16T11:46:35.303Z
Learnt from: PPsyrius
PR: vacanza/holidays#2638
File: holidays/countries/svalbard_and_jan_mayen.py:26-32
Timestamp: 2025-06-16T11:46:35.303Z
Learning: When creating country holiday aliases that inherit from parent countries (like Svalbard and Jan Mayen from Norway, or Åland from Finland), it's standard practice to hardcode a specific subdivision code in the _populate methods since the subdivision codes for the parent country yield identical results. The Åland Islands implementation serves as the reference pattern for this approach.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-30T20:18:46.006Z
Learnt from: KJhellico
PR: vacanza/holidays#2386
File: holidays/countries/nepal.py:24-26
Timestamp: 2025-03-30T20:18:46.006Z
Learning: In the holidays library, country classes do not directly implement `_populate()`. Instead, they implement specialized methods like `_populate_public_holidays()`, and the base class `HolidayBase` handles the orchestration by calling these specialized methods.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-06-18T10:12:57.419Z
Learnt from: PPsyrius
PR: vacanza/holidays#2642
File: holidays/countries/france.py:178-182
Timestamp: 2025-06-18T10:12:57.419Z
Learning: In the France holidays implementation, subdivisions like "GES" and "Metropole" that covered multiple departments with different holiday rules are completely deprecated rather than aliased, because aliasing them to a subset (like Alsace-Moselle) would provide incomplete or incorrect holiday data for the other covered regions. Complete deprecation is preferred over partial/incorrect data coverage.

Applied to files:

  • holidays/countries/switzerland.py
🧬 Code graph analysis (1)
holidays/countries/switzerland.py (5)
holidays/calendars/gregorian.py (2)
  • _timedelta (37-42)
  • _get_nth_weekday_of_month (64-89)
holidays/groups/christian.py (4)
  • _add_holy_thursday (364-373)
  • _easter_sunday (105-109)
  • _add_christmas_eve (253-261)
  • _christmas_day (98-102)
holidays/groups/international.py (1)
  • _add_new_years_eve (192-201)
holidays/observed_holiday_base.py (3)
  • ObservedHolidayBase (102-256)
  • _move_holiday_forced (213-216)
  • _add_observed (144-197)
holidays/holiday_base.py (5)
  • _add_holiday (797-809)
  • _is_tuesday (850-851)
  • _is_wednesday (853-854)
  • _is_thursday (856-857)
  • _is_weekend (868-875)
🪛 Ruff (0.13.3)
holidays/countries/switzerland.py

737-737: Missing return type annotation for private function _populate_subdiv_zh_common

Add return type annotation: None

(ANN202)


763-763: Missing return type annotation for private function _populate_subdiv_zh_half_day_holidays

Add return type annotation: None

(ANN202)


773-773: Missing return type annotation for private function _populate_subdiv_zh_optional_holidays

Add return type annotation: None

(ANN202)

⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test Python 3.14 on windows-latest

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.

Copy link
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: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ab58ac2 and 4a4d206.

📒 Files selected for processing (11)
  • README.md (1 hunks)
  • holidays/countries/switzerland.py (3 hunks)
  • holidays/locale/de/LC_MESSAGES/CH.po (2 hunks)
  • holidays/locale/en_US/LC_MESSAGES/CH.po (2 hunks)
  • holidays/locale/fr/LC_MESSAGES/CH.po (2 hunks)
  • holidays/locale/it/LC_MESSAGES/CH.po (2 hunks)
  • holidays/locale/th/LC_MESSAGES/CH.po (1 hunks)
  • holidays/locale/uk/LC_MESSAGES/CH.po (2 hunks)
  • snapshots/countries/CH_ZH.json (1 hunks)
  • tests/countries/test_switzerland.py (23 hunks)
  • tests/test_utils.py (5 hunks)
🧰 Additional context used
🧠 Learnings (17)
📚 Learning: 2025-04-03T05:59:57.480Z
Learnt from: PPsyrius
PR: vacanza/holidays#2407
File: snapshots/countries/TL_COMMON.json:7-7
Timestamp: 2025-04-03T05:59:57.480Z
Learning: In the holidays project, snapshot files (like snapshots/countries/TL_COMMON.json) are auto-generated when running `make snapshot` and should not be manually edited. Semicolons (;) in holiday entries are used as separators when multiple holidays occur on the same date.

Applied to files:

  • snapshots/countries/CH_ZH.json
📚 Learning: 2025-04-05T04:47:27.213Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:52-64
Timestamp: 2025-04-05T04:47:27.213Z
Learning: For holiday tests in the vacanza/holidays project, structure tests by individual holidays rather than by years. Each test method should focus on a specific holiday and test it across multiple years (from start_year through 2050) using helper methods like `assertHolidayName`. For fixed holidays, use generators like `(f"{year}-01-01" for year in range(1991, 2051))`. For movable holidays, specify individual dates for specific years followed by a range check.

Applied to files:

  • tests/test_utils.py
  • tests/countries/test_switzerland.py
📚 Learning: 2025-09-18T03:19:23.722Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_algeria.py:28-30
Timestamp: 2025-09-18T03:19:23.722Z
Learning: In the vacanza/holidays project, tests now use self.start_year and self.end_year from the TestCase class instead of country-specific aliases (like DZ.start_year) for start_year and end_year references. This approach provides the test framework with better control over test year ranges rather than being tied to specific country start years.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-05-06T21:07:11.577Z
Learnt from: KJhellico
PR: vacanza/holidays#2530
File: tests/countries/test_andorra.py:23-28
Timestamp: 2025-05-06T21:07:11.577Z
Learning: In the holidays project, test methods for country holidays follow a standard form where year ranges are explicitly recreated in each test method rather than being stored as class variables, to maintain consistency across all country tests.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T06:49:06.217Z
Learnt from: PPsyrius
PR: vacanza/holidays#2386
File: tests/countries/test_nepal.py:499-536
Timestamp: 2025-04-05T06:49:06.217Z
Learning: In the holidays project, test files follow a dual testing approach: individual methods test specific holidays across multiple years, while comprehensive year-specific tests (e.g., `test_2025`) verify all holidays for a specific year in a single assertion. Both approaches serve different testing purposes and complement each other.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-09-14T16:03:13.558Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_barbados.py:21-23
Timestamp: 2025-09-14T16:03:13.558Z
Learning: In tests/countries/test_barbados.py, using years_non_observed=range(2000, 2024) is intentional because all observed holiday examples fall within 2001-2023, making this range appropriate for limiting testing to years where observed holidays actually exist in the test data.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:29:38.042Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:85-86
Timestamp: 2025-04-05T04:29:38.042Z
Learning: For testing holiday implementations in the vacanza/holidays repository, recommend using `from tests.common import CommonCountryTests` as the base class instead of directly using `unittest.TestCase` to maintain consistency with project conventions and leverage common test utilities.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-08-25T04:28:02.061Z
Learnt from: PPsyrius
PR: vacanza/holidays#2848
File: tests/countries/test_somalia.py:44-127
Timestamp: 2025-08-25T04:28:02.061Z
Learning: In the holidays library, Islamic holiday tests use `self.no_estimated_holidays = Country(years=years, islamic_show_estimated=False)` as the library-wide standard approach to simplify test cases. This pattern is intentional and preferred over testing estimated labels.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-09-14T16:05:55.205Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_iran.py:28-28
Timestamp: 2025-09-14T16:05:55.205Z
Learning: In tests/countries/test_iran.py, using years=(self.start_year - 1, 2102) in the no-holiday test is intentional because Iran uses the Persian Calendar which has specific supported year range constraints, and 2102 represents the upper limit of the Persian Calendar's supported range, not just an arbitrary far-future date.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-09-10T14:35:54.603Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_brazil.py:28-30
Timestamp: 2025-09-10T14:35:54.603Z
Learning: In the holidays project, the test_no_holidays method should test ALL supported_categories (via categories=CountryClass.supported_categories) rather than just the default PUBLIC category, to ensure comprehensive validation that no holidays exist before start_year across any supported category including OPTIONAL and subdivision categories.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:50:40.752Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:31-49
Timestamp: 2025-04-05T04:50:40.752Z
Learning: For Turkmenistan holiday tests, use this class structure: `class TestTurkmenistan(CommonCountryTests, TestCase)` with imports `from unittest import TestCase`, `from holidays.countries import Turkmenistan, TM, TKM`, and `from tests.common import CommonCountryTests`. Ensure to call `super().setUp()` in the setUp method.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-09-14T17:17:14.387Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py:209-209
Timestamp: 2025-09-14T17:17:14.387Z
Learning: In tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py, the explicit loop iteration pattern for subdivision-specific holiday checks (like Anniversary Day for TA subdivision) is intentionally preferred over using assertSubdivTa helper methods, as confirmed by PPsyrius.

Applied to files:

  • tests/countries/test_switzerland.py
📚 Learning: 2025-09-14T06:39:32.896Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_switzerland.py:22-23
Timestamp: 2025-09-14T06:39:32.896Z
Learning: In tests/countries/test_switzerland.py, the cls.full_range = range(1970, 2050) is intentionally hard-coded rather than using CH.start_year until a proper test case refactor is completed for Switzerland's implementation.

Applied to files:

  • tests/countries/test_switzerland.py
📚 Learning: 2025-06-18T10:07:58.780Z
Learnt from: PPsyrius
PR: vacanza/holidays#2642
File: holidays/countries/french_southern_territories.py:41-44
Timestamp: 2025-06-18T10:07:58.780Z
Learning: Territorial holiday classes that inherit from parent countries (like HolidaysAX from Finland, HolidaysSJ from Norway, HolidaysTF from France) follow a standard pattern of silently overriding self.subdiv in their _populate_public_holidays() method without validation, as this ensures they always use the correct subdivision code for their territory regardless of user input.

Applied to files:

  • tests/countries/test_switzerland.py
📚 Learning: 2025-06-18T17:01:58.067Z
Learnt from: PPsyrius
PR: vacanza/holidays#2642
File: tests/countries/test_wallis_and_futuna.py:19-23
Timestamp: 2025-06-18T17:01:58.067Z
Learning: In the vacanza/holidays repository, the standard pattern for test class setUpClass methods is `super().setUpClass(HolidayClass)` or `super().setUpClass(HolidayClass, years=...)` where HolidayClass is passed as the first argument. This is the correct signature that matches the CommonCountryTests.setUpClass method which accepts test_class as the first parameter after cls. Pylint warnings about parameter count mismatch are false positives when comparing against TestCase.setUpClass instead of the immediate parent CommonCountryTests.setUpClass.

Applied to files:

  • tests/countries/test_switzerland.py
📚 Learning: 2025-09-10T13:46:06.329Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_canada.py:745-747
Timestamp: 2025-09-10T13:46:06.329Z
Learning: In the vacanza/holidays test framework, assertion methods like assertNoSubdivNuOptionalHolidayName correctly accept multiple range objects as separate arguments, such as assertNoSubdivNuOptionalHolidayName(name, range(CA.start_year, 2000), range(2020, 2050)). This is the intended usage pattern and should not be "fixed" by splitting into separate calls.

Applied to files:

  • tests/countries/test_switzerland.py
📚 Learning: 2025-07-24T15:21:31.632Z
Learnt from: PPsyrius
PR: vacanza/holidays#2750
File: tests/countries/test_germany.py:46-46
Timestamp: 2025-07-24T15:21:31.632Z
Learning: In the holidays project test files, the standard method name for testing the absence of holidays is `test_no_holidays`, not more descriptive names like `test_no_holidays_before_1990`. This is a consistent naming convention across country test files like France and Germany.

Applied to files:

  • tests/countries/test_switzerland.py
🧬 Code graph analysis (3)
holidays/countries/switzerland.py (5)
holidays/calendars/gregorian.py (2)
  • _timedelta (37-42)
  • _get_nth_weekday_of_month (64-89)
holidays/groups/christian.py (1)
  • _easter_sunday (105-109)
holidays/observed_holiday_base.py (2)
  • ObservedHolidayBase (102-246)
  • _move_holiday (198-206)
holidays/holiday_base.py (1)
  • _add_holiday (797-809)
holidays/countries/japan.py (1)
  • _vernal_equinox_date (211-222)
tests/test_utils.py (1)
holidays/utils.py (5)
  • country_holidays (32-228)
  • CountryHoliday (316-333)
  • financial_holidays (231-313)
  • list_supported_countries (411-422)
  • list_supported_financial (426-437)
tests/countries/test_switzerland.py (2)
holidays/countries/switzerland.py (2)
  • Switzerland (27-761)
  • CH (764-765)
tests/common.py (4)
  • assertNoHolidayName (305-307)
  • assertHolidayName (198-202)
  • assertHolidayNameCount (258-260)
  • assertLocalizedHolidays (359-370)
🔇 Additional comments (26)
holidays/locale/it/LC_MESSAGES/CH.po (2)

16-16: Metadata updates look good.

Standard PO file metadata properly updated.

Also applies to: 18-19, 26-26


125-131: Appropriate handling of Zurich-specific holiday names.

Keeping the original German names for Knabenschiessen and Sechseläuten is consistent with how other region-specific Swiss holidays are handled in this file (e.g., "Jeûne genevois", "Restauration genevoise"). These are proper nouns for Zurich traditions without established Italian translations.

holidays/locale/de/LC_MESSAGES/CH.po (2)

16-26: Metadata updates look good.

Version bump, revision date, translator attribution, and generator version are all appropriately updated. The changes align with the PR's timeline and contributor information.


124-131: New holiday entries are correctly formatted.

The additions for Knabenschiessen and Sechseläuten follow the established pattern, with proper translator comments and empty msgstr values appropriate for the German source language. Both entries align with the PR's objective to add Zurich half-day holidays.

tests/test_utils.py (9)

15-15: Import addition looks good.

The defaultdict import is used correctly in the TestListLocalizedEntities class to collect entity-to-languages mappings.


42-53: Test coverage for year specifications is comprehensive.

The refactored tests cover single year, multiple years tuple, and range objects. Each test correctly verifies the years attribute matches the expected set.


54-64: Error handling tests are clear and correct.

The new test methods properly verify that NotImplementedError is raised for invalid country codes and subdivision codes.


66-69: Deprecation warning test is properly structured.

Using assertWarns(DeprecationWarning) is the correct approach, and the warning message verification ensures the deprecation notice is present.


79-97: Financial market tests mirror country tests appropriately.

The refactored tests for financial holidays follow the same pattern as country holidays, ensuring consistency across the test suite. Year specification and error handling coverage is complete.


105-126: Generalized helper method reduces code duplication effectively.

The _check_holidays_years helper elegantly consolidates year validation logic for both countries and financial markets. The dual checking approach (individual years + full range) ensures comprehensive coverage.


132-141: Parallel test structure for countries and financial markets is excellent.

Both test methods now use the same helper, ensuring consistent validation logic. The pytest skip decorators appropriately limit execution to the latest Python version for efficiency.


149-164: Locale collection logic is clean and efficient.

Using defaultdict to build the entity-to-languages mapping from locale directory structure is a solid approach. The path parsing (path.stem for entity, path.parts[-3] for locale) correctly extracts the needed information.


197-221: Entity verification tests are thorough and maintainable.

The tests verify both the presence of specific entities and that the total count matches the number of implementation files. This dual check ensures completeness and helps catch missing entities.

holidays/locale/uk/LC_MESSAGES/CH.po (2)

16-26: Header metadata updates are appropriate.

Version bump to 0.82, updated revision date, and X-Generator version reflect the current changes. Metadata is correctly formatted.


125-131: New Ukrainian translations added correctly.

Both "Knabenschiessen" and "Sechseläuten" have been transliterated to Ukrainian ("Кнабеншісен" and "Зексельйотен"). The entries follow the proper PO file format and are consistent with existing translations in the file.

tests/countries/test_switzerland.py (11)

25-35: Class setup refactoring improves clarity.

Replacing CH(...) with Switzerland(...) and introducing separate subdiv_half_day_holidays and subdiv_optional_holidays mappings makes the test structure more explicit and aligns with the new category-based holiday handling.


44-73: Holiday list now includes Zurich half-day holidays.

"Sechseläuten" and "Knabenschiessen" have been correctly added to the comprehensive holiday set. The alphabetical/chronological ordering is maintained.


105-112: Berchtold's Day test correctly references new optional holidays mapping.

The loop now uses self.subdiv_optional_holidays instead of the old subdiv_holidays_optional, maintaining consistency with the class setup changes.


237-242: Good Friday optional subdivision test updated correctly.

References to subdiv_optional_holidays are consistent with the refactoring.


279-284: Easter Monday optional subdivision test updated correctly.

Consistent usage of the new subdiv_optional_holidays mapping.


303-312: Labor Day now correctly tests HALF_DAY category for Solothurn.

The new subdiv_half_day_holidays mapping is used to verify that Labor Day is a half-day holiday in SO subdivision. This aligns with the new category structure.


378-383: Whit Monday optional subdivision test updated correctly.

Consistent with the pattern used for other optional holiday tests.


611-618: Saint Stephen's Day optional subdivision test updated correctly.

Proper usage of subdiv_optional_holidays for the optional subdivisions.


681-724: Knabenschiessen test is comprehensive.

The test correctly verifies:

  • Absence in non-ZH subdivisions
  • Presence in ZH subdivision for PUBLIC category (2 dates per year: Saturday and Sunday)
  • Presence in ZH subdivision for HALF_DAY category (1 date per year: Monday)
  • Specific date expectations for multiple years
  • Holiday count validation
  • Start year boundary (1899)

726-762: Sechseläuten test covers both modern and historical calculation methods.

The test correctly verifies:

  • Absence in non-ZH subdivisions
  • Presence only in HALF_DAY category for ZH
  • Modern calculation (3rd Monday in April, adjusted for Holy Week) from 1952 onwards
  • Historical calculation (1st Monday after Vernal Equinox) from 1902-1951
  • Specific date expectations for both periods
  • Start year boundary (1902)

Good attention to the two different calculation rules across different time periods.


774-926: Localization tests updated to include new holidays.

All localization tests (default, en_US, fr, it, th, uk) now include the expected dates and translations for "Sechseläuten" and "Knabenschiessen". The Thai localization test is a new addition and follows the same pattern as existing localization tests.

Note: Some localizations keep the original names (e.g., "Knabenschiessen" and "Sechseläuten" in en_US, fr, it), while others provide translations (e.g., Thai: "คนาเบนชิสเซน" and "เซ็กเซ่ะเล๊าเท่น", Ukrainian: "Кнабеншісен" and "Зексельйотен").

Copy link

codecov bot commented Oct 4, 2025

Codecov Report

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

Additional details and impacted files
@@            Coverage Diff            @@
##               dev     #2984   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          305       305           
  Lines        18003     18037   +34     
  Branches      2323      2329    +6     
=========================================
+ Hits         18003     18037   +34     

☔ 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.

@KJhellico
Copy link
Collaborator

According to this, Zurich also have half-day holiday (afternoon) on Christmas Eve and 1/4 day (?) holidays on Maundy Thursday, Ascension Eve and New Year's Eve. In addition, the rest of the day for some of them (3/4 of Maundy Thursday, 1/2 of Sechseläuten, Knabenschiessen, Christmas Eve) are "company holidays" (Betriebsferientage), which can be interpreted as OPTIONAL in our terms.
I don't know how best to approach "1/4 day". The simplest solution would be to just make it as HALF_DAY with a corresponding specification in the name (like "(from 1pm)" in some countries). We can go further and add the PARTIAL_DAY category. ;)
In v1, we should consider implementing holiday times as datetime instead of date.

@PPsyrius PPsyrius marked this pull request as draft October 6, 2025 02:28
@PPsyrius
Copy link
Collaborator Author

PPsyrius commented Oct 7, 2025

From https://www.stadt-zuerich.ch/de/politik-und-verwaltung/arbeiten-bei-der-stadt/gut-zu-wissen/ferien-urlaub/feiertage-betriebsferientage-bft.html

Betriebsferientage (BFT)
Als städtische Mitarbeitende haben Sie neben den übrigen Ferien Anspruch auf jährlich sechs Betriebsferientage. Wenn Sie diese nicht an den vom Stadtrat jährlich festgelegten Tagen beziehen können, weil der Betrieb aufrechterhalten werden muss, steht es Ihnen frei, sie als zusätzliche Ferientage individuell einzuziehen.

Company holidays (BFT)
As a municipal employee, you are entitled to six days of company holidays per year in addition to the other holidays. If you are unable to obtain these on the days set annually by the City Council because operations must be maintained, you are free to collect them individually as additional vacation days.

@KJhellico Maybe OPTIONAL cateogory instead? From what I understand these are supposedly full days in practice

@KJhellico
Copy link
Collaborator

Yes, for "Company holidays" OPTIONAL is the most accurate option.

@PPsyrius PPsyrius changed the title Update Switzerland holidays: add Zurich's HALF_DAY holidays, th l10n support Update Switzerland holidays: add Zurich's HALF_DAY, OPTIONAL holidays, th l10n support Oct 8, 2025
@PPsyrius PPsyrius marked this pull request as ready for review October 10, 2025 04:27
@PPsyrius PPsyrius requested a review from KJhellico October 10, 2025 04:27
Copy link
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

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 205f1af and cdcf76b.

📒 Files selected for processing (1)
  • holidays/countries/switzerland.py (3 hunks)
🧰 Additional context used
🧠 Learnings (15)
📚 Learning: 2025-03-19T16:54:58.657Z
Learnt from: PPsyrius
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:146-159
Timestamp: 2025-03-19T16:54:58.657Z
Learning: In the holidays library implementation, explicit holiday dates (like Diwali in Fiji) are only defined for historical years with official sources (2016-2025). Future dates beyond the explicitly defined range are automatically calculated by methods like `_add_diwali`, which provide approximations when official dates aren't yet available.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-07-09T20:27:37.760Z
Learnt from: KJhellico
PR: vacanza/holidays#2623
File: holidays/countries/christmas_island.py:110-112
Timestamp: 2025-07-09T20:27:37.760Z
Learning: In Christmas Island, ANZAC Day (April 25) follows the same observed holiday rules as other holidays, using the SAT_SUN_TO_NEXT_MON rule to move to Monday when it falls on a weekend. The implementation correctly uses `_add_observed` wrapper around `_add_anzac_day`.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-19T16:53:00.375Z
Learnt from: PPsyrius
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:185-188
Timestamp: 2025-03-19T16:53:00.375Z
Learning: In the Fiji holidays implementation, the `special_public_holidays_observed` dictionary in `FijiStaticHolidays` is only used for exceptions to the normal observance rules, not for documenting all holidays. Only 2019's Constitution Day needed a special entry as it didn't follow the standard patterns.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-28T05:42:12.777Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_indonesia.py:221-223
Timestamp: 2025-09-28T05:42:12.777Z
Learning: In tests/countries/test_indonesia.py, the manual set inclusion checks using get_named and years_found for Lunar New Year (test_lunar_new_year) and Vesak Day (test_vesak_day) are intentional and should remain until both holidays get their own `{insert}_no_estimated` flags implemented, rather than using standard harness assertions like assertHolidayName/assertNoHolidayName.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-29T15:15:05.919Z
Learnt from: KJhellico
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:171-183
Timestamp: 2025-03-29T15:15:05.919Z
Learning: In the Fiji holidays implementation, the maintainers are aware of the need to extend the MAWLID_DATES dictionary beyond 2025 when future official references become available, and will do so when appropriate. No suggestions about extending this dictionary should be made in future reviews.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-18T07:01:12.236Z
Learnt from: PPsyrius
PR: vacanza/holidays#2942
File: holidays/countries/south_africa.py:91-98
Timestamp: 2025-09-18T07:01:12.236Z
Learning: In the holidays library South Africa implementation, inline ternary operators for holiday name selection (like "Republic Day" if self._year >= 1961 else "Union Day") are intentionally kept inline rather than extracted to separate variables, as this structure is designed in preparation for future localization (l10n) support where the contextual relationship between conditions and translatable strings needs to be preserved.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T07:26:25.431Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: holidays/countries/south_africa.py:69-75
Timestamp: 2025-09-14T07:26:25.431Z
Learning: When reviewing historical holiday implementations in the vacanza/holidays repository, trust the maintainers' research and implementation decisions for specific historical edge cases, especially when they can provide sources like Wikipedia or other historical documentation that supports unusual or complex date calculation rules during specific time periods.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-08-03T13:48:11.910Z
Learnt from: KJhellico
PR: vacanza/holidays#2777
File: holidays/countries/gambia.py:120-122
Timestamp: 2025-08-03T13:48:11.910Z
Learning: When reviewing holiday implementations in the holidays library, defer to the maintainers' choice of start years for specific holiday policies, as they likely have access to more reliable primary sources and official documentation than what can be found through web searches.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T04:41:10.139Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_south_africa.py:22-22
Timestamp: 2025-09-14T04:41:10.139Z
Learning: South Africa's observed holiday system only started in 1995, so in tests/countries/test_south_africa.py, using years_non_observed=range(1995, 2050) is intentional to limit testing to years where observed holidays actually exist, improving both correctness and performance.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-07-09T21:16:35.145Z
Learnt from: KJhellico
PR: vacanza/holidays#2623
File: tests/countries/test_christmas_island.py:136-146
Timestamp: 2025-07-09T21:16:35.145Z
Learning: In Christmas Island's holiday implementation, the test_christmas_day method cannot use assertNoNonObservedHoliday because in some years observed Christmas Day overlaps with Boxing Day when both holidays are moved due to weekend conflicts, causing the standard non-observed holiday check to fail inappropriately.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-06-16T12:28:31.641Z
Learnt from: PPsyrius
PR: vacanza/holidays#2632
File: holidays/countries/solomon_islands.py:95-98
Timestamp: 2025-06-16T12:28:31.641Z
Learning: Library-wide holiday patterns and their optimizations should be handled at the base class level (like InternationalHolidays) rather than documenting workarounds in individual country modules. This maintains separation of concerns and avoids documentation duplication.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-07-02T18:17:53.342Z
Learnt from: KJhellico
PR: vacanza/holidays#2608
File: tests/countries/test_saint_vincent_and_the_grenadines.py:162-178
Timestamp: 2025-07-02T18:17:53.342Z
Learning: In the Saint Vincent and the Grenadines holidays implementation, New Year's Day is added without observed rules using `_add_new_years_day()` and should not include observed rule testing in its test method. Only holidays explicitly wrapped with `_add_observed()` have observed behavior.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-08-26T09:43:38.329Z
Learnt from: PPsyrius
PR: vacanza/holidays#2821
File: holidays/countries/tanzania.py:145-163
Timestamp: 2025-08-26T09:43:38.329Z
Learning: In the Tanzania holidays implementation, when multiple holidays fall on the same date (like Eid al-Fitr and Mwalimu Nyerere Day on 2007-10-14), the observed rule logic correctly applies to all holidays on that date. The SAT_SUN_TO_NEXT_MON_TUE rule for the first Eid day doesn't create issues with co-occurring holidays because in practice, such collisions occur on Sundays where both SAT_SUN_TO_NEXT_MON and SAT_SUN_TO_NEXT_MON_TUE rules yield identical results (both move to Monday).

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T04:36:25.108Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: holidays/countries/chile.py:121-123
Timestamp: 2025-09-14T04:36:25.108Z
Learning: In the Chile holidays implementation, the MON_ONLY observance rule correctly implements Law 20.983 for January 2. MON_ONLY is defined as ObservedRule({TUE: None, WED: None, THU: None, FRI: None, SAT: None, SUN: None}), which means when _add_observed() is called with MON_ONLY, it removes holidays that fall on Tuesday through Sunday (via self.pop(dt)) and only keeps holidays that fall on Monday. This perfectly implements the law that January 2 is only a holiday when January 1 falls on Sunday.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-23T10:11:50.465Z
Learnt from: KJhellico
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:63-70
Timestamp: 2025-03-23T10:11:50.465Z
Learning: In the holidays library, the `SAT_SUN_TO_NEXT_MON_TUE` rule is specifically used for consecutive holidays (like Christmas Day and Boxing Day) to ensure they're observed on separate weekdays (Monday and Tuesday) when they fall on weekends, while `SAT_SUN_TO_NEXT_MON` is used as the default rule for other holidays.

Applied to files:

  • holidays/countries/switzerland.py
🧬 Code graph analysis (1)
holidays/countries/switzerland.py (3)
holidays/calendars/gregorian.py (2)
  • _timedelta (37-42)
  • _get_nth_weekday_of_month (64-89)
holidays/observed_holiday_base.py (3)
  • ObservedHolidayBase (102-256)
  • _move_holiday_forced (213-216)
  • _add_observed (144-197)
holidays/holiday_base.py (5)
  • _add_holiday (797-809)
  • _is_tuesday (850-851)
  • _is_wednesday (853-854)
  • _is_thursday (856-857)
  • _is_weekend (868-875)
🪛 Ruff (0.13.3)
holidays/countries/switzerland.py

737-737: Missing return type annotation for private function _populate_subdiv_zh_common_holidays

Add return type annotation: None

(ANN202)


763-763: Missing return type annotation for private function _populate_subdiv_zh_half_day_holidays

Add return type annotation: None

(ANN202)


773-773: Missing return type annotation for private function _populate_subdiv_zh_optional_holidays

Add return type annotation: None

(ANN202)


799-799: Docstring contains ambiguous (EN DASH). Did you mean - (HYPHEN-MINUS)?

(RUF002)

⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test Python 3.13 on windows-latest
  • GitHub Check: Test Python 3.14 on windows-latest
🔇 Additional comments (6)
holidays/countries/switzerland.py (6)

15-25: LGTM!

Import additions support the new Zurich holiday calculations and observed rules correctly.


107-107: LGTM!

Thai language support added as documented in PR objectives.


33-37: LGTM!

Reference documentation properly cites sources for Zurich holidays and vernal equinox data.


728-732: LGTM!

Knabenschiessen correctly added to Zurich public holidays for both Saturday (day before) and Sunday (2nd Sunday of September) starting from 1899.


763-771: LGTM!

Half-day holidays correctly include Knabenschiessen Monday and day before Ascension Day, with proper delegation to common holidays.


773-795: LGTM!

Optional holidays correctly implement Betriebsferientage (company holiday) conditional logic, ensuring total days remain within policy limits based on Christmas day placement and weekend exclusions.

Copy link
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: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 205f1af and cdcf76b.

📒 Files selected for processing (1)
  • holidays/countries/switzerland.py (3 hunks)
🧰 Additional context used
🧠 Learnings (15)
📚 Learning: 2025-03-19T16:54:58.657Z
Learnt from: PPsyrius
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:146-159
Timestamp: 2025-03-19T16:54:58.657Z
Learning: In the holidays library implementation, explicit holiday dates (like Diwali in Fiji) are only defined for historical years with official sources (2016-2025). Future dates beyond the explicitly defined range are automatically calculated by methods like `_add_diwali`, which provide approximations when official dates aren't yet available.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-07-09T20:27:37.760Z
Learnt from: KJhellico
PR: vacanza/holidays#2623
File: holidays/countries/christmas_island.py:110-112
Timestamp: 2025-07-09T20:27:37.760Z
Learning: In Christmas Island, ANZAC Day (April 25) follows the same observed holiday rules as other holidays, using the SAT_SUN_TO_NEXT_MON rule to move to Monday when it falls on a weekend. The implementation correctly uses `_add_observed` wrapper around `_add_anzac_day`.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-19T16:53:00.375Z
Learnt from: PPsyrius
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:185-188
Timestamp: 2025-03-19T16:53:00.375Z
Learning: In the Fiji holidays implementation, the `special_public_holidays_observed` dictionary in `FijiStaticHolidays` is only used for exceptions to the normal observance rules, not for documenting all holidays. Only 2019's Constitution Day needed a special entry as it didn't follow the standard patterns.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-28T05:42:12.777Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_indonesia.py:221-223
Timestamp: 2025-09-28T05:42:12.777Z
Learning: In tests/countries/test_indonesia.py, the manual set inclusion checks using get_named and years_found for Lunar New Year (test_lunar_new_year) and Vesak Day (test_vesak_day) are intentional and should remain until both holidays get their own `{insert}_no_estimated` flags implemented, rather than using standard harness assertions like assertHolidayName/assertNoHolidayName.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-29T15:15:05.919Z
Learnt from: KJhellico
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:171-183
Timestamp: 2025-03-29T15:15:05.919Z
Learning: In the Fiji holidays implementation, the maintainers are aware of the need to extend the MAWLID_DATES dictionary beyond 2025 when future official references become available, and will do so when appropriate. No suggestions about extending this dictionary should be made in future reviews.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-18T07:01:12.236Z
Learnt from: PPsyrius
PR: vacanza/holidays#2942
File: holidays/countries/south_africa.py:91-98
Timestamp: 2025-09-18T07:01:12.236Z
Learning: In the holidays library South Africa implementation, inline ternary operators for holiday name selection (like "Republic Day" if self._year >= 1961 else "Union Day") are intentionally kept inline rather than extracted to separate variables, as this structure is designed in preparation for future localization (l10n) support where the contextual relationship between conditions and translatable strings needs to be preserved.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T07:26:25.431Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: holidays/countries/south_africa.py:69-75
Timestamp: 2025-09-14T07:26:25.431Z
Learning: When reviewing historical holiday implementations in the vacanza/holidays repository, trust the maintainers' research and implementation decisions for specific historical edge cases, especially when they can provide sources like Wikipedia or other historical documentation that supports unusual or complex date calculation rules during specific time periods.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-08-03T13:48:11.910Z
Learnt from: KJhellico
PR: vacanza/holidays#2777
File: holidays/countries/gambia.py:120-122
Timestamp: 2025-08-03T13:48:11.910Z
Learning: When reviewing holiday implementations in the holidays library, defer to the maintainers' choice of start years for specific holiday policies, as they likely have access to more reliable primary sources and official documentation than what can be found through web searches.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T04:41:10.139Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_south_africa.py:22-22
Timestamp: 2025-09-14T04:41:10.139Z
Learning: South Africa's observed holiday system only started in 1995, so in tests/countries/test_south_africa.py, using years_non_observed=range(1995, 2050) is intentional to limit testing to years where observed holidays actually exist, improving both correctness and performance.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-07-09T21:16:35.145Z
Learnt from: KJhellico
PR: vacanza/holidays#2623
File: tests/countries/test_christmas_island.py:136-146
Timestamp: 2025-07-09T21:16:35.145Z
Learning: In Christmas Island's holiday implementation, the test_christmas_day method cannot use assertNoNonObservedHoliday because in some years observed Christmas Day overlaps with Boxing Day when both holidays are moved due to weekend conflicts, causing the standard non-observed holiday check to fail inappropriately.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-06-16T12:28:31.641Z
Learnt from: PPsyrius
PR: vacanza/holidays#2632
File: holidays/countries/solomon_islands.py:95-98
Timestamp: 2025-06-16T12:28:31.641Z
Learning: Library-wide holiday patterns and their optimizations should be handled at the base class level (like InternationalHolidays) rather than documenting workarounds in individual country modules. This maintains separation of concerns and avoids documentation duplication.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-07-02T18:17:53.342Z
Learnt from: KJhellico
PR: vacanza/holidays#2608
File: tests/countries/test_saint_vincent_and_the_grenadines.py:162-178
Timestamp: 2025-07-02T18:17:53.342Z
Learning: In the Saint Vincent and the Grenadines holidays implementation, New Year's Day is added without observed rules using `_add_new_years_day()` and should not include observed rule testing in its test method. Only holidays explicitly wrapped with `_add_observed()` have observed behavior.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-08-26T09:43:38.329Z
Learnt from: PPsyrius
PR: vacanza/holidays#2821
File: holidays/countries/tanzania.py:145-163
Timestamp: 2025-08-26T09:43:38.329Z
Learning: In the Tanzania holidays implementation, when multiple holidays fall on the same date (like Eid al-Fitr and Mwalimu Nyerere Day on 2007-10-14), the observed rule logic correctly applies to all holidays on that date. The SAT_SUN_TO_NEXT_MON_TUE rule for the first Eid day doesn't create issues with co-occurring holidays because in practice, such collisions occur on Sundays where both SAT_SUN_TO_NEXT_MON and SAT_SUN_TO_NEXT_MON_TUE rules yield identical results (both move to Monday).

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-09-14T04:36:25.108Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: holidays/countries/chile.py:121-123
Timestamp: 2025-09-14T04:36:25.108Z
Learning: In the Chile holidays implementation, the MON_ONLY observance rule correctly implements Law 20.983 for January 2. MON_ONLY is defined as ObservedRule({TUE: None, WED: None, THU: None, FRI: None, SAT: None, SUN: None}), which means when _add_observed() is called with MON_ONLY, it removes holidays that fall on Tuesday through Sunday (via self.pop(dt)) and only keeps holidays that fall on Monday. This perfectly implements the law that January 2 is only a holiday when January 1 falls on Sunday.

Applied to files:

  • holidays/countries/switzerland.py
📚 Learning: 2025-03-23T10:11:50.465Z
Learnt from: KJhellico
PR: vacanza/holidays#2354
File: holidays/countries/fiji.py:63-70
Timestamp: 2025-03-23T10:11:50.465Z
Learning: In the holidays library, the `SAT_SUN_TO_NEXT_MON_TUE` rule is specifically used for consecutive holidays (like Christmas Day and Boxing Day) to ensure they're observed on separate weekdays (Monday and Tuesday) when they fall on weekends, while `SAT_SUN_TO_NEXT_MON` is used as the default rule for other holidays.

Applied to files:

  • holidays/countries/switzerland.py
🧬 Code graph analysis (1)
holidays/countries/switzerland.py (5)
holidays/calendars/gregorian.py (2)
  • _timedelta (37-42)
  • _get_nth_weekday_of_month (64-89)
holidays/groups/christian.py (4)
  • _add_holy_thursday (364-373)
  • _easter_sunday (105-109)
  • _add_christmas_eve (253-261)
  • _christmas_day (98-102)
holidays/groups/international.py (1)
  • _add_new_years_eve (192-201)
holidays/observed_holiday_base.py (3)
  • ObservedHolidayBase (102-256)
  • _move_holiday_forced (213-216)
  • _add_observed (144-197)
holidays/holiday_base.py (5)
  • _add_holiday (797-809)
  • _is_tuesday (850-851)
  • _is_wednesday (853-854)
  • _is_thursday (856-857)
  • _is_weekend (868-875)
🪛 Ruff (0.13.3)
holidays/countries/switzerland.py

737-737: Missing return type annotation for private function _populate_subdiv_zh_common_holidays

Add return type annotation: None

(ANN202)


763-763: Missing return type annotation for private function _populate_subdiv_zh_half_day_holidays

Add return type annotation: None

(ANN202)


773-773: Missing return type annotation for private function _populate_subdiv_zh_optional_holidays

Add return type annotation: None

(ANN202)


799-799: Docstring contains ambiguous (EN DASH). Did you mean - (HYPHEN-MINUS)?

(RUF002)

⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test build on macos-latest
  • GitHub Check: Test build on ubuntu-latest
  • GitHub Check: Test docs build

KJhellico
KJhellico previously approved these changes Oct 10, 2025
Copy link
Collaborator

@KJhellico KJhellico left a comment

Choose a reason for hiding this comment

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

LGTM! 👍

Copy link
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.

LGTM

@arkid15r arkid15r enabled auto-merge October 11, 2025 01:50
Copy link

@arkid15r arkid15r added this pull request to the merge queue Oct 11, 2025
Merged via the queue into vacanza:dev with commit ad444fb Oct 11, 2025
36 checks passed
@PPsyrius PPsyrius deleted the swiss_zurich_halfday_holidays branch October 11, 2025 08:46
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.

Zurich half-day holidays in Switzerland

3 participants

点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载