Skip to content

Add grammar & converter for Christian holidays#162

Merged
rlskoeser merged 4 commits into
developfrom
feature/christian-holidays
Apr 24, 2026
Merged

Add grammar & converter for Christian holidays#162
rlskoeser merged 4 commits into
developfrom
feature/christian-holidays

Conversation

@rlskoeser
Copy link
Copy Markdown
Member

@rlskoeser rlskoeser commented Apr 10, 2026

Adds a new grammar and converter for Christian holidays; both standalone and omnibus.

Adapted from code originally written from Hale/Eliot dataset project; converted & updated with help from OpenCode and Claude

Summary by CodeRabbit

  • New Features

    • Added support for parsing Christian liturgical and holiday dates (movable feasts like Easter/Pentecost and fixed holidays like Epiphany, St. Patrick’s), with optional years and preserved input labels
    • Added a Weekday enumeration for weekday representations
  • Tests

    • Expanded test coverage and added cases/modules for holiday/liturgical date parsing and integration with the combined parser

- Adapted from Hale/Eliot dataset code
- Converted with help from OpenCode and Claude
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

Warning

Rate limit exceeded

@rlskoeser has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 57 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 57 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e53cf959-bc8a-4055-b78b-3a406be45aa9

📥 Commits

Reviewing files that changed from the base of the PR and between b31a1ed and 5168ba5.

📒 Files selected for processing (3)
  • src/undate/converters/grammars/holidays.lark
  • src/undate/converters/holidays.py
  • tests/test_converters/test_holidays.py

Walkthrough

This PR adds Christian liturgical holiday parsing: a new holidays grammar and HolidayDateConverter, integrates it into the combined parser, adds a Weekday IntEnum and minor Date.weekday change, and provides comprehensive tests for fixed and movable feast parsing and behavior.

Changes

Cohort / File(s) Summary
Combined Parser Integration
src/undate/converters/combined.py, src/undate/converters/grammars/combined.lark
Register HolidayTransformer in the merged transformer and extend the combined start rule to include holidays__holiday_date via a relative import. Documentation string updated to list Christian liturgical dates.
Holiday Date Grammar
src/undate/converters/grammars/holidays.lark
New Lark grammar declaring holiday_date, movable_feast, fixed_date, and year tokens; regex tokens for many liturgical/movable and fixed holidays.
Holiday Date Converter
src/undate/converters/holidays.py
New converter HolidayDateConverter with HolidayTransformer that resolves fixed holidays via lookup and movable feasts via Easter + offsets using convertdate.holidays.easter(). parse() implemented; to_string() raises ValueError.
Date Utilities
src/undate/date.py
Added Weekday IntEnum (MONDAY=0 … SUNDAY=6) and ensured Date.weekday returns an int.
Tests
tests/test_converters/test_combined_parser.py, tests/test_converters/test_holidays.py
Added liturgical test cases to combined parser tests and a new test_holidays.py covering fixed/movable feasts, label preservation, year inference, weekday checks, error cases, and to_string behavior.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant Converter as HolidayDateConverter
    participant Parser as LarkParser
    participant Transformer as HolidayTransformer
    participant EasterCalc as convertdate.holidays
    participant Undate as Undate

    User->>Converter: parse("Easter 1916")
    Converter->>Parser: parse input with holidays.lark
    Parser->>Transformer: produce parse tree (movable_feast + year)
    Transformer->>EasterCalc: easter(1916)
    EasterCalc-->>Transformer: (month, day)
    Transformer->>Transformer: apply feast offset
    Transformer->>Undate: construct Undate(year, month, day)
    Undate-->>Converter: result
    Converter-->>User: return Undate
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • robcast
  • jdamerow
  • ColeDCrawford

Poem

