diff --git a/borax/calendars/festivals2.py b/borax/calendars/festivals2.py
index e402ab5..49f0ccd 100644
--- a/borax/calendars/festivals2.py
+++ b/borax/calendars/festivals2.py
@@ -30,6 +30,8 @@ class FreqConst:
YEARLY = 0
MONTHLY = 1
+ LABEL2VAL = {'monthly': 1, 'yearly': 0, 'm': 1, 'y': 0}
+
class FestivalCatalog:
basic = 'basic'
@@ -460,12 +462,17 @@ class SolarFestival(Festival):
"""
date_class = date
- def __init__(self, *, day: int, freq: int = FreqConst.YEARLY, month: int = 0, name: str = None):
+ def __init__(self, *, day: int, freq: Union[int, Literal['yearly', 'monthly', 'y', 'm']] = FreqConst.YEARLY,
+ month: int = 0, name: str = None):
if day < 0:
day = -day
reverse = 1
else:
reverse = 0
+ if isinstance(freq, str):
+ freq = FreqConst.LABEL2VAL.get(freq, -1)
+ if freq == -1:
+ raise ValueError('Invalid freq string.')
super().__init__(name=name, freq=freq, month=month, day=day, reverse=reverse, schema=FestivalSchema.SOLAR)
def _get_description(self) -> str:
@@ -680,13 +687,17 @@ class LunarFestival(Festival):
"""
date_class = LunarDate
- def __init__(self, *, day: int, freq: int = FreqConst.YEARLY, month: int = 0, leap: int = _IGNORE_LEAP_MONTH,
- name: str = None):
+ def __init__(self, *, day: int, freq: Union[int, Literal['yearly', 'monthly', 'y', 'm']] = FreqConst.YEARLY,
+ month: int = 0, leap: int = _IGNORE_LEAP_MONTH, name: str = None):
if day < 0:
day = -day
reverse = 1
else:
reverse = 0
+ if isinstance(freq, str):
+ freq = FreqConst.LABEL2VAL.get(freq, -1)
+ if freq == -1:
+ raise ValueError('Invalid freq string.')
super().__init__(freq=freq, name=name, month=month, day=day, leap=leap, reverse=reverse,
schema=FestivalSchema.LUNAR)
diff --git a/docs/changelog.md b/docs/changelog.md
index 9c4aa6d..0de0594 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,5 +1,9 @@
# 更新日志
+## v4.1.1
+
+- `SolarFestival` 和`LunarFestival` 初始化函数 `freq` 参数支持字符串设置( [ #56](https://github.com/kinegratii/borax/issues/56) )
+
## v4.1.0 (20240131)
> Borax最低python版本要求为python3.9
diff --git a/docs/guides/festivals2.md b/docs/guides/festivals2.md
index 0d5aa2c..951dc33 100644
--- a/docs/guides/festivals2.md
+++ b/docs/guides/festivals2.md
@@ -2,6 +2,8 @@
> 模块: `borax.calendars.festivals2`
+> Updated in 4.1.1: SolarFestival和LunarFestival的freq参数支持字符串形式。
+
> Updated in 4.1.0:新增 Festival.code属性。
> Updated in 3.5.6: 星期型节日(WeekFestival)类支持倒数序号。如:“国际麻风节(1月最后一个星期天)”
@@ -161,11 +163,13 @@ class SolarFestival(*, day: int, freq: int = FreqConst.YEARLY, month: int = 0, n
参数定义
-| 参数 | 描述 | 取值 |
-| ----- | ------------------------------------------------------------ | -------------- |
-| freq | 节日频率,“每年”或“每月”,默认“每年”。 | 0:每年;1:每月 |
-| month | 月份。 | 0,1-12 |
-| day | 日期序号。当month取值0时,表示一年的第几天;否则表示该月的第几天。允许取负值,表示一年/一个月的倒数 第几天。 | |
+| 参数 | 描述 | 取值 |
+| ----- | ------------------------------------------------------------ | ---------------------------------------------- |
+| freq | 节日频率,“每年”或“每月”,默认“每年”。 | 0/yearly/y:每年;1/monthly/m:每月 1 |
+| month | 月份。 | 0,1-12 |
+| day | 日期序号。当month取值0时,表示一年的第几天;否则表示该月的第几天。允许取负值,表示一年/一个月的倒数 第几天。 | |
+
+1. v4.1.1 新增字符串形式。
6种形式定义
@@ -186,12 +190,14 @@ class LunarFestival(*, day:int, freq:int=FreqConst.YEARLY, month:int=0, leap:int
参数定义
-| 参数 | 描述 | 取值 |
-| ----- | ------------------------------------------------------------ | --------------- |
-| freq | 节日频率,“每年”或“每月”,默认“每年”。 | 0:每年;1:每月 |
-| month | 月份。 | 0,1-12 |
-| leap | 闰月标记。取值参见 `LeapConst`。 | LeapConst.MIXED |
-| day | 日期序号。当month未设置时,表示一年的第几天;否则表示该月的第几天。允许取负值,表示一年/一个月的倒数 第几天。 | |
+| 参数 | 描述 | 取值 |
+| ----- | ------------------------------------------------------------ | ---------------------------------------------- |
+| freq | 节日频率,“每年”或“每月”,默认“每年”。 | 0/yearly/y:每年;1/monthly/m:每月 1 |
+| month | 月份。 | 0,1-12 |
+| leap | 闰月标记。取值参见 `LeapConst`。 | LeapConst.MIXED |
+| day | 日期序号。当month未设置时,表示一年的第几天;否则表示该月的第几天。允许取负值,表示一年/一个月的倒数 第几天。 | |
+
+1. v4.1.1 新增字符串形式。
### WeekFestival
@@ -386,7 +392,7 @@ Festival.list_days_in_future(end_date=None, reverse: bool = False, count: int =
Festival.list_days_in_past(end_date=None, reverse: bool = False, count: int = -1) -> List[WrappedDate]
```
-返回今后时间([today, end_date])之间(含起止日期)匹配本 Festival 的日期列表。
+返回过去时间([today, end_date])之间(含起止日期)匹配本 Festival 的日期列表。
### get_one_day
@@ -687,7 +693,7 @@ pprint.pprint(days)
FestivalLibrary.monthdaycalendar(year: int, month: int, firstweekday: int = 0)
```
-返回二维列表,每一行表示一个星期。逻辑同iter_month_daytuples。
+返回二维列表,每一行表示一个星期。逻辑同`iter_month_daytuples` 。
### to_csv
diff --git a/tests/test_festival2_list.py b/tests/test_festival2_list.py
index 421ec86..5d46530 100644
--- a/tests/test_festival2_list.py
+++ b/tests/test_festival2_list.py
@@ -47,6 +47,13 @@ def test_reverse(self):
self.assertEqual(date(2021, 2, 28), sf2.at(year=2021, month=2))
self.assertEqual(date(2020, 2, 29), sf2.at(year=2020, month=2))
+ def test_freq_string(self):
+ sf = SolarFestival(freq='monthly', day=1)
+ self.assertTrue(sf.is_(date(2024, 2, 1)))
+
+ with self.assertRaises(ValueError):
+ SolarFestival(freq='33', day=1)
+
class WeekFestivalTestCase(unittest.TestCase):
def test_basic_logic(self):
@@ -136,6 +143,12 @@ def test_monthly(self):
with self.assertRaises(FestivalError):
lf.at(year=2021)
+ def test_freq_string(self):
+ lf = LunarFestival(freq='m', day=1)
+ self.assertTrue(lf.is_(LunarDate(2024, 1, 1)))
+ with self.assertRaises(ValueError):
+ LunarFestival(freq='xxx', day=1)
+
class CheckFestivalTestCase(unittest.TestCase):
def test_all_days(self):