如何使用kosher_dart为JewishDate高效添加月份(兼容闰年)
如何在kosher_dart中高效为JewishDate添加指定月份(O(1)复杂度)
核心思路
犹太历遵循19年闰周规则,每19年中有7个闰年(含13个月),其余12个平年(含12个月)。利用这个固定周期,我们可以直接计算添加指定月份后的目标年、月,无需循环逐年校验,保证O(1)时间复杂度(最多遍历19次固定周期,属于常数时间)。
实现步骤
获取当前日期的核心参数
先提取当前JewishDate的年、月、日:final currentYear = jewishDate.jewishYear; final currentMonth = jewishDate.jewishMonth; final currentDay = jewishDate.dayOfMonth;定义19年闰周的月份规则
预定义闰周中每一年的月份数(索引对应闰周内的第1-19年):// 19年闰周内每年的月份数:闰年为13,平年为12 const _monthsPerCycleYear = [12,12,13,12,12,13,12,13,12,12,13,12,12,13,12,12,13,12,13];计算目标年和目标月份
基于闰周规则,计算添加指定月份后的年和月:int addMonths = 6; // 示例:添加6个月 int targetYear = currentYear; int targetMonth = currentMonth; int remaining = addMonths; // 当前年在19年闰周中的位置(索引0对应闰周第1年) final currentCycleIdx = (currentYear - 1) % 19; // 先处理当前年剩余的月份 final monthsLeftInCurrent = _monthsPerCycleYear[currentCycleIdx] - targetMonth + 1; if (remaining <= monthsLeftInCurrent) { targetMonth += remaining; remaining = 0; } else { remaining -= monthsLeftInCurrent; targetYear += 1; // 遍历闰周后续年份,直到用完剩余月份(最多循环19次,常数时间) while (remaining > 0) { final nextCycleIdx = (targetYear - 1) % 19; final monthsInNextYear = _monthsPerCycleYear[nextCycleIdx]; if (remaining <= monthsInNextYear) { targetMonth = remaining; remaining = 0; } else { remaining -= monthsInNextYear; targetYear += 1; } } }修正日期有效性
由于犹太历部分月份的天数不固定(如Cheshvan、Kislev),需将目标日期修正为对应月份的有效天数:// 创建目标年份月份的日历实例,获取该月最大天数 final targetCalendar = JewishCalendar(); targetCalendar.setJewishDate(targetYear, targetMonth, 1); final maxDayInMonth = targetCalendar.getDaysInJewishMonth(); // 若原日期超过当月最大天数,取当月最后一天 final targetDay = currentDay > maxDayInMonth ? maxDayInMonth : currentDay;生成最终的JewishDate实例
final newJewishDate = JewishDate(); newJewishDate.setJewishDate(targetYear, targetMonth, targetDay);
关键说明
- 闰年处理:通过预定义的
_monthsPerCycleYear数组,自动适配平年/闰年的月份数,不会出现目标月份为Adar II但目标年是平年的情况。 - 月份天数适配:利用
JewishCalendar.getDaysInJewishMonth()获取目标月份的准确天数,避免无效日期。 - 时间复杂度:所有操作均为常数时间,即使遍历闰周也最多19次,完全符合O(1)要求。
内容的提问来源于stack exchange,提问作者נתן אנטר
相关产品推荐
相关产品推荐