🐰 With calendar hops and tiny feet,
I chase the feasts both fixed and fleet.
From Epiphany to Easter's day,
I parse the dates and leap away. 🥕📅

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.88% which is insufficient. The required threshold is 80.00%. 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 'Add grammar & converter for Christian holidays' accurately summarizes the main changes: introduction of a new grammar file (holidays.lark), a new converter (HolidayDateConverter), and integration into the combined parser.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/christian-holidays

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 Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.06%. Comparing base (78cbbbb) to head (5168ba5).
⚠️ Report is 11 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #162      +/-   ##
===========================================
+ Coverage    99.00%   99.06%   +0.05%     
===========================================
  Files           45       47       +2     
  Lines         2216     2356     +140     
===========================================
+ Hits          2194     2334     +140     
  Misses          22       22              

☔ 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: 1

🧹 Nitpick comments (2)
src/undate/converters/holidays.py (2)

49-50: Pass the holiday calendar explicitly.

HolidayTransformer declares calendar = Calendar.GREGORIAN, but holiday_date() currently relies on Undate's default by calling Undate(**parts). Passing calendar=self.calendar here makes the converter self-contained and avoids silent behavior changes if that default ever moves.

♻️ Suggested tweak
     def holiday_date(self, items):
         parts = self._get_date_parts(items)
-        return Undate(**parts)
+        return Undate(calendar=self.calendar, **parts)

Also applies to: 75-77

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

In `@src/undate/converters/holidays.py` around lines 49 - 50, HolidayTransformer
sets calendar = Calendar.GREGORIAN but holiday_date() (and the similar block
around the other occurrence) constructs Undate using Undate(**parts) which
relies on Undate's default; update those constructors to pass the transformer's
calendar explicitly (e.g., Undate(calendar=self.calendar, **parts)) so the
converter is self-contained and won't change behavior if Undate's default
calendar changes; locate this in the HolidayTransformer class and in the other
conversion site referenced and add calendar=self.calendar to the Undate(...)
calls.

10-12: Consider explicitly adding type stubs for convertdate to improve type-checking transparency.

While the CI workflow uses mypy --install-types, which should automatically fetch types-convertdate from typeshed, adding it to the check optional-dependencies group would make this requirement explicit and improve IDE/local development experience. You can either add "types-convertdate" to the check list in pyproject.toml, or rely on the auto-installation during CI—both approaches work, but explicit declaration is clearer for maintainability.

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

