From 85aec531f5fc91fd05d4caed2f1f75cb3627abf1 Mon Sep 17 00:00:00 2001 From: kinegratii Date: Tue, 2 Apr 2024 22:43:18 +0800 Subject: [PATCH] :sparkles: New LunarDate for last day in a year or a month --- borax/calendars/festivals2.py | 2 +- borax/calendars/lunardate.py | 18 +++++++++++++++--- docs/changelog.md | 2 +- tests/test_lunardate.py | 11 +++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/borax/calendars/festivals2.py b/borax/calendars/festivals2.py index de999a4..6ef87eb 100644 --- a/borax/calendars/festivals2.py +++ b/borax/calendars/festivals2.py @@ -181,7 +181,7 @@ def solar_month(year: int, month: int) -> Tuple[date, date]: @staticmethod def lunar_year(year: int, end_year: int = 0) -> Tuple[LunarDate, LunarDate]: end_year = end_year or year - return LunarDate(year, 1, 1), LunarDate.last_day_of_year(end_year) + return LunarDate(year, 1, 1), LunarDate.last_day(end_year) @staticmethod def lunar_month(year: int, month: int, leap: int = _IGNORE_LEAP_MONTH) -> Tuple[LunarDate, LunarDate]: diff --git a/borax/calendars/lunardate.py b/borax/calendars/lunardate.py index 8250037..aa87b03 100644 --- a/borax/calendars/lunardate.py +++ b/borax/calendars/lunardate.py @@ -659,9 +659,21 @@ def tomorrow(cls) -> 'LunarDate': return cls.from_solar_date(sd.year, sd.month, sd.day) @classmethod - def last_day_of_year(cls, year: int) -> 'LunarDate': - """return the last day in a lunar year.""" - month, day, leap = list(LCalendars.iter_year_month(year))[-1] + def last_day(cls, year: int, month: int = 0, leap: int = 0) -> 'LunarDate': + """return the last day in a lunar year or a lunar month.""" + mdls = list(LCalendars.iter_year_month(year)) + if month == 0: + index = -1 + else: + leap_month_of_year = LCalendars.leap_month(year) + if leap: + if month == leap_month_of_year: + index = month + else: + raise InvalidLunarDateError(f'{year=}, {month=},leap=1 does not exist.') + else: + index = month - 1 + int(leap_month_of_year and month > leap_month_of_year) + month, day, leap = mdls[index] return cls(year, month, day, leap) @classmethod diff --git a/docs/changelog.md b/docs/changelog.md index 8da96ea..1be80c8 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,7 +2,7 @@ ## v4.1.1 -- 新增创建农历年最后一天的方法 `LunarDate.last_day_of_year` +- 新增创建农历年或农历月最后一天的方法 `LunarDate.last_day` - `SolarFestival` 和`LunarFestival` 初始化函数 `freq` 参数支持字符串设置( [ #56](https://github.com/kinegratii/borax/issues/56) ) - `Period.solar_year` 和 `Period.lunar_year` 新增 `end_year` 参数,支持跨年份计算 - 废弃模块:`borax.choices` diff --git a/tests/test_lunardate.py b/tests/test_lunardate.py index 1ae8465..6005949 100644 --- a/tests/test_lunardate.py +++ b/tests/test_lunardate.py @@ -39,6 +39,17 @@ def test_create_specific_dates(self): self.assertEqual(LunarDate(2023, 12, 30), LunarDate.last_day_of_year(2023)) + def test_last_day(self): + self.assertEqual(LunarDate(2023, 12, 30), LunarDate.last_day(2023)) + self.assertEqual(LunarDate(2023, 1, 29), LunarDate.last_day(2023, 1)) + self.assertEqual(LunarDate(2023, 2, 30), LunarDate.last_day(2023, 2)) + self.assertEqual(LunarDate(2023, 2, 29, 1), LunarDate.last_day(2023, 2, leap=1)) + self.assertEqual(LunarDate(2023, 3, 29), LunarDate.last_day(2023, 3)) + + self.assertEqual(LunarDate(2024, 12, 29), LunarDate.last_day(2024)) + with self.assertRaises(Exception): + LunarDate.last_day(2024, 2, 1) + def test_convert_datetime(self): dt = LunarDate(1976, 8, 8, 1).to_solar_date() self.assertEqual(date(1976, 10, 1), dt)