Skip to content

Commit b436f33

Browse files
committed
Implement representative years for hebrew calendar converter
1 parent 43bc97b commit b436f33

2 files changed

Lines changed: 58 additions & 0 deletions

File tree

src/undate/converters/calendars/hebrew/converter.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ class HebrewDateConverter(BaseCalendarConverter):
2121
name: str = "Hebrew"
2222
calendar_name: str = "Anno Mundi"
2323

24+
#: arbitrary known non-leap year; 4816 is a non-leap year with 353 days (minimum possible)
25+
NON_LEAP_YEAR: int = 4816
26+
#: arbitrary known leap year; 4837 is a leap year with 385 days (maximum possible)
27+
LEAP_YEAR: int = 4837
28+
2429
def __init__(self):
2530
self.transformer = HebrewDateTransformer()
2631

@@ -51,6 +56,32 @@ def days_in_year(self, year: int) -> int:
5156
"""the number of days in the specified year for this calendar"""
5257
return int(hebrew.year_days(year))
5358

59+
def representative_years(self, years: None | list[int] = None) -> list[int]:
60+
"""Takes a list of years and returns a subset with all possible variations in number of days.
61+
If no years are specified, returns ...
62+
"""
63+
64+
year_lengths = set()
65+
max_year_lengths = 6 # there are 6 different possible length years
66+
67+
# if years is unset or list is empty
68+
if not years:
69+
# NOTE: this does not cover all possible lengths, but should cover min/max
70+
return [self.LEAP_YEAR, self.NON_LEAP_YEAR]
71+
72+
rep_years = []
73+
for year in years:
74+
days = self.days_in_year(year)
75+
if days not in year_lengths:
76+
year_lengths.add(days)
77+
rep_years.append(year)
78+
79+
# stop if we find one example of each type of year
80+
if len(year_lengths) == max_year_lengths:
81+
break
82+
83+
return rep_years
84+
5485
def to_gregorian(self, year: int, month: int, day: int) -> tuple[int, int, int]:
5586
"""Convert a Hebrew date, specified by year, month, and day,
5687
to the Gregorian equivalent date. Returns a tuple of year, month, day.

tests/test_converters/test_calendars/test_hebrew/test_hebrew_converter.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,30 @@ def test_compare_across_calendars(self):
153153
)
154154
expected_gregorian_years = [-3261, 33, 1056, 1350, 1655, 1995]
155155
assert [d.earliest.year for d in sorted_dates] == expected_gregorian_years
156+
157+
def test_representative_years(self):
158+
converter = HebrewDateConverter()
159+
# single year is not filtered
160+
assert converter.representative_years([4816]) == [4816]
161+
# 4816 has 353 days; 4817 has 355; 4818 has 384; 4819 has 355
162+
assert converter.representative_years([4816, 4817, 4818, 4819]) == [
163+
4816,
164+
4817,
165+
4818,
166+
]
167+
assert converter.representative_years([4816, 4817, 4818, 4819, 4837]) == [
168+
4816,
169+
4817,
170+
4818,
171+
4837,
172+
]
173+
174+
# if no years are provided, returns a known leap year and non-leap years
175+
assert converter.representative_years() == [
176+
converter.LEAP_YEAR,
177+
converter.NON_LEAP_YEAR,
178+
]
179+
assert converter.representative_years([]) == [
180+
converter.LEAP_YEAR,
181+
converter.NON_LEAP_YEAR,
182+
]

0 commit comments

Comments
 (0)