In `@src/undate/converters/holidays.py` around lines 10 - 12, Add an explicit
dependency on the convertdate type stubs so type-checking is deterministic:
update your project's optional-dependencies "check" group in pyproject.toml to
include "types-convertdate" (this relates to the import of convertdate/holidays
in src/undate/converters/holidays.py), or document that CI relies on mypy's
--install-types behavior; ensure the change is reflected in dependency metadata
so IDEs and local mypy runs pick up the types for convertdate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/undate/converters/grammars/holidays.lark`:
- Line 17: The grammar rule year: /\d{4}/ currently accepts "0000", which later
causes datetime.date(*holidays.easter(parts["year"])) in the movable-feast
resolver to raise ValueError; update the year rule to disallow "0000" (e.g. use
a regex that rejects all-zero year such as a negative lookahead or require the
first digit 1-9) so that inputs like "0000" fail during parsing rather than
during transformation.

---

Nitpick comments:
In `@src/undate/converters/holidays.py`:
- Around line 49-50: HolidayTransformer sets calendar = Calendar.GREGORIAN but
holiday_date() (and the similar block around the other occurrence) constructs
Undate using Undate(**parts) which relies on Undate's default; update those
constructors to pass the transformer's calendar explicitly (e.g.,
Undate(calendar=self.calendar, **parts)) so the converter is self-contained and
won't change behavior if Undate's default calendar changes; locate this in the
HolidayTransformer class and in the other conversion site referenced and add
calendar=self.calendar to the Undate(...) calls.
- Around line 10-12: Add an explicit dependency on the convertdate type stubs so
type-checking is deterministic: update your project's optional-dependencies
"check" group in pyproject.toml to include "types-convertdate" (this relates to
the import of convertdate/holidays in src/undate/converters/holidays.py), or
document that CI relies on mypy's --install-types behavior; ensure the change is
reflected in dependency metadata so IDEs and local mypy runs pick up the types
for convertdate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f81e7b2a-9863-49d0-a914-86a214cb91e9

📥 Commits

Reviewing files that changed from the base of the PR and between 60328de and 5fd7505.

📒 Files selected for processing (7)
  • src/undate/converters/combined.py
  • src/undate/converters/grammars/combined.lark
  • src/undate/converters/grammars/holidays.lark
  • src/undate/converters/holidays.py
  • src/undate/date.py
  • tests/test_converters/test_combined_parser.py
  • tests/test_converters/test_holidays.py

// holidays that are always on the same date
fixed_date: EPIPHANY | CANDLEMASS | ST_PATRICKS | ALL_FOOLS | ST_CYPRIANS

year: /\d{4}/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python - <<'PY'
import datetime

for year in (0, 1):
    try:
        print(year, datetime.date(year, 1, 1).isoformat())
    except Exception as exc:
        print(year, type(exc).__name__, exc)
PY

Repository: dh-tech/undate-python

Length of output: 113


🏁 Script executed:

# Find and examine the holidays.py file
fd -t f holidays.py

Repository: dh-tech/undate-python

Length of output: 137


🏁 Script executed:

# Look at the resolver code around the mentioned lines
find . -name "holidays.py" -type f | head -5 | xargs wc -l

Repository: dh-tech/undate-python

Length of output: 104


🏁 Script executed:

# Search for the resolver code that uses datetime.date
rg -A 5 -B 5 "datetime.date\|holidays.easter" --type py

Repository: dh-tech/undate-python

Length of output: 47


🏁 Script executed:

cat -n src/undate/converters/holidays.py | head -150

Repository: dh-tech/undate-python

Length of output: 6947


🏁 Script executed:

python - <<'PY'
from convertdate import holidays
import datetime

# Test what happens when calling holidays.easter(0)
for year in (0, 1, 9999, 10000):
    try:
        easter_result = holidays.easter(year)
        print(f"holidays.easter({year}) = {easter_result}")
        # Now try to create datetime.date with it
        try:
            d = datetime.date(*easter_result)
            print(f"  datetime.date(*{easter_result}) = {d.isoformat()}")
        except Exception as e:
            print(f"  datetime.date(*{easter_result}) raises {type(e).__name__}: {e}")
    except Exception as e:
        print(f"holidays.easter({year}) raises {type(e).__name__}: {e}")
PY

Repository: dh-tech/undate-python

Length of output: 188


🏁 Script executed:

# Find project configuration files
fd -t f -e "toml" -e "txt" -e "cfg" | grep -i "setup\|requirements\|pyproject"

Repository: dh-tech/undate-python

Length of output: 79


🏁 Script executed:

# Test datetime.date year boundaries
python - <<'PY'
import datetime

# Test valid year boundaries
test_years = [1, 9999, 10000, -1]
for year in test_years:
    try:
        d = datetime.date(year, 1, 1)
        print(f"datetime.date({year}, 1, 1) = {d.isoformat()}")
    except Exception as e:
        print(f"datetime.date({year}, 1, 1) raises {type(e).__name__}: {e}")
PY

Repository: dh-tech/undate-python

Length of output: 279


🏁 Script executed:

cat -n src/undate/converters/grammars/holidays.lark

Repository: dh-tech/undate-python

Length of output: 1407


Reject 0000 before it reaches the movable-feast calculation.

The grammar currently allows year: /\d{4}/ to match 0000, but the movable-feast resolver at line 127 uses datetime.date(*holidays.easter(parts["year"])), which only supports years 1–9999. Parsing inputs like Easter 0000 will therefore result in a ValueError at transformation time instead of a normal parse failure.

Grammar fix
-year: /\d{4}/
+year: /(?!0000)\d{4}/
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
year: /\d{4}/
year: /(?!0000)\d{4}/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/undate/converters/grammars/holidays.lark` at line 17, The grammar rule
year: /\d{4}/ currently accepts "0000", which later causes
datetime.date(*holidays.easter(parts["year"])) in the movable-feast resolver to
raise ValueError; update the year rule to disallow "0000" (e.g. use a regex that
rejects all-zero year such as a negative lookahead or require the first digit
1-9) so that inputs like "0000" fail during parsing rather than during
transformation.

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: 4

