@@ -475,29 +475,35 @@ def _get_date_part(self, part: str) -> Optional[str]:
475
475
def possible_years (self ) -> list [int ] | range :
476
476
"""A list or range of possible years for this date in the original calendar.
477
477
Returns a list with a single year for dates with fully-known years."""
478
- if self .known_year :
479
- return [self .earliest .year ]
478
+ # get the initial value passed in for year in original calendar
479
+ initial_year_value = self .initial_values ["year" ]
480
+ # if integer, year is fully known and is the only possible value
481
+ if isinstance (initial_year_value , int ):
482
+ return [initial_year_value ]
480
483
481
- step = 1
484
+ # if year is None or string with all unknown digits, bail out
482
485
if (
483
- self . is_partially_known ( "year" )
484
- and str (self .year ).replace (self .MISSING_DIGIT , "" ) ! = ""
486
+ initial_year_value is None
487
+ or str (self .year ).replace (self .MISSING_DIGIT , "" ) = = ""
485
488
):
486
- # determine the smallest step size for the missing digit
487
- earliest_year = int (str (self .year ).replace (self .MISSING_DIGIT , "0" ))
488
- latest_year = int (str (self .year ).replace (self .MISSING_DIGIT , "9" ))
489
- missing_digit_place = len (str (self .year )) - str (self .year ).rfind (
490
- self .MISSING_DIGIT
489
+ # otherwise, year is fully unknown
490
+ # returning range from min year to max year is not useful in any scenario!
491
+ raise ValueError (
492
+ "Possible years cannot be returned for completely unknown year"
491
493
)
492
- # convert place to 1, 10, 100, 1000, etc.
493
- step = 10 ** (missing_digit_place - 1 )
494
- return range (earliest_year , latest_year + 1 , step )
495
-
496
- # otherwise, year is fully unknown
497
- # returning range from min year to max year is not useful in any scenario!
498
- raise ValueError (
499
- "Possible years cannot be returned for completely unknown year"
494
+
495
+ # otherwise, year is partially known
496
+ # determine the smallest step size for the missing digit
497
+ earliest_year = int (str (self .year ).replace (self .MISSING_DIGIT , "0" ))
498
+ latest_year = int (str (self .year ).replace (self .MISSING_DIGIT , "9" ))
499
+ missing_digit_place = len (str (self .year )) - str (self .year ).rfind (
500
+ self .MISSING_DIGIT
500
501
)
502
+ # convert place to 1, 10, 100, 1000, etc.
503
+ step = 10 ** (missing_digit_place - 1 )
504
+ # generate a range from earliest to latest with the appropriate step
505
+ # based on the smallest missing digit
506
+ return range (earliest_year , latest_year + 1 , step )
501
507
502
508
@property
503
509
def representative_years (self ) -> list [int ]:
@@ -540,12 +546,32 @@ def duration(self) -> Timedelta | UnDelta:
540
546
# appease mypy, which says month values could be None here;
541
547
# Date object allows optional month, but earliest/latest initialization
542
548
# should always be day-precision dates
543
- if self .earliest .month is not None and self .latest .month is not None :
544
- for possible_month in range (self .earliest .month , self .latest .month + 1 ):
545
- for year in self .representative_years :
546
- possible_max_days .add (
547
- self .calendar_converter .max_day (year , possible_month )
548
- )
549
+
550
+ # FIXME: earliest/latest are gregorian! need to use months from the original calendar,
551
+ # not converted months
552
+ initial_month_value = self .initial_values ["month" ]
553
+ # if integer, month is fully known and is the only possible value
554
+ possible_months : list [int ] | range
555
+ if isinstance (initial_month_value , int ):
556
+ possible_months = [initial_month_value ]
557
+ elif isinstance (initial_month_value , str ):
558
+ # earliest possible month for missing digit
559
+ earliest_month = int (
560
+ initial_month_value .replace (self .MISSING_DIGIT , "0" )
561
+ )
562
+ # latest possible month for missing digit, but no greater than
563
+ # calendar max month
564
+ latest_month = min (
565
+ self .calendar_converter .max_month (
566
+ self .calendar_converter .LEAP_YEAR
567
+ ),
568
+ int (initial_month_value .replace (self .MISSING_DIGIT , "9" )),
569
+ )
570
+ possible_months = range (earliest_month , latest_month + 1 )
571
+
572
+ for month in possible_months :
573
+ for year in self .representative_years :
574
+ possible_max_days .add (self .calendar_converter .max_day (year , month ))
549
575
550
576
# if precision is year but year is unknown, return an uncertain delta
551
577
elif self .precision == DatePrecision .YEAR :
0 commit comments