fcalendar 0.12.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ publish:
10
+ name: Build and publish to PyPI
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+
15
+ steps:
16
+ - name: Checkout repository
17
+ uses: actions/checkout@v4
18
+
19
+ - name: Set up Python
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.10"
23
+
24
+ - name: Install build dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install build
28
+
29
+ - name: Build package
30
+ run: python -m build
31
+
32
+ - name: Publish to PyPI
33
+ uses: pypa/gh-action-pypi-publish@release/v1
34
+ with:
35
+ password: ${{ secrets.PYPI_API_TOKEN }}
@@ -0,0 +1,10 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
@@ -0,0 +1,27 @@
1
+ [MAIN]
2
+ # 忽略的模块
3
+ ignore=tests
4
+
5
+ [MESSAGES CONTROL]
6
+ # 禁用一些过于严格的检查
7
+ disable=
8
+ too-many-lines,
9
+ too-many-locals,
10
+ too-many-branches,
11
+ too-many-statements,
12
+ too-many-return-statements,
13
+ invalid-name,
14
+ broad-exception-caught,
15
+ consider-iterating-dictionary,
16
+ f-string-without-interpolation,
17
+ no-else-return,
18
+ import-outside-toplevel,
19
+ unused-variable,
20
+ redefined-outer-name,
21
+ reimported,
22
+ ungrouped-imports,
23
+ superfluous-parens
24
+
25
+ [FORMAT]
26
+ # 允许更长的行
27
+ max-line-length=120
@@ -0,0 +1 @@
1
+ 3.10
@@ -0,0 +1,7 @@
1
+ {
2
+ "python.testing.pytestArgs": [
3
+ "tests"
4
+ ],
5
+ "python.testing.unittestEnabled": false,
6
+ "python.testing.pytestEnabled": true
7
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 youngfree
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+ include uv.lock
5
+ recursive-include fcalendar *.py
6
+ recursive-include fcalendar *.typed
@@ -0,0 +1,486 @@
1
+ Metadata-Version: 2.4
2
+ Name: fcalendar
3
+ Version: 0.12.0
4
+ Summary: Add your description here
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: chinesecalendar>=1.9.0
8
+ Requires-Dist: lunardate>=0.2.2
9
+ Description-Content-Type: text/markdown
10
+
11
+ English | [简体中文](README_CN.md)
12
+
13
+ # fcalendar
14
+
15
+ A powerful Python library and CLI tool for recognizing and annotating Chinese/English time expressions, and querying Chinese public holiday schedules.
16
+
17
+ ## ✨ Features
18
+
19
+ - 🌍 **Multi-language Support**: Automatic language detection, supports both Chinese and English input/output
20
+ - 🎯 **Relative Time**: tomorrow, next week, next month, etc.
21
+ - 📅 **Chinese Legal Holidays**: Spring Festival, National Day, Mid-Autumn Festival, etc.
22
+ - 🌙 **Lunar Calendar**: Traditional festivals, lunar dates
23
+ - 🎄 **Western Festivals**: Christmas, Halloween, Valentine's Day, etc.
24
+ - 🌸 **24 Solar Terms**: Spring Equinox, Winter Solstice, etc.
25
+ - 🍂 **Seasons**: Spring, Summer, Autumn, Winter
26
+ - 📊 **Quarters and Cycles**: Q1-Q4, first/second half of year
27
+ - 📆 **Specific Dates**: Supports various date formats
28
+ - 🔄 **Year Prefixes**: last year, next year, 2024, etc.
29
+ - ⏰ **Real-time**: Supports current time queries (returns Beijing time)
30
+ - 🗓️ **Holiday Query**: Query Chinese public holidays and weekends within a specified range
31
+ - 💻 **CLI Support**: All core features accessible via command-line interface
32
+
33
+ ## 📦 Installation
34
+
35
+ ### Install from PyPI
36
+
37
+ ```bash
38
+ pip install fcalendar
39
+ ```
40
+
41
+ ### Install from Aliyun PyPI (Internal Network)
42
+
43
+ ```bash
44
+ pip install fcalendar
45
+ ```
46
+
47
+ ### Install from Source
48
+
49
+ ```bash
50
+ git clone https://github.com/youngfreefjs/fcalendar.git
51
+ cd fcalendar
52
+ pip install -e .
53
+ ```
54
+ ## 🚀 Quick Start
55
+
56
+ ### Python API
57
+
58
+ ```python
59
+ from fcalendar import query, holiday
60
+ import datetime
61
+
62
+ # Time expression recognition
63
+ result = query("meeting tomorrow", datetime.date(2026, 2, 13))
64
+ print(result)
65
+ # Output: meeting tomorrow (Today is February 13, 2026, tomorrow is February 14, 2026)
66
+
67
+ # Holiday query
68
+ result = holiday("next_month", datetime.date(2026, 3, 31))
69
+ print(result)
70
+ # Output: [{'type': 'holiday', 'name': '清明节', 'start': '2026-04-04', 'end': '2026-04-06', 'days': 3}, ...]
71
+ ```
72
+
73
+ ### CLI
74
+
75
+ ```bash
76
+ # Time expression recognition
77
+ fcalendar query "meeting next Monday"
78
+ # Output: {"input": "meeting next Monday", "result": "meeting next Monday (Today is ..., next Monday is April 6, 2026)"}
79
+
80
+ # Holiday query (supports Chinese and English scope)
81
+ fcalendar holiday --scope next_month
82
+ fcalendar holiday --scope 本周
83
+ fcalendar holiday --scope "weeks=3"
84
+ fcalendar holiday --scope 未来两个月
85
+ ```
86
+
87
+ ## 🌍 Language Support
88
+
89
+ fcalendar supports both **Chinese** and **English** with automatic language detection:
90
+
91
+ ### Automatic Language Detection
92
+
93
+ The library automatically detects the input language and returns output in the same language:
94
+
95
+ ```python
96
+ # Chinese input → Chinese output
97
+ query("明天开会", datetime.date(2026, 2, 13))
98
+ # Output: 明天开会(今天是2026 年 2 月 13 日,明天是2026 年 2 月 14 日)
99
+
100
+ # English input → English output
101
+ query("meeting tomorrow", datetime.date(2026, 2, 13))
102
+ # Output: meeting tomorrow (Today is February 13, 2026, tomorrow is February 14, 2026)
103
+ ```
104
+
105
+ ### Manual Language Specification
106
+
107
+ You can also manually specify the language using the `lang` parameter:
108
+
109
+ ```python
110
+ # Force English output
111
+ query("tomorrow", datetime.date(2026, 2, 13), lang='en')
112
+ # Output: tomorrow (Today is February 13, 2026, tomorrow is February 14, 2026)
113
+
114
+ # Force Chinese output
115
+ query("明天", datetime.date(2026, 2, 13), lang='zh')
116
+ # Output: 明天(今天是2026 年 2 月 13 日,明天是2026 年 2 月 14 日)
117
+ ```
118
+
119
+ ### Supported English Expressions
120
+
121
+ - **Relative time**: today, tomorrow, day after tomorrow, next week, next month
122
+ - **Weekdays**: Monday, Tuesday, next Monday, this weekend, next weekend
123
+ - **Festivals**: Christmas, Halloween, Valentine's Day, Easter, Thanksgiving
124
+ - **Specific dates**: January 15, 2026, July 15th, Jan 15
125
+
126
+ > **Note**: For Chinese documentation and examples, please see [README_CN.md](README_CN.md)
127
+
128
+ ## 📖 Usage Examples
129
+ ### Real-time Query
130
+
131
+ ```python
132
+ # Query current time (returns Beijing time)
133
+ result = query("现在是几点")
134
+ print(result)
135
+ # Output: 现在是几点(今天是2026 年 3 月 24 日,现在是2026 年 3 月 24 日 21:35:42)
136
+
137
+ # Supports various current time keywords
138
+ keywords = ["当前时间", "现在", "当前", "目前", "此时", "此刻", "眼下", "当下", "这会儿", "这时候", "今天"]
139
+ ```
140
+
141
+ ## 📖 Supported Time Expressions
142
+ ### 1️⃣ Relative Time and Real-time
143
+
144
+ ```python
145
+ # Relative time
146
+ query("meeting tomorrow", datetime.date(2026, 2, 13))
147
+ # Output: meeting tomorrow (Today is February 13, 2026, tomorrow is February 14, 2026)
148
+
149
+ query("travel day after tomorrow", datetime.date(2026, 2, 13))
150
+ # Output: travel day after tomorrow (Today is February 13, 2026, day after tomorrow is February 15, 2026)
151
+
152
+ query("appointment next week", datetime.date(2026, 2, 13))
153
+ # Output: appointment next week (Today is February 13, 2026, next week is February 20, 2026)
154
+
155
+ query("meeting next Monday", datetime.date(2026, 2, 13))
156
+ # Output: meeting next Monday (Today is February 13, 2026, next Monday is February 16, 2026)
157
+
158
+ query("travel next weekend", datetime.date(2026, 2, 13))
159
+ # Output: travel next weekend (Today is February 13, 2026, next weekend is February 21, 2026 - February 22, 2026)
160
+
161
+ query("party this weekend", datetime.date(2026, 2, 13))
162
+ # Output: party this weekend (Today is February 13, 2026, this weekend is February 14, 2026 - February 15, 2026)
163
+
164
+ query("visit museum Wednesday", datetime.date(2026, 2, 13))
165
+ # Output: visit museum Wednesday (Today is February 13, 2026, Wednesday is February 18, 2026)
166
+
167
+ query("business trip next month", datetime.date(2026, 2, 13))
168
+ # Output: business trip next month (Today is February 13, 2026, next month is March 1, 2026 - March 31, 2026)
169
+
170
+ # Real-time keywords (returns Beijing time)
171
+ query("what time is it now", datetime.date(2026, 2, 13))
172
+ # Output: what time is it now (Today is February 13, 2026, now is Beijing time February 13, 2026 00:00:00)
173
+
174
+ query("current time", datetime.date(2026, 2, 13))
175
+ # Output: current time (Today is February 13, 2026, current time is Beijing time February 13, 2026 00:00:00)
176
+ ```
177
+ ### 2️⃣ Western Festivals
178
+
179
+ ```python
180
+ query("buy gifts for Christmas", datetime.date(2026, 2, 13))
181
+ # Output: buy gifts for Christmas (Today is February 13, 2026, Christmas is December 25, 2026)
182
+
183
+ query("Halloween party", datetime.date(2026, 2, 13))
184
+ # Output: Halloween party (Today is February 13, 2026, Halloween is October 31, 2026)
185
+
186
+ query("Valentine's Day flowers", datetime.date(2026, 2, 13))
187
+ # Output: Valentine's Day flowers (Today is February 13, 2026, Valentine's Day is February 14, 2026)
188
+
189
+ query("Easter church service", datetime.date(2026, 2, 13))
190
+ # Output: Easter church service (Today is February 13, 2026, Easter is April 5, 2026)
191
+
192
+ query("Thanksgiving dinner", datetime.date(2026, 2, 13))
193
+ # Output: Thanksgiving dinner (Today is February 13, 2026, Thanksgiving is November 26, 2026)
194
+
195
+ query("Independence Day fireworks", datetime.date(2026, 2, 13))
196
+ # Output: Independence Day fireworks (Today is February 13, 2026, Independence Day is July 4, 2026)
197
+ ```
198
+
199
+ ### 3️⃣ Specific Dates
200
+
201
+ ```python
202
+ # Month and day
203
+ query("meeting on January 15", datetime.date(2026, 2, 13))
204
+ # Output: meeting on January 15 (Today is February 13, 2026, January 15 is January 15, 2027)
205
+
206
+ query("vacation July 15th", datetime.date(2026, 2, 13))
207
+ # Output: vacation July 15th (Today is February 13, 2026, July 15th is July 15, 2026)
208
+
209
+ # With year
210
+ query("conference on January 15, 2027", datetime.date(2026, 2, 13))
211
+ # Output: conference on January 15, 2027 (Today is February 13, 2026, January 15, 2027 is January 15, 2027)
212
+ ```
213
+
214
+ ### 4️⃣ Quarters and Cycles
215
+
216
+ ```python
217
+ query("Q1 meeting", datetime.date(2026, 2, 13))
218
+ # Output: Q1 meeting (Today is February 13, 2026, Q1 is January 1, 2026 - March 31, 2026)
219
+
220
+ query("Q4 summary", datetime.date(2026, 2, 13))
221
+ # Output: Q4 summary (Today is February 13, 2026, Q4 is October 1, 2026 - December 31, 2026)
222
+ ```
223
+
224
+ ### 5️⃣ Complex Combined Examples
225
+
226
+ ```python
227
+ # Multiple time expressions
228
+ text = "meeting tomorrow, travel next weekend, Christmas party"
229
+ result = query(text, datetime.date(2026, 2, 13))
230
+ print(result)
231
+ # Output: meeting tomorrow, travel next weekend, Christmas party (Today is February 13, 2026, tomorrow is February 14, 2026, next weekend is February 21, 2026 - February 22, 2026, Christmas is December 25, 2026)
232
+
233
+ # Comprehensive example
234
+ text = "meeting tomorrow, hotel reservation on July 15th, travel next weekend, visit museum Wednesday, buy gifts for Christmas, Q4 meeting, Easter church service"
235
+ result = query(text, datetime.date(2026, 2, 13))
236
+ # All time expressions will be correctly recognized and annotated
237
+ ```
238
+
239
+ ## 🗓️ Holiday Query API
240
+
241
+ `holiday(scope, today)` queries Chinese public holidays and normal weekends within a given time range. Workdays-on-weekends (调休上班) are excluded to keep the output clean.
242
+
243
+ ```python
244
+ from fcalendar import holiday
245
+ import datetime
246
+
247
+ # Next month's holidays
248
+ result = holiday("next_month", datetime.date(2026, 3, 31))
249
+ # [{'type': 'holiday', 'name': '清明节', 'start': '2026-04-04', 'end': '2026-04-06', 'days': 3},
250
+ # {'type': 'weekend', 'name': '周末', 'start': '2026-04-11', 'end': '2026-04-12', 'days': 2}, ...]
251
+
252
+ # This week
253
+ holiday("this_week")
254
+ holiday("本周") # Chinese scope also supported
255
+
256
+ # Next 3 weeks / 2 months
257
+ holiday("weeks=3")
258
+ holiday("三周") # Chinese numeral
259
+ holiday("months=2")
260
+ holiday("未来两个月")
261
+ ```
262
+
263
+ **Return fields per record:**
264
+
265
+ | Field | Type | Description |
266
+ |-------|------|-------------|
267
+ | `type` | str | `"holiday"` (public holiday) or `"weekend"` (normal restful weekend) |
268
+ | `name` | str | Name, e.g. `"劳动节"`, `"周末"` |
269
+ | `start` | str | Start date, ISO format (YYYY-MM-DD) |
270
+ | `end` | str | End date, ISO format (YYYY-MM-DD) |
271
+ | `days` | int | Number of days |
272
+
273
+ **Supported scope values:**
274
+
275
+ | Scope | Alias | Description |
276
+ |-------|-------|-------------|
277
+ | `half_year` | `半年`, `未来半年` | Next 180 days (default) |
278
+ | `this_week` | `本周`, `这周` | Current week |
279
+ | `next_week` | `下周`, `下一周` | Next week |
280
+ | `next_month` | `下个月`, `下月` | Full next month |
281
+ | `weeks=N` | `N周`, `未来N周` | Next N weeks |
282
+ | `months=N` | `N个月`, `未来N个月` | Next N months |
283
+
284
+ ---
285
+
286
+ ## 💻 CLI
287
+
288
+ All core features are accessible via the `fcalendar` command-line tool.
289
+
290
+ ### Install
291
+
292
+ ```bash
293
+ pip install fcalendar
294
+ ```
295
+
296
+ ### Commands
297
+
298
+ ```bash
299
+ # Time expression recognition → single-line JSON output
300
+ fcalendar query "Spring Festival travel plan"
301
+ # {"input": "Spring Festival travel plan", "result": "Spring Festival travel plan (Today is ..., Spring Festival is ...)"}
302
+
303
+ fcalendar query "下周一开会" --today 2026-03-31
304
+ fcalendar query "meeting next Monday" --lang en
305
+
306
+ # Holiday query → JSON array output
307
+ fcalendar holiday # default: next 180 days
308
+ fcalendar holiday --scope this_week
309
+ fcalendar holiday --scope 本周 # Chinese scope
310
+ fcalendar holiday --scope weeks=3
311
+ fcalendar holiday --scope 未来两个月
312
+ fcalendar holiday --scope next_month --today 2026-09-01
313
+
314
+ # Help
315
+ fcalendar --help
316
+ fcalendar query --help
317
+ fcalendar holiday --help
318
+ ```
319
+
320
+ ---
321
+
322
+ ## 🛠️ Development
323
+
324
+ This project uses `uv` for dependency management:
325
+
326
+ ```bash
327
+ # Install dependencies
328
+ uv sync
329
+
330
+ # Run all tests
331
+ uv run pytest tests/ -v
332
+
333
+ # Run benchmark tests
334
+ uv run pytest tests/test_benchmark.py::test_benchmark_cases -v -s
335
+
336
+ # Run a single test
337
+ uv run pytest tests/test_benchmark.py::test_basic_query -v
338
+ ```
339
+
340
+ ### Test Coverage
341
+
342
+ The project contains **44+ test cases** covering all time expression types:
343
+
344
+ - ✅ Relative time (tomorrow, next week, next month)
345
+ - ✅ Real-time keywords (current time, now, etc.)
346
+ - ✅ Chinese legal holidays
347
+ - ✅ Lunar calendar dates and traditional festivals
348
+ - ✅ Western festivals
349
+ - ✅ 24 solar terms
350
+ - ✅ Seasons and quarters
351
+ - ✅ Specific dates
352
+ - ✅ Year prefixes (last year, next year, 2024, etc.)
353
+ - ✅ Complex combined expressions
354
+ - ✅ Holiday query (public holidays + weekends)
355
+ - ✅ Chinese scope expressions (本周, 未来三周, etc.)
356
+
357
+ Run tests to see detailed results:
358
+
359
+ ```bash
360
+ $ uv run pytest tests/test_benchmark.py::test_benchmark_cases -v -s
361
+
362
+ ============================================================
363
+ 开始运行 Benchmark 测试,共 47 个用例
364
+ ============================================================
365
+
366
+ ✅ [relative_weekday_01] PASSED
367
+ ✅ [relative_weekend_01] PASSED
368
+ ✅ [holiday_spring_festival_01] PASSED
369
+ ✅ [current_time_01] PASSED
370
+ ...
371
+ ============================================================
372
+ 测试完成!
373
+ ============================================================
374
+ 总计: 47 个用例
375
+ 成功: 47 个 (100.0%)
376
+ 失败: 0 个 (0.0%)
377
+ ============================================================
378
+ ```
379
+
380
+ ## 📋 Dependencies
381
+
382
+ - Python >= 3.10
383
+ - chinesecalendar >= 1.9.0 (Chinese legal holiday data)
384
+ - lunardate >= 0.2.2 (Lunar calendar date conversion)
385
+
386
+ ## 📂 Project Structure
387
+
388
+ ```
389
+ fcalendar/
390
+ ├── fcalendar/ # Core package
391
+ │ ├── __init__.py # Package initialization, exports query / holiday
392
+ │ ├── core.py # Core time annotation and holiday query logic
393
+ │ └── cli.py # CLI entry point (fcalendar command)
394
+ ├── fcalendar-skill/ # AI Agent skill documentation
395
+ │ └── SKILL.md # Skill config for AI Agent integration
396
+ ├── tests/ # Test suite
397
+ │ ├── __init__.py
398
+ │ ├── benchmark.json # Test case data (200+ cases)
399
+ │ └── test_benchmark.py # Test code (44+ test functions)
400
+ ├── setup.py # Traditional packaging configuration
401
+ ├── pyproject.toml # Modern packaging configuration (uv)
402
+ ├── publish.sh # Publishing script (Aliyun PyPI)
403
+ └── README.md # Project documentation
404
+ ```
405
+
406
+ ## 🔧 Core Functions
407
+
408
+ ### `annotate_time_expressions(text, today=None, lang=None)`
409
+
410
+ Main function that recognizes and annotates time expressions in text.
411
+
412
+ **Parameters:**
413
+ - `text` (str): Text to be annotated
414
+ - `today` (datetime.date, optional): Reference date, defaults to current date
415
+ - `lang` (str, optional): Language code ('zh' for Chinese, 'en' for English). If None, automatically detects language
416
+
417
+ **Returns:**
418
+ - str: Annotated text in format `original text (context information)`
419
+
420
+ **Features:**
421
+ - **Multi-language support**: Automatically detects input language and returns output in the same language
422
+ - Automatically deduplicates overlapping annotations, keeping longer (more specific) expressions
423
+ - Supports simultaneous annotation of multiple time expressions
424
+ - Preserves original text integrity, adding annotation information in parentheses
425
+ - Supports real-time queries (returns Beijing time when `today` parameter is not provided)
426
+
427
+ ### `query(text, today=None, lang=None)`
428
+
429
+ Convenience function, alias for `annotate_time_expressions`.
430
+
431
+ **Parameters:**
432
+ - `text` (str): Text to be annotated
433
+ - `today` (datetime.date, optional): Reference date, defaults to current date
434
+ - `lang` (str, optional): Language code ('zh' for Chinese, 'en' for English). If None, automatically detects language
435
+
436
+ ## 🚀 Publishing
437
+
438
+ Use the provided publishing script:
439
+
440
+ ```bash
441
+ bash publish.sh
442
+ ```
443
+
444
+ ## 📌 Version Management
445
+
446
+ Current version: **0.11.0**
447
+
448
+ Version numbers need to be synchronized in the following locations:
449
+ - `__version__` in `fcalendar/__init__.py`
450
+ - `version` in `pyproject.toml`
451
+ - `setup.py` automatically reads version from `__init__.py`
452
+
453
+ ## 🙏 Acknowledgements
454
+
455
+ This project is built upon the following open-source libraries:
456
+
457
+ - [**chinese-calendar**](https://github.com/LKI/chinese-calendar) — Chinese legal holiday data for Python, by [@LKI](https://github.com/LKI). Used for accurate Chinese public holiday and workday-on-weekend detection.
458
+ - [**python-lunardate**](https://github.com/lidaobing/python-lunardate) — Lunar calendar date conversion for Python, by [@lidaobing](https://github.com/lidaobing). Used for converting between lunar and Gregorian dates, powering traditional festival and lunar date recognition.
459
+
460
+ ---
461
+
462
+ ## 📄 License
463
+
464
+ MIT License
465
+
466
+
467
+
468
+ ## 🤝 Contributing
469
+
470
+ Issues and Pull Requests are welcome!
471
+
472
+ ## 📝 Changelog
473
+
474
+ ### v0.12.0
475
+ - ✨ Added `holiday()` API: query Chinese public holidays and weekends within a specified range
476
+ - ✨ Added CLI (`fcalendar query` / `fcalendar holiday`): all core features accessible via command line
477
+ - ✨ `holiday()` scope supports Chinese and English, including Chinese numerals (一、两、三...十二)
478
+ - ✨ Added `fcalendar-skill/SKILL.md` for AI Agent integration
479
+ - 📝 Updated documentation and test coverage (44+ test functions)
480
+
481
+ ### v0.11.0
482
+ - ✨ Added real-time keyword support (current time, now, etc.)
483
+ - ✨ Support for multiple stacking expressions (week after next, three days from now, etc.)
484
+ - 🐛 Fixed edge cases in lunar date recognition
485
+ - 📝 Improved documentation and test cases
486
+ - 🎨 Optimized annotation format for better readability