🧹 Nitpick comments (2)
src/undate/converters/holidays.py (2)

55-55: Remove commented-out code.

Several blocks of dead/commented-out code remain in HolidayTransformer (line 55 in year, lines 65–66 and 69–73 in fixed_date). Since a cleanup commit is already part of this PR, these should be dropped to keep the module tidy and avoid reader confusion about intent.

🧹 Proposed cleanup
     def year(self, items):
         value = "".join([str(i) for i in items])
         return Token("year", value)
-        # return Tree(data="year", children=[value])
     def fixed_date(self, items):
         item = items[0]
         holiday_name = item.type.split("__")[-1]
-        # token_type = item.type
-        # token type is holiday fixed-date name; use to determine month/day
         month, day = FIXED_HOLIDAYS.get(holiday_name)
         return Tree("fixed_date", [Token("month", month), Token("day", day)])
-        # for key in FIXED_HOLIDAYS:
-        #     if token_type == key or token_type == f"holidays__{key}":
-        #         month, day = FIXED_HOLIDAYS[key]
-        #         return Tree("fixed_date", [Token("month", month), Token("day", day)])
-        # raise ValueError(f"Unknown fixed holiday: {item.type}")

Also applies to: 65-73

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

In `@src/undate/converters/holidays.py` at line 55, Remove the leftover
commented-out code blocks inside the HolidayTransformer methods: delete the
commented "return Tree(data=\"year\", children=[value])" inside the year method
and remove the commented lines in fixed_date (the blocks around the earlier
commented logic and any commented returns). Keep the active logic untouched—only
delete the dead/commented code in HolidayTransformer.year and
HolidayTransformer.fixed_date so the module is tidy and behavior is unchanged.

112-114: Redundant str(field) cast.

field is assigned from child.type, which is already a str. The cast is a no-op.

♻️ Proposed cleanup
-            if field and value:
-                # currently all date parts are integer only
-                parts[str(field)] = int(value)
+            if field and value:
+                # currently all date parts are integer only
+                parts[field] = int(value)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/undate/converters/holidays.py` around lines 112 - 114, Remove the
redundant str() cast when assigning to the parts dict: in the block where field
is set from child.type and you do parts[str(field)] = int(value), change it to
parts[field] = int(value) (since field is already a str); update any nearby
comments if needed and run relevant unit tests for the converter
(functions/variables: field, child.type, parts) to ensure no behavior change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/undate/converters/holidays.py`:
- Around line 22-28: Rename the misspelled holiday key "CANDLEMASS" to
"CANDLEMAS" in the FIXED_HOLIDAYS dict and update all corresponding references
(grammar terminal in holidays.lark and any usages in code, tests, or parser
rules) to the single‑s spelling so the terminal name and dict key match; search
for "CANDLEMASS" across the repo and replace with "CANDLEMAS", then run relevant
tests/parsing to ensure no remaining references break.
- Around line 117-122: The branch handling movable_feast currently accesses
parts["year"] and raises a cryptic KeyError when year is missing; update the
movable feast handling (the code using movable_feast, MOVEABLE_FEASTS,
holidays.easter, and parts.update) to first check for a year in parts and either
raise a clear ValueError (e.g., "movable feast requires a year") or return a
partial Undate according to project semantics; ensure parse() still receives a
consistent exception type by documenting/wrapping this new error behavior (or
re-raising as ValueError) so consumers of parse() see the advertised ValueError
rather than KeyError.
- Around line 62-73: The fixed_date method calls
FIXED_HOLIDAYS.get(holiday_name) and unpacks its result without checking for
None, which causes an opaque TypeError when a terminal is missing; change
fixed_date (in the fixed_date method) to validate the lookup result from
FIXED_HOLIDAYS.get(holiday_name), and if None raise a clear ValueError
(including item.type and holiday_name in the message) so callers get a helpful
error, otherwise continue to return Tree("fixed_date", [Token("month", month),
Token("day", day)]) as before.
- Line 10: The mypy failure is caused by missing type stubs for the third‑party
module imported in the holidays.py file; fix it by either appending a per‑import
mypy ignore to the import statement (the line reading "from convertdate import
holidays") so mypy skips that specific import, or add a mypy config override
that targets module "convertdate" and "convertdate.*" with
ignore_missing_imports = true to silence missing stubs globally for that
package.

---

Nitpick comments:
In `@src/undate/converters/holidays.py`:
- Line 55: Remove the leftover commented-out code blocks inside the
HolidayTransformer methods: delete the commented "return Tree(data=\"year\",
children=[value])" inside the year method and remove the commented lines in
fixed_date (the blocks around the earlier commented logic and any commented
returns). Keep the active logic untouched—only delete the dead/commented code in
HolidayTransformer.year and HolidayTransformer.fixed_date so the module is tidy
and behavior is unchanged.
- Around line 112-114: Remove the redundant str() cast when assigning to the
parts dict: in the block where field is set from child.type and you do
parts[str(field)] = int(value), change it to parts[field] = int(value) (since
field is already a str); update any nearby comments if needed and run relevant
unit tests for the converter (functions/variables: field, child.type, parts) to
ensure no behavior change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 16e4af3b-4969-417d-968d-f652ee7960a2

