1919# Pre 3.10 requires Union for multiple types, e.g. Union[int, None] instead of int | None
2020from typing import Dict , Optional , Union
2121
22- from undate .converters .base import BaseDateConverter
22+ from undate .converters .base import BaseCalendarConverter , BaseDateConverter
2323from undate .date import ONE_DAY , Date , DatePrecision , Timedelta , UnDelta
2424
2525
@@ -32,10 +32,14 @@ class Calendar(StrEnum):
3232 SELEUCID = auto ()
3333
3434 @staticmethod
35- def get_converter (calendar ):
35+ def get_converter (calendar ) -> BaseCalendarConverter :
3636 # calendar converter must be available with a name matching
3737 # the title-case name of the calendar enum entry
3838 converter_cls = BaseDateConverter .available_converters ()[calendar .value .title ()]
39+ if not issubclass (converter_cls , BaseCalendarConverter ):
40+ raise ValueError (
41+ f"Requested converter { converter_cls } is not a CalendarConverter"
42+ )
3943 return converter_cls ()
4044
4145
@@ -492,13 +496,12 @@ def duration(self) -> Timedelta | UnDelta:
492496 self .calendar_converter .LEAP_YEAR ,
493497 self .calendar_converter .NON_LEAP_YEAR ,
494498 ]
495- possible_max_days = None
499+ possible_max_days = set ()
496500
497501 # if precision is month and year is unknown,
498502 # calculate month duration within a single year (not min/max)
499503 if self .precision == DatePrecision .MONTH :
500504 # for every possible month and year, get max days for that month,
501- possible_max_days = set ()
502505 # appease mypy, which says month values could be None here;
503506 # Date object allows optional month, but earliest/latest initialization
504507 # should always be day-precision dates
@@ -511,40 +514,17 @@ def duration(self) -> Timedelta | UnDelta:
511514
512515 # if precision is year but year is unknown, return an uncertain delta
513516 elif self .precision == DatePrecision .YEAR :
514- possible_max_days = set ()
515517 # this is currently hebrew-specific due to the way the start/end of year wraps for that calendar
516- try :
517- possible_max_days = set (
518- [self .calendar_converter .days_in_year (y ) for y in possible_years ]
519- )
520- except NotImplementedError :
521- pass
522-
523- if not possible_max_days :
524- for year in possible_years :
525- # TODO: shift logic to calendars for parity with Hebrew?
526- year_start = Date (
527- * self .calendar_converter .to_gregorian (
528- year , self .calendar_converter .min_month (), 1
529- )
530- )
531- last_month = self .calendar_converter .max_month (year )
532- year_end = Date (
533- * self .calendar_converter .to_gregorian (
534- year ,
535- last_month ,
536- self .calendar_converter .max_day (year , last_month ),
537- )
538- )
539-
540- year_days = (year_end - year_start ).days + 1
541- possible_max_days .add (year_days )
518+ # with contextlib.suppress(NotImplementedError):
519+ possible_max_days = {
520+ self .calendar_converter .days_in_year (y ) for y in possible_years
521+ }
542522
543523 # if there is more than one possible value for number of days
544524 # due to range including lear year / non-leap year, return an uncertain delta
545- if possible_max_days and len ( possible_max_days ) > 1 :
546- return UnDelta ( * possible_max_days )
547- else :
525+ if possible_max_days :
526+ if len ( possible_max_days ) > 1 :
527+ return UnDelta ( * possible_max_days )
548528 return Timedelta (possible_max_days .pop ())
549529
550530 # otherwise, subtract earliest from latest and add a day to include start day in the count
0 commit comments