Skip to content

Conversation

rlskoeser
Copy link
Member

@rlskoeser rlskoeser commented Aug 29, 2025

this is to address bug reported in #140 - durations for non-Gregorian months were being calculated as uncertain when they are in fact known

Summary by CodeRabbit

  • New Features

    • Enhanced handling of non-Gregorian calendars for year and month logic.
    • Partially known years now produce computed ranges; fully known years return a single value; clearer error for completely unknown years.
    • Month durations derived from original calendar inputs, returning exact or uncertain lengths as appropriate.
  • Bug Fixes

    • Corrected month-length calculations for Hebrew, Islamic, and Seleucid calendars across varying years.
  • Tests

    • Added comprehensive tests for possible_years and duration behaviors in non-Gregorian calendars.

Copy link
Contributor

coderabbitai bot commented Aug 29, 2025

Warning

Rate limit exceeded

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between c48a6c6 and 31c8201.

📒 Files selected for processing (1)
  • src/undate/undate.py (2 hunks)

Walkthrough

Adds MIN_YEAR and MAX_YEAR constants to HebrewDateConverter. Reworks Undate possible_years to derive from initial_values["year"] with partial-digit handling and step inference. Updates duration month handling to compute possible months from initial_values and aggregate max days across representative years. Adds tests for non-Gregorian calendars covering possible_years and month durations.

Changes

Cohort / File(s) Summary of Changes
Hebrew Calendar Converter
src/undate/converters/calendars/hebrew/converter.py
Added class constants: MIN_YEAR: int = 1 and MAX_YEAR = int(2.5e12); no method or control-flow changes.
Undate Core Logic
src/undate/undate.py
Rewrote possible_years to use initial_values["year"] with partial-digit expansion and computed step; raises for completely unknown year. Reworked duration() MONTH branch to compute possible months from initial_values["month"] and aggregate month lengths via max_day over representative years.
Tests: Non-Gregorian Handling
tests/test_undate.py
Added tests validating non-Gregorian possible_years behavior and month duration calculations across Seleucid, Hebrew, and Islamic calendars, including variable-length months and yearless month cases.

Sequence Diagram(s)

sequenceDiagram
  participant C as Caller
  participant U as Undate.possible_years
  Note over U: Input: initial_values["year"]
  C->>U: request possible_years
  alt year is int (fully known)
    U-->>C: [year]
  else year is str with some known digits
    U->>U: earliest = replace_missing_with_0(year)
    U->>U: latest = replace_missing_with_9(year)
    U->>U: step = 10^(position_of_first_missing - 1)
    U-->>C: range(earliest, latest, step) inclusive
  else year missing or no known digits
    U-->>C: raise ValueError("completely unknown year")
  end
Loading
sequenceDiagram
  participant C as Caller
  participant U as Undate.duration (MONTH)
  participant Cal as Calendar
  Note over U: Inputs: calendar, initial_values.month, representative_years
  C->>U: duration for MONTH
  alt month is int
    U->>U: possible_months = [month]
  else month is partial string
    U->>U: earliest = replace_missing_with_0
    U->>U: latest = min(cal_max_month, replace_missing_with_9)
    U->>U: possible_months = range(earliest, latest)
  end
  loop for m in possible_months, y in representative_years
    U->>Cal: max_day(y, m)
    Cal-->>U: day_count
    U->>U: collect possible_max_days
  end
  U-->>C: deterministic day or UnInt(...) from possible_max_days
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • robcast

Poem

A nibble of dates, a hop through years,
I count the moons with twitchy ears.
Hebrew bounds set wide and clear,
Months unfurl from what we hear.
Partial digits, clues in sight—
I hop the range, both day and night.
Thump-thump: the math feels right! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/non-gregorian-month-duration

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

codecov bot commented Aug 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.78%. Comparing base (7170433) to head (31c8201).
⚠️ Report is 16 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #146      +/-   ##
===========================================
+ Coverage    98.72%   98.78%   +0.06%     
===========================================
  Files           38       38              
  Lines         1956     1973      +17     
===========================================
+ Hits          1931     1949      +18     
+ Misses          25       24       -1     

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

🧹 Nitpick comments (3)
src/undate/converters/calendars/hebrew/converter.py (1)

24-28: Avoid float-to-int conversion for MAX_YEAR; tighten the comment

Casting from a float literal is unnecessary and risks subtle rounding. Also, the comment uses 2.5^16 (caret) but the intended notation is 2.5e16.

-    #: earliest possible year in the Hebrew calendar is year 1, it does not go negative
-    MIN_YEAR: int = 1
-    # convertdate gives a month 34 for numpy max year 2.5^16, so scale it back a bit
-    MAX_YEAR = int(2.5e12)
+    #: earliest possible year in the Hebrew calendar is year 1; it does not go negative
+    MIN_YEAR: int = 1
+    # convertdate returns invalid months for extremely large years (~2.5e16); use a safer bound
+    MAX_YEAR: int = 2_500_000_000_000
tests/test_undate.py (1)

459-472: Solid coverage for non‑Gregorian month durations; consider adding “unknown month” cases

These checks validate fixed and variable month lengths across calendars. To prevent regressions with partially/fully unknown months, add cases like:

  • Undate(month="XX", calendar="Hebrew") → UnInt(29, 30) or UnInt(29, 30, 29/30/…) depending on representative years
  • Undate(month="0X", calendar="Islamic") → UnInt(29, 30)

I can add a parametrized test to cover "XX" and "0X" inputs for Hebrew/Islamic/Seleucid months.

src/undate/undate.py (1)

585-591: Construct UnDelta with sorted bounds to avoid order/arity pitfalls

possible_max_days is a set; argument order to UnDelta is non-deterministic. Prefer min/max.

-            if len(possible_max_days) > 1:
-                return UnDelta(*possible_max_days)
+            if len(possible_max_days) > 1:
+                lo, hi = min(possible_max_days), max(possible_max_days)
+                return UnDelta(lo, hi)
             return Timedelta(possible_max_days.pop())
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c6b97ff and c48a6c6.

📒 Files selected for processing (3)
  • src/undate/converters/calendars/hebrew/converter.py (1 hunks)
  • src/undate/undate.py (2 hunks)
  • tests/test_undate.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/undate/undate.py (5)
src/undate/date.py (2)
  • year (230-231)
  • month (234-238)
src/undate/converters/calendars/hebrew/converter.py (3)
  • max_month (41-44)
  • representative_years (64-88)
  • max_day (55-58)
src/undate/converters/calendars/islamic/converter.py (3)
  • max_month (45-47)
  • representative_years (49-73)
  • max_day (37-39)
src/undate/converters/base.py (3)
  • max_month (165-167)
  • representative_years (194-200)
  • max_day (177-179)
src/undate/converters/calendars/gregorian.py (3)
  • max_month (25-27)
  • representative_years (48-73)
  • max_day (29-46)
tests/test_undate.py (2)
src/undate/undate.py (3)
  • possible_years (475-506)
  • duration (526-593)
  • month (446-456)
src/undate/date.py (3)
  • days (29-31)
  • month (234-238)
  • UnInt (35-121)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (python)
🔇 Additional comments (1)
tests/test_undate.py (1)

413-415: LGTM: preserves original calendar for fully known non‑Gregorian years

This assertion guards against unintended Gregorian normalization in possible_years. Good coverage.

@rlskoeser rlskoeser merged commit 50f297f into develop Sep 18, 2025
12 checks passed
@rlskoeser rlskoeser deleted the bugfix/non-gregorian-month-duration branch September 18, 2025 15:01
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