📥 Commits

Reviewing files that changed from the base of the PR and between 5fd7505 and b31a1ed.

📒 Files selected for processing (1)
  • src/undate/converters/holidays.py

Comment thread src/undate/converters/holidays.py Outdated
Comment on lines +22 to +28
FIXED_HOLIDAYS = {
"EPIPHANY": (1, 6), # January 6
"CANDLEMASS": (2, 2), # February 2; 40th day & end of epiphany
"ST_PATRICKS": (3, 17), # March 17
"ALL_FOOLS": (4, 1), # All / April fools day, April 1
"ST_CYPRIANS": (9, 16), # St. Cyprian's Feast day: September 16
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Typo: "CANDLEMASS" should be "CANDLEMAS".

The feast is spelled Candlemas (single "s"). This terminal name is likely mirrored in holidays.lark, so both the grammar terminal and this key need updating to match.

✏️ Proposed fix
 FIXED_HOLIDAYS = {
     "EPIPHANY": (1, 6),  # January 6
-    "CANDLEMASS": (2, 2),  # February 2; 40th day & end of epiphany
+    "CANDLEMAS": (2, 2),  # February 2; 40th day & end of epiphany
     "ST_PATRICKS": (3, 17),  # March 17
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FIXED_HOLIDAYS = {
"EPIPHANY": (1, 6), # January 6
"CANDLEMASS": (2, 2), # February 2; 40th day & end of epiphany
"ST_PATRICKS": (3, 17), # March 17
"ALL_FOOLS": (4, 1), # All / April fools day, April 1
"ST_CYPRIANS": (9, 16), # St. Cyprian's Feast day: September 16
}
FIXED_HOLIDAYS = {
"EPIPHANY": (1, 6), # January 6
"CANDLEMAS": (2, 2), # February 2; 40th day & end of epiphany
"ST_PATRICKS": (3, 17), # March 17
"ALL_FOOLS": (4, 1), # All / April fools day, April 1
"ST_CYPRIANS": (9, 16), # St. Cyprian's Feast day: September 16
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/undate/converters/holidays.py` around lines 22 - 28, Rename the
misspelled holiday key "CANDLEMASS" to "CANDLEMAS" in the FIXED_HOLIDAYS dict
and update all corresponding references (grammar terminal in holidays.lark and
any usages in code, tests, or parser rules) to the single‑s spelling so the
terminal name and dict key match; search for "CANDLEMASS" across the repo and
replace with "CANDLEMAS", then run relevant tests/parsing to ensure no remaining
references break.

Comment thread src/undate/converters/holidays.py Outdated
Comment thread src/undate/converters/holidays.py
@rlskoeser rlskoeser merged commit 5ab3f6b into develop Apr 24, 2026
16 checks passed
@rlskoeser rlskoeser deleted the feature/christian-holidays branch April 24, 2026 16:10
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