82 Commits

Author SHA1 Message Date
5166d6ce3b Merge pull request 'feature/hk-holiday-support' (#2) from feature/hk-holiday-support into master
Reviewed-on: #2
2026-04-27 05:14:45 +00:00
526d99f193 docs: add data generation, import, and extension guide to README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 12:53:44 +08:00
72ab05df3f docs: update README to cover Hong Kong holiday data
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 12:51:35 +08:00
05a1dca074 feat: add Hong Kong public holiday support
- Add scripts/fetch_hk.py to fetch HK holidays from 1823.gov.hk
- Make generate_ics() cal_name/cal_desc configurable
- Refactor update.py with REGIONS config; support --region cn|hk flag
- Generate hk/{year}.json and hk/{year}.ics under hk/ subdirectory

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 12:09:34 +08:00
c60002b782 Merge pull request 'add 2026 CN holiday info' (#1) from hotfix/add_2026_CN_holiday into master
Reviewed-on: #1
2026-01-05 05:08:59 +00:00
95df17c865 add 2026 CN holiday info 2026-01-05 13:05:25 +08:00
renovate[bot]
29869ddebf chore(deps): update dependency coverage to v7.6.9 (#248)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-06 16:22:10 +00:00
renovate[bot]
54784bad95 chore(deps): update dependency pytest to v8.3.4 (#247)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-01 18:06:34 +00:00
renovate[bot]
56b88184f3 chore(deps): update dependency tqdm to v4.67.1 (#246)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-25 01:57:20 +00:00
renovate[bot]
a39828d0d0 chore(deps): update dependency coverage to v7.6.8 (#245)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-24 07:45:59 +00:00
renovate[bot]
2ea4249b95 chore(deps): update dependency icalendar to v6.1.0 (#235)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-23 01:38:59 +00:00
Kwok
5046df59ec test: update years in description_parsing_cases.json (#244) 2024-11-17 00:42:04 +08:00
renovate[bot]
dc9b5e2ccf chore(deps): pin dependencies 2024-11-16 14:48:27 +08:00
NateScarlet
1d5fb6465e chore: update renovate config 2024-11-16 14:47:22 +08:00
NateScarlet
0c2759c89d chore(deps): update dependency icalendar to v6.0.1 2024-11-16 14:35:15 +08:00
NateScarlet
cd46049bba docs: remove code climate badges 2024-11-16 14:18:10 +08:00
NateScarlet
b3920d0395 Merge branch 'master' of https://github.com/NateScarlet/holiday-cn 2024-11-16 14:12:22 +08:00
NateScarlet
412805386b docs: add jsdelivr badge 2024-11-16 14:12:09 +08:00
renovate[bot]
72dbe5a3a0 chore(deps): update dependency coverage to v7.6.7 (#242)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-15 18:08:37 +00:00
renovate[bot]
acf9c753e7 chore(deps): update dependency coverage to v7.6.5 (#241)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-14 21:36:53 +00:00
NateScarlet
169c3e5d1b docs: update related papers 2024-11-12 21:04:09 +08:00
NateScarlet
9567f22846 chore(deps): update dependency black to v24.10.0 2024-11-12 20:54:44 +08:00
renovate[bot]
cf5e394103 chore(deps): update dependency coverage to v7 2024-11-12 20:49:50 +08:00
renovate[bot]
69146c43de chore(deps): update dependency pytest to v8 2024-11-12 20:47:46 +08:00
NateScarlet
0dedd4f863 ci: update actions/setup-python to v5 2024-11-12 20:44:50 +08:00
NateScarlet
f3e07139d0 ci: update actions/checkout to v4 2024-11-12 20:44:09 +08:00
NateScarlet
97434adcac chore(deps): update python to 3.12 2024-11-12 20:41:06 +08:00
GitHub Actions
6d06f199f8 chore(release): update holiday data
[skip ci]
2024-11-12 12:30:13 +00:00
NateScarlet
a7a1065c70 fix: handle new description 2024-11-12 20:29:26 +08:00
NateScarlet
aefd2f1458 docs: add alternative jsdelivr url 2024-11-11 15:50:44 +08:00
renovate[bot]
5a57998efa chore(deps): update dependency tqdm to v4.67.0 2024-11-06 21:44:51 +00:00
renovate[bot]
d4597e6cf3 chore(deps): update dependency tqdm to v4.66.6 2024-10-28 15:21:23 +00:00
renovate[bot]
14cd952eaa chore(deps): update dependency tqdm to v4.66.5 2024-08-04 04:43:59 +00:00
renovate[bot]
2f78d9d49b chore(deps): update dependency requests to v2.32.3 2024-06-17 19:33:36 +00:00
renovate[bot]
fd01b1d32a chore(deps): update dependency requests to v2.32.2 [security] 2024-06-17 16:09:21 +00:00
renovate[bot]
d5d050fc94 chore(deps): update dependency tqdm to v4.66.4 2024-05-03 03:16:11 +00:00
renovate[bot]
267bfda287 chore(deps): update dependency tqdm to v4.66.2 2024-02-10 21:05:08 +00:00
NateScarlet
ca608d54dd docs: update ghproxy url 2024-01-28 02:55:15 +08:00
NateScarlet
1f8bd77f1c docs: update ghproxy url 2024-01-28 02:46:43 +08:00
NateScarlet
ccea60b3ce docs: add notice about weekend 2024-01-18 19:38:00 +08:00
renovate[bot]
35d55cda4e chore(deps): update dependency beautifulsoup4 to v4.12.3 2024-01-17 21:54:48 +00:00
NateScarlet
385a47c4be docs: update maintenance year 2024-01-03 12:13:56 +08:00
GitHub Actions
87eda11391 chore(release): update holiday data
[skip ci]
2024-01-01 12:13:45 +00:00
renovate[bot]
224b285ae7 chore(deps): update dependency pytest to v7.4.4 2023-12-31 15:52:21 +00:00
renovate[bot]
f4f6d0f174 chore(deps): update dependency black to v23.12.1 2023-12-23 04:27:00 +00:00
renovate[bot]
a08257d14a chore(deps): update dependency black to v23.12.0 2023-12-12 10:18:34 +00:00
renovate[bot]
cc1887d463 chore(deps): update dependency black to v23.11.0 2023-11-08 10:49:55 +00:00
GitHub Actions
b00e2d38a8 chore(release): update holiday data
[skip ci]
2023-10-25 03:11:15 +00:00
NateScarlet
74303b42dd fix: should not check paper url
gov.cn change url frequently
2023-10-25 11:10:37 +08:00
renovate[bot]
00f45649fa chore(deps): update dependency pytest to v7.4.3 2023-10-24 21:51:20 +00:00
renovate[bot]
c05f95b517 chore(deps): update dependency black to v23.10.1 2023-10-24 01:21:05 +00:00
renovate[bot]
26bf12e7c0 chore(deps): update dependency black to v23.10.0 2023-10-17 21:21:53 +00:00
NateScarlet
f439a6750a ci: migrate hub to gh
https://github.com/actions/runner-images/issues/8362
2023-10-08 00:35:13 +08:00
renovate[bot]
85a0a0085b chore(deps): update dependency black to v23.9.1 2023-09-11 07:08:43 +00:00
renovate[bot]
e2c18f51eb chore(deps): update dependency black to v23.9.0 2023-09-09 07:12:17 +00:00
renovate[bot]
122cdf65f3 chore(deps): update dependency pytest to v7.4.2 2023-09-07 21:22:05 +00:00
renovate[bot]
740104579c chore(deps): update dependency icalendar to v4.1.1 2023-09-06 23:00:47 +00:00
renovate[bot]
0533af04bd chore(deps): update dependency pytest to v7.4.1 2023-09-02 19:55:45 +00:00
NateScarlet
c7dc8a194e chore(release): update holiday data
[skip ci]
2023-08-17 23:05:29 +08:00
NateScarlet
cd791e1893 fix: follow gov.cn api change 2023-08-17 22:48:17 +08:00
renovate[bot]
8e4cf83082 chore(deps): update dependency tqdm to v4.66.1 2023-08-10 15:54:48 +00:00
renovate[bot]
ac0ef28ba7 chore(deps): update dependency tqdm to v4.66.0 2023-08-09 17:54:55 +00:00
renovate[bot]
eb94de4808 chore(deps): update dependency tqdm to v4.65.2 2023-08-09 03:20:15 +00:00
renovate[bot]
2f21068a0c chore(deps): update dependency tqdm to v4.65.1 2023-08-08 13:45:37 +00:00
renovate[bot]
932344b48a chore(deps): update dependency black to v23.7.0 2023-07-11 04:54:53 +00:00
renovate[bot]
009e5b342e chore(deps): update dependency pytest to v7.4.0 2023-06-23 16:15:00 +00:00
renovate[bot]
2d410be0a3 chore(deps): update dependency pytest to v7.3.2 2023-06-11 00:27:41 +00:00
renovate[bot]
ef70020a73 chore(deps): update dependency requests to v2.31.0 2023-05-22 21:28:37 +00:00
NateScarlet
d1369f1c05 fix: follow site dom change 2023-05-15 01:58:42 +08:00
NateScarlet
868d0eb712 fix: follow site dom change 2023-05-14 14:24:31 +08:00
renovate[bot]
43ade74e48 chore(deps): update dependency requests to v2.30.0 2023-05-04 17:58:06 +00:00
renovate[bot]
cb9d9297a2 chore(deps): update dependency requests to v2.29.0 2023-04-26 23:04:52 +00:00
renovate[bot]
7225f513be chore(deps): update dependency pytest to v7.3.1 2023-04-14 22:39:37 +00:00
renovate[bot]
df25c19f3c chore(deps): update dependency pytest to v7.3.0 2023-04-08 23:38:42 +00:00
renovate[bot]
4611a6451d chore(deps): update dependency beautifulsoup4 to v4.12.2 2023-04-07 18:31:49 +00:00
renovate[bot]
cd3a247ae7 chore(deps): update dependency beautifulsoup4 to v4.12.1 2023-04-05 21:04:16 +00:00
renovate[bot]
85c1438c7b chore(deps): update dependency black to v23.3.0 2023-03-29 10:30:53 +00:00
renovate[bot]
6ab5c14c2a chore(deps): update dependency beautifulsoup4 to v4.12.0 2023-03-20 15:29:25 +00:00
renovate[bot]
e6c29e0bcd chore(deps): update dependency tqdm to v4.65.0 2023-03-04 11:05:47 +00:00
renovate[bot]
5257ede632 chore(deps): update dependency pytest to v7.2.2 2023-03-04 08:00:36 +00:00
NateScarlet
f5696c2f52 chore(deps): upgrade black to v23.1.0 2023-02-09 22:46:41 +08:00
renovate[bot]
82e0ae1a60 chore(deps): update dependency beautifulsoup4 to v4.11.2 2023-02-01 02:16:22 +00:00
60 changed files with 1922 additions and 426 deletions

View File

@@ -11,10 +11,10 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5
with:
python-version: '3.8'
python-version: '3.12'
- name: Install dependencies
run: pip install -r dev-requirements.txt
- name: Setup git user

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2007.json",
"year": 2007,
"papers": [
"http://www.gov.cn/zhengce/content/2008-03/28/content_1761.htm"
"http://www.gov.cn/zhengce/zhengceku/2008-03/28/content_1761.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2008.json",
"year": 2008,
"papers": [
"http://www.gov.cn/zhengce/content/2008-03/28/content_1645.htm"
"http://www.gov.cn/zhengce/zhengceku/2008-03/28/content_1645.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2009.json",
"year": 2009,
"papers": [
"http://www.gov.cn/zhengce/content/2008-12/10/content_1572.htm"
"http://www.gov.cn/zhengce/zhengceku/2008-12/10/content_1572.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2010.json",
"year": 2010,
"papers": [
"http://www.gov.cn/zhengce/content/2009-12/08/content_1476.htm"
"http://www.gov.cn/zhengce/zhengceku/2009-12/08/content_1476.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2011.json",
"year": 2011,
"papers": [
"http://www.gov.cn/zhengce/content/2010-12/10/content_1423.htm"
"http://www.gov.cn/zhengce/zhengceku/2010-12/10/content_1423.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2012.json",
"year": 2012,
"papers": [
"http://www.gov.cn/zhengce/content/2011-12/06/content_1411.htm"
"http://www.gov.cn/zhengce/zhengceku/2011-12/06/content_1411.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2013.json",
"year": 2013,
"papers": [
"http://www.gov.cn/zhengce/content/2012-12/10/content_1353.htm"
"http://www.gov.cn/zhengce/zhengceku/2012-12/10/content_1353.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2014.json",
"year": 2014,
"papers": [
"http://www.gov.cn/zhengce/content/2014-01/02/content_1194.htm"
"http://www.gov.cn/zhengce/zhengceku/2014-01/02/content_1194.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,8 +3,8 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2015.json",
"year": 2015,
"papers": [
"http://www.gov.cn/zhengce/content/2014-12/16/content_9302.htm",
"http://www.gov.cn/zhengce/content/2015-05/13/content_9742.htm"
"http://www.gov.cn/zhengce/zhengceku/2014-12/16/content_9302.htm",
"http://www.gov.cn/zhengce/zhengceku/2015-05/13/content_9742.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2016.json",
"year": 2016,
"papers": [
"http://www.gov.cn/zhengce/content/2015-12/10/content_10394.htm"
"http://www.gov.cn/zhengce/zhengceku/2015-12/10/content_10394.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2017.json",
"year": 2017,
"papers": [
"http://www.gov.cn/zhengce/content/2016-12/01/content_5141603.htm"
"http://www.gov.cn/zhengce/zhengceku/2016-12/01/content_5141603.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2018.json",
"year": 2018,
"papers": [
"http://www.gov.cn/zhengce/content/2017-11/30/content_5243579.htm"
"http://www.gov.cn/zhengce/zhengceku/2017-11/30/content_5243579.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,8 +3,8 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2019.json",
"year": 2019,
"papers": [
"http://www.gov.cn/zhengce/content/2018-12/06/content_5346276.htm",
"http://www.gov.cn/zhengce/content/2019-03/22/content_5375877.htm"
"http://www.gov.cn/zhengce/zhengceku/2018-12/06/content_5346276.htm",
"http://www.gov.cn/zhengce/zhengceku/2019-03/22/content_5375877.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,8 +3,8 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2020.json",
"year": 2020,
"papers": [
"http://www.gov.cn/zhengce/content/2019-11/21/content_5454164.htm",
"http://www.gov.cn/zhengce/content/2020-01/27/content_5472352.htm"
"http://www.gov.cn/zhengce/zhengceku/2019-11/21/content_5454164.htm",
"http://www.gov.cn/zhengce/zhengceku/2020-01/27/content_5472352.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2021.json",
"year": 2021,
"papers": [
"http://www.gov.cn/zhengce/content/2020-11/25/content_5564127.htm"
"http://www.gov.cn/zhengce/zhengceku/2020-11/25/content_5564127.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2022.json",
"year": 2022,
"papers": [
"http://www.gov.cn/zhengce/content/2021-10/25/content_5644835.htm"
"http://www.gov.cn/zhengce/zhengceku/2021-10/25/content_5644835.htm"
],
"days": [
{

View File

@@ -8,7 +8,7 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD

View File

@@ -3,7 +3,7 @@
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2023.json",
"year": 2023,
"papers": [
"http://www.gov.cn/zhengce/content/2022-12/08/content_5730844.htm"
"http://www.gov.cn/zhengce/zhengceku/2022-12/08/content_5730844.htm"
],
"days": [
{

107
2024.ics
View File

@@ -8,9 +8,114 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20240101
DTEND;VALUE=DATE:20240102
DTSTAMP;VALUE=DATE:20240101
UID:2024-01-01/2024-01-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20240204
DTEND;VALUE=DATE:20240205
DTSTAMP;VALUE=DATE:20240204
UID:2024-02-04/2024-02-05/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:春节假期
DTSTART;VALUE=DATE:20240210
DTEND;VALUE=DATE:20240218
DTSTAMP;VALUE=DATE:20240210
UID:2024-02-10/2024-02-18/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20240218
DTEND;VALUE=DATE:20240219
DTSTAMP;VALUE=DATE:20240218
UID:2024-02-18/2024-02-19/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明节假期
DTSTART;VALUE=DATE:20240404
DTEND;VALUE=DATE:20240407
DTSTAMP;VALUE=DATE:20240404
UID:2024-04-04/2024-04-07/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补清明节假期)
DTSTART;VALUE=DATE:20240407
DTEND;VALUE=DATE:20240408
DTSTAMP;VALUE=DATE:20240407
UID:2024-04-07/2024-04-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20240428
DTEND;VALUE=DATE:20240429
DTSTAMP;VALUE=DATE:20240428
UID:2024-04-28/2024-04-29/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:劳动节假期
DTSTART;VALUE=DATE:20240501
DTEND;VALUE=DATE:20240506
DTSTAMP;VALUE=DATE:20240501
UID:2024-05-01/2024-05-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20240511
DTEND;VALUE=DATE:20240512
DTSTAMP;VALUE=DATE:20240511
UID:2024-05-11/2024-05-12/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午节假期
DTSTART;VALUE=DATE:20240610
DTEND;VALUE=DATE:20240611
DTSTAMP;VALUE=DATE:20240610
UID:2024-06-10/2024-06-11/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补中秋节假期)
DTSTART;VALUE=DATE:20240914
DTEND;VALUE=DATE:20240915
DTSTAMP;VALUE=DATE:20240914
UID:2024-09-14/2024-09-15/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:中秋节假期
DTSTART;VALUE=DATE:20240915
DTEND;VALUE=DATE:20240918
DTSTAMP;VALUE=DATE:20240915
UID:2024-09-15/2024-09-18/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20240929
DTEND;VALUE=DATE:20240930
DTSTAMP;VALUE=DATE:20240929
UID:2024-09-29/2024-09-30/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:国庆节假期
DTSTART;VALUE=DATE:20241001
DTEND;VALUE=DATE:20241008
DTSTAMP;VALUE=DATE:20241001
UID:2024-10-01/2024-10-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20241012
DTEND;VALUE=DATE:20241013
DTSTAMP;VALUE=DATE:20241012
UID:2024-10-12/2024-10-13/NateScarlet/holiday-cn
END:VEVENT
END:VCALENDAR

187
2024.json
View File

@@ -2,6 +2,189 @@
"$schema": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json",
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2024.json",
"year": 2024,
"papers": [],
"days": []
"papers": [
"https://www.gov.cn/zhengce/zhengceku/202310/content_6911528.htm"
],
"days": [
{
"name": "元旦",
"date": "2024-01-01",
"isOffDay": true
},
{
"name": "春节",
"date": "2024-02-04",
"isOffDay": false
},
{
"name": "春节",
"date": "2024-02-10",
"isOffDay": true
},
{
"name": "春节",
"date": "2024-02-11",
"isOffDay": true
},
{
"name": "春节",
"date": "2024-02-12",
"isOffDay": true
},
{
"name": "春节",
"date": "2024-02-13",
"isOffDay": true
},
{
"name": "春节",
"date": "2024-02-14",
"isOffDay": true
},
{
"name": "春节",
"date": "2024-02-15",
"isOffDay": true
},
{
"name": "春节",
"date": "2024-02-16",
"isOffDay": true
},
{
"name": "春节",
"date": "2024-02-17",
"isOffDay": true
},
{
"name": "春节",
"date": "2024-02-18",
"isOffDay": false
},
{
"name": "清明节",
"date": "2024-04-04",
"isOffDay": true
},
{
"name": "清明节",
"date": "2024-04-05",
"isOffDay": true
},
{
"name": "清明节",
"date": "2024-04-06",
"isOffDay": true
},
{
"name": "清明节",
"date": "2024-04-07",
"isOffDay": false
},
{
"name": "劳动节",
"date": "2024-04-28",
"isOffDay": false
},
{
"name": "劳动节",
"date": "2024-05-01",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2024-05-02",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2024-05-03",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2024-05-04",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2024-05-05",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2024-05-11",
"isOffDay": false
},
{
"name": "端午节",
"date": "2024-06-10",
"isOffDay": true
},
{
"name": "中秋节",
"date": "2024-09-14",
"isOffDay": false
},
{
"name": "中秋节",
"date": "2024-09-15",
"isOffDay": true
},
{
"name": "中秋节",
"date": "2024-09-16",
"isOffDay": true
},
{
"name": "中秋节",
"date": "2024-09-17",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2024-09-29",
"isOffDay": false
},
{
"name": "国庆节",
"date": "2024-10-01",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2024-10-02",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2024-10-03",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2024-10-04",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2024-10-05",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2024-10-06",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2024-10-07",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2024-10-12",
"isOffDay": false
}
]
}

93
2025.ics Normal file
View File

@@ -0,0 +1,93 @@
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
CLASS:PUBLIC
X-WR-CALDESC:中国法定节假日数据,自动每日抓取国务院公
告。
X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20250101
DTEND;VALUE=DATE:20250102
DTSTAMP;VALUE=DATE:20250101
UID:2025-01-01/2025-01-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20250126
DTEND;VALUE=DATE:20250127
DTSTAMP;VALUE=DATE:20250126
UID:2025-01-26/2025-01-27/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:春节假期
DTSTART;VALUE=DATE:20250128
DTEND;VALUE=DATE:20250205
DTSTAMP;VALUE=DATE:20250128
UID:2025-01-28/2025-02-05/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20250208
DTEND;VALUE=DATE:20250209
DTSTAMP;VALUE=DATE:20250208
UID:2025-02-08/2025-02-09/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明节假期
DTSTART;VALUE=DATE:20250404
DTEND;VALUE=DATE:20250407
DTSTAMP;VALUE=DATE:20250404
UID:2025-04-04/2025-04-07/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20250427
DTEND;VALUE=DATE:20250428
DTSTAMP;VALUE=DATE:20250427
UID:2025-04-27/2025-04-28/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:劳动节假期
DTSTART;VALUE=DATE:20250501
DTEND;VALUE=DATE:20250506
DTSTAMP;VALUE=DATE:20250501
UID:2025-05-01/2025-05-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午节假期
DTSTART;VALUE=DATE:20250531
DTEND;VALUE=DATE:20250603
DTSTAMP;VALUE=DATE:20250531
UID:2025-05-31/2025-06-03/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节、中秋节假期)
DTSTART;VALUE=DATE:20250928
DTEND;VALUE=DATE:20250929
DTSTAMP;VALUE=DATE:20250928
UID:2025-09-28/2025-09-29/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:国庆节、中秋节假期
DTSTART;VALUE=DATE:20251001
DTEND;VALUE=DATE:20251009
DTSTAMP;VALUE=DATE:20251001
UID:2025-10-01/2025-10-09/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节、中秋节假期)
DTSTART;VALUE=DATE:20251011
DTEND;VALUE=DATE:20251012
DTSTAMP;VALUE=DATE:20251011
UID:2025-10-11/2025-10-12/NateScarlet/holiday-cn
END:VEVENT
END:VCALENDAR

175
2025.json Normal file
View File

@@ -0,0 +1,175 @@
{
"$schema": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json",
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2025.json",
"year": 2025,
"papers": [
"https://www.gov.cn/zhengce/zhengceku/202411/content_6986383.htm"
],
"days": [
{
"name": "元旦",
"date": "2025-01-01",
"isOffDay": true
},
{
"name": "春节",
"date": "2025-01-26",
"isOffDay": false
},
{
"name": "春节",
"date": "2025-01-28",
"isOffDay": true
},
{
"name": "春节",
"date": "2025-01-29",
"isOffDay": true
},
{
"name": "春节",
"date": "2025-01-30",
"isOffDay": true
},
{
"name": "春节",
"date": "2025-01-31",
"isOffDay": true
},
{
"name": "春节",
"date": "2025-02-01",
"isOffDay": true
},
{
"name": "春节",
"date": "2025-02-02",
"isOffDay": true
},
{
"name": "春节",
"date": "2025-02-03",
"isOffDay": true
},
{
"name": "春节",
"date": "2025-02-04",
"isOffDay": true
},
{
"name": "春节",
"date": "2025-02-08",
"isOffDay": false
},
{
"name": "清明节",
"date": "2025-04-04",
"isOffDay": true
},
{
"name": "清明节",
"date": "2025-04-05",
"isOffDay": true
},
{
"name": "清明节",
"date": "2025-04-06",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2025-04-27",
"isOffDay": false
},
{
"name": "劳动节",
"date": "2025-05-01",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2025-05-02",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2025-05-03",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2025-05-04",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2025-05-05",
"isOffDay": true
},
{
"name": "端午节",
"date": "2025-05-31",
"isOffDay": true
},
{
"name": "端午节",
"date": "2025-06-01",
"isOffDay": true
},
{
"name": "端午节",
"date": "2025-06-02",
"isOffDay": true
},
{
"name": "国庆节、中秋节",
"date": "2025-09-28",
"isOffDay": false
},
{
"name": "国庆节、中秋节",
"date": "2025-10-01",
"isOffDay": true
},
{
"name": "国庆节、中秋节",
"date": "2025-10-02",
"isOffDay": true
},
{
"name": "国庆节、中秋节",
"date": "2025-10-03",
"isOffDay": true
},
{
"name": "国庆节、中秋节",
"date": "2025-10-04",
"isOffDay": true
},
{
"name": "国庆节、中秋节",
"date": "2025-10-05",
"isOffDay": true
},
{
"name": "国庆节、中秋节",
"date": "2025-10-06",
"isOffDay": true
},
{
"name": "国庆节、中秋节",
"date": "2025-10-07",
"isOffDay": true
},
{
"name": "国庆节、中秋节",
"date": "2025-10-08",
"isOffDay": true
},
{
"name": "国庆节、中秋节",
"date": "2025-10-11",
"isOffDay": false
}
]
}

107
2026.ics Normal file
View File

@@ -0,0 +1,107 @@
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
CLASS:PUBLIC
X-WR-CALDESC:中国法定节假日数据,自动每日抓取国务院公
告。
X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20260101
DTEND;VALUE=DATE:20260104
DTSTAMP;VALUE=DATE:20260101
UID:2026-01-01/2026-01-04/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补元旦假期)
DTSTART;VALUE=DATE:20260104
DTEND;VALUE=DATE:20260105
DTSTAMP;VALUE=DATE:20260104
UID:2026-01-04/2026-01-05/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20260214
DTEND;VALUE=DATE:20260215
DTSTAMP;VALUE=DATE:20260214
UID:2026-02-14/2026-02-15/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:春节假期
DTSTART;VALUE=DATE:20260215
DTEND;VALUE=DATE:20260224
DTSTAMP;VALUE=DATE:20260215
UID:2026-02-15/2026-02-24/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20260228
DTEND;VALUE=DATE:20260301
DTSTAMP;VALUE=DATE:20260228
UID:2026-02-28/2026-03-01/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明节假期
DTSTART;VALUE=DATE:20260404
DTEND;VALUE=DATE:20260407
DTSTAMP;VALUE=DATE:20260404
UID:2026-04-04/2026-04-07/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:劳动节假期
DTSTART;VALUE=DATE:20260501
DTEND;VALUE=DATE:20260506
DTSTAMP;VALUE=DATE:20260501
UID:2026-05-01/2026-05-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20260509
DTEND;VALUE=DATE:20260510
DTSTAMP;VALUE=DATE:20260509
UID:2026-05-09/2026-05-10/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午节假期
DTSTART;VALUE=DATE:20260619
DTEND;VALUE=DATE:20260622
DTSTAMP;VALUE=DATE:20260619
UID:2026-06-19/2026-06-22/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20260920
DTEND;VALUE=DATE:20260921
DTSTAMP;VALUE=DATE:20260920
UID:2026-09-20/2026-09-21/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:中秋节假期
DTSTART;VALUE=DATE:20260925
DTEND;VALUE=DATE:20260928
DTSTAMP;VALUE=DATE:20260925
UID:2026-09-25/2026-09-28/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:国庆节假期
DTSTART;VALUE=DATE:20261001
DTEND;VALUE=DATE:20261008
DTSTAMP;VALUE=DATE:20261001
UID:2026-10-01/2026-10-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20261010
DTEND;VALUE=DATE:20261011
DTSTAMP;VALUE=DATE:20261010
UID:2026-10-10/2026-10-11/NateScarlet/holiday-cn
END:VEVENT
END:VCALENDAR

205
2026.json Normal file
View File

@@ -0,0 +1,205 @@
{
"$schema": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json",
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2026.json",
"year": 2026,
"papers": [
"https://www.gov.cn/zhengce/zhengceku/202511/content_7047091.htm"
],
"days": [
{
"name": "元旦",
"date": "2026-01-01",
"isOffDay": true
},
{
"name": "元旦",
"date": "2026-01-02",
"isOffDay": true
},
{
"name": "元旦",
"date": "2026-01-03",
"isOffDay": true
},
{
"name": "元旦",
"date": "2026-01-04",
"isOffDay": false
},
{
"name": "春节",
"date": "2026-02-14",
"isOffDay": false
},
{
"name": "春节",
"date": "2026-02-15",
"isOffDay": true
},
{
"name": "春节",
"date": "2026-02-16",
"isOffDay": true
},
{
"name": "春节",
"date": "2026-02-17",
"isOffDay": true
},
{
"name": "春节",
"date": "2026-02-18",
"isOffDay": true
},
{
"name": "春节",
"date": "2026-02-19",
"isOffDay": true
},
{
"name": "春节",
"date": "2026-02-20",
"isOffDay": true
},
{
"name": "春节",
"date": "2026-02-21",
"isOffDay": true
},
{
"name": "春节",
"date": "2026-02-22",
"isOffDay": true
},
{
"name": "春节",
"date": "2026-02-23",
"isOffDay": true
},
{
"name": "春节",
"date": "2026-02-28",
"isOffDay": false
},
{
"name": "清明节",
"date": "2026-04-04",
"isOffDay": true
},
{
"name": "清明节",
"date": "2026-04-05",
"isOffDay": true
},
{
"name": "清明节",
"date": "2026-04-06",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2026-05-01",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2026-05-02",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2026-05-03",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2026-05-04",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2026-05-05",
"isOffDay": true
},
{
"name": "劳动节",
"date": "2026-05-09",
"isOffDay": false
},
{
"name": "端午节",
"date": "2026-06-19",
"isOffDay": true
},
{
"name": "端午节",
"date": "2026-06-20",
"isOffDay": true
},
{
"name": "端午节",
"date": "2026-06-21",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2026-09-20",
"isOffDay": false
},
{
"name": "中秋节",
"date": "2026-09-25",
"isOffDay": true
},
{
"name": "中秋节",
"date": "2026-09-26",
"isOffDay": true
},
{
"name": "中秋节",
"date": "2026-09-27",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2026-10-01",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2026-10-02",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2026-10-03",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2026-10-04",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2026-10-05",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2026-10-06",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2026-10-07",
"isOffDay": true
},
{
"name": "国庆节",
"date": "2026-10-10",
"isOffDay": false
}
]
}

16
2027.ics Normal file
View File

@@ -0,0 +1,16 @@
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
CLASS:PUBLIC
X-WR-CALDESC:中国法定节假日数据,自动每日抓取国务院公
告。
X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD
END:VTIMEZONE
END:VCALENDAR

7
2027.json Normal file
View File

@@ -0,0 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json",
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2027.json",
"year": 2027,
"papers": [],
"days": []
}

View File

@@ -3,16 +3,16 @@
default: format
ifeq ($(OS),Windows_NT)
PYTHON?=py -3.8
PYTHON?=py -3.12
else
PYTHON?=python3
endif
lint:
$(PYTHON) -m black -t py38 --check --diff .
$(PYTHON) -m black -t py312 --check --diff .
format:
$(PYTHON) -m black -t py38 .
$(PYTHON) -m black -t py312 .
.PHONY: test
test:

138
README.md
View File

@@ -3,18 +3,20 @@
[![Build Status](https://github.com/NateScarlet/holiday-cn/workflows/CI/badge.svg)](https://github.com/NateScarlet/holiday-cn/actions)
[![Release](https://img.shields.io/github/release/NateScarlet/holiday-cn.svg)](https://github.com/NateScarlet/holiday-cn/releases/latest)
[![CalVer](https://img.shields.io/badge/calver-YYYY.0M.0D-22bfda.svg)](http://calver.org)
[![Maintainability](https://api.codeclimate.com/v1/badges/c8e9d9c51bd2d858c577/maintainability)](https://codeclimate.com/github/NateScarlet/holiday-cn/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/c8e9d9c51bd2d858c577/test_coverage)](https://codeclimate.com/github/NateScarlet/holiday-cn/test_coverage)
![Maintenance](https://img.shields.io/maintenance/yes/2023.svg)
[![JSDelivr](https://data.jsdelivr.com/v1/package/gh/NateScarlet/holiday-cn/badge?style=rounded)](https://www.jsdelivr.com/package/gh/NateScarlet/holiday-cn)
![Maintenance](https://img.shields.io/maintenance/yes/2024.svg)
中国法定节假日数据 自动每日抓取国务院公告
中国大陆及香港节假日数据
- 中国大陆:自动每日抓取国务院公告
- 香港:来源于香港特别行政区政府 [1823.gov.hk](https://www.1823.gov.hk/common/ical/tc.json),数据覆盖 2024 年起
- [x] 提供 JSON 格式节假日数据
- [x] CI 自动更新
- [x] 数据变化时自动发布新版本 ( `Watch` - `Release only` 以获取邮件提醒! )
- [x] [发布页面]提供 JSON 打包下载
数据格式:
数据格式(中国大陆、香港通用):
[JSON Schema](./schema.json)
@@ -22,7 +24,7 @@
interface Holidays {
/** 完整年份, 整数。*/
year: number;
/** 所用国务院文件网址列表 */
/** 所用数据来源网址列表 */
papers: string[];
days: {
/** 节日名称 */
@@ -37,13 +39,23 @@ interface Holidays {
## 注意事项
**中国大陆**
- 年份是按照国务院文件标题年份而不是日期年份12 月份的日期可能会被下一年的文件影响,因此应检查两个文件。
- `与周末连休` 的周末不是法定节假日,数据里不会包含,见[《全国年节及纪念日放假办法》](https://www.gov.cn/zhengce/content/202411/content_6986380.htm) [#213](https://github.com/NateScarlet/holiday-cn/issues/213#issuecomment-1869546011) [#221](https://github.com/NateScarlet/holiday-cn/issues/221)
**香港**
- 香港不设调休补班制度,数据中不会出现 `isOffDay: false` 的条目。
- 假期名称为繁体中文。
- 数据覆盖范围取决于港府发布进度,通常提前公布至次年。
## 通过互联网使用
提示:任何第三方服务都可能故障或停止服务,如果稳定性要求高请自己搭建静态文件服务。
数据地址格式:
### 中国大陆
`https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{年份}.json`
@@ -51,26 +63,134 @@ interface Holidays {
`https://cdn.jsdelivr.net/gh/NateScarlet/holiday-cn@master/{年份}.json`
`https://fastly.jsdelivr.net/gh/NateScarlet/holiday-cn@master/{年份}.json`
也可尝试使用 [ghproxy](https://github.com/hunshcn/gh-proxy) 或其他 Github 加速:
`https://ghproxy.com/https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{年份}.json`
`https://{ghproxy服务}/https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{年份}.json`
~~访问 github 不方便时可使用国内镜像仓库~~ 2022-08-05: coding 现在要求登录才能下载开源仓库的文件。
~~`https://natescarlet.coding.net/p/github/d/holiday-cn/git/raw/master/{年份}.json`~~
### 香港
`https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/hk/{年份}.json`
## ICalendar 订阅
网址格式参见上一节
### 中国大陆
`{年份}.ics` 为对应年份的节假日
`holiday-cn.ics` 为 3 年前至次年的节假日
### 香港
`hk/{年份}.ics` 为对应年份的节假日
`holiday-hk.ics` 为 3 年前至次年的节假日
感谢 @retanoj 的 ics 格式转换实现
## 作为 git 子模块使用
参见 [Git 工具 - 子模块](https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%AD%90%E6%A8%A1%E5%9D%97)
## 数据生成
安装依赖:
```sh
pip install -r dev-requirements.txt
```
更新当年及次年数据(所有地区):
```sh
python scripts/update.py
```
只更新指定地区:
```sh
python scripts/update.py --region cn # 仅中国大陆
python scripts/update.py --region hk # 仅香港
```
更新所有历史年份(仅中国大陆,香港数据源仅覆盖 2024 年起):
```sh
python scripts/update.py --all --region cn
```
CI 每日自动执行 `python scripts/update.py --release`,数据有变化时自动提交并发布新版本。
## 导入到业务系统teramesh-backend
数据通过 Django management command 导入工作日历:
```sh
# 进入应用容器
kubectl exec -it pod/teramesh-app-0 -- /bin/sh
# 导入所有地区(中国大陆 + 香港)
python manage.py populate_working_calendar
# 只导入指定地区
python manage.py populate_working_calendar --region CN
python manage.py populate_working_calendar --region HK
```
命令会导入当年及次年的假期数据。数据按 `country` 级别写入,部署在香港(`country=HK`)的站点自动使用香港假期,内地站点使用内地假期,无需额外配置。
## 扩展支持新地区
如需接入其他地区(如美国、日本等),按以下步骤操作:
**1. 新增数据抓取模块**
`scripts/` 下新建 `fetch_{地区代码}.py`,实现 `fetch_{地区代码}_holiday(year: int) -> dict`,返回格式与现有地区一致:
```python
{
"year": 2025,
"papers": ["数据来源URL"],
"days": [
{"name": "假期名称", "date": "2025-01-01", "isOffDay": True}
]
}
```
注意:若该地区无调休补班制度,`isOffDay` 始终为 `True`
**2. 在 `scripts/update.py` 的 `REGIONS` 中注册**
```python
REGIONS = {
"cn": { ... },
"hk": { ... },
"us": { # 新增
"fetch": fetch_us_holiday,
"start_year": 2024,
"subdir": "us",
"main_ics_name": "holiday-us.ics",
"cal_name": "美国联邦假期",
"cal_desc": "美国联邦公共假期数据。",
},
}
```
**3. 在 `teramesh-backend` 的 `HOLIDAY_SOURCES` 中注册**
```python
HOLIDAY_SOURCES = {
"CN": f"{GITEA_BASE}/{{year}}.json",
"HK": f"{GITEA_BASE}/hk/{{year}}.json",
"US": f"{GITEA_BASE}/us/{{year}}.json", # 新增
}
```
之后运行 `python manage.py populate_working_calendar --region US` 即可导入,其余地区不受影响。
[发布页面]: https://github.com/NateScarlet/holiday-cn/releases

View File

@@ -1,10 +1,10 @@
# main
requests==2.28.2
beautifulsoup4==4.11.1
tqdm==4.64.1
icalendar==4.1.0
requests==2.32.3
beautifulsoup4==4.12.3
tqdm==4.67.1
icalendar==6.1.0
# test
pytest==7.2.1
coverage==6.5.0
black==22.12.0
pytest==8.3.4
coverage==7.6.9
black==24.10.0

100
hk/2026.ics Normal file
View File

@@ -0,0 +1,100 @@
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
CLASS:PUBLIC
X-WR-CALDESC:香港公众假期数据,来源:香港特别行政区政
府 1823.gov.hk。
X-WR-CALNAME:香港公众假期
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
SUMMARY:一月一日假期
DTSTART;VALUE=DATE:20260101
DTEND;VALUE=DATE:20260102
DTSTAMP;VALUE=DATE:20260101
UID:2026-01-01/2026-01-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:農曆年初一假期
DTSTART;VALUE=DATE:20260217
DTEND;VALUE=DATE:20260220
DTSTAMP;VALUE=DATE:20260217
UID:2026-02-17/2026-02-20/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:耶穌受難節假期
DTSTART;VALUE=DATE:20260403
DTEND;VALUE=DATE:20260405
DTSTAMP;VALUE=DATE:20260403
UID:2026-04-03/2026-04-05/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明節翌日假期
DTSTART;VALUE=DATE:20260406
DTEND;VALUE=DATE:20260408
DTSTAMP;VALUE=DATE:20260406
UID:2026-04-06/2026-04-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:勞動節假期
DTSTART;VALUE=DATE:20260501
DTEND;VALUE=DATE:20260502
DTSTAMP;VALUE=DATE:20260501
UID:2026-05-01/2026-05-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:佛誕翌日假期
DTSTART;VALUE=DATE:20260525
DTEND;VALUE=DATE:20260526
DTSTAMP;VALUE=DATE:20260525
UID:2026-05-25/2026-05-26/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午節假期
DTSTART;VALUE=DATE:20260619
DTEND;VALUE=DATE:20260620
DTSTAMP;VALUE=DATE:20260619
UID:2026-06-19/2026-06-20/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:香港特別行政區成立紀念日假期
DTSTART;VALUE=DATE:20260701
DTEND;VALUE=DATE:20260702
DTSTAMP;VALUE=DATE:20260701
UID:2026-07-01/2026-07-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:中秋節翌日假期
DTSTART;VALUE=DATE:20260926
DTEND;VALUE=DATE:20260927
DTSTAMP;VALUE=DATE:20260926
UID:2026-09-26/2026-09-27/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:國慶日假期
DTSTART;VALUE=DATE:20261001
DTEND;VALUE=DATE:20261002
DTSTAMP;VALUE=DATE:20261001
UID:2026-10-01/2026-10-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:重陽節翌日假期
DTSTART;VALUE=DATE:20261019
DTEND;VALUE=DATE:20261020
DTSTAMP;VALUE=DATE:20261019
UID:2026-10-19/2026-10-20/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:聖誕節假期
DTSTART;VALUE=DATE:20261225
DTEND;VALUE=DATE:20261227
DTSTAMP;VALUE=DATE:20261225
UID:2026-12-25/2026-12-27/NateScarlet/holiday-cn
END:VEVENT
END:VCALENDAR

95
hk/2026.json Normal file
View File

@@ -0,0 +1,95 @@
{
"$schema": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json",
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/hk/2026.json",
"year": 2026,
"papers": [
"https://www.1823.gov.hk/common/ical/tc.json"
],
"days": [
{
"name": "一月一日",
"date": "2026-01-01",
"isOffDay": true
},
{
"name": "農曆年初一",
"date": "2026-02-17",
"isOffDay": true
},
{
"name": "農曆年初二",
"date": "2026-02-18",
"isOffDay": true
},
{
"name": "農曆年初三",
"date": "2026-02-19",
"isOffDay": true
},
{
"name": "耶穌受難節",
"date": "2026-04-03",
"isOffDay": true
},
{
"name": "耶穌受難節翌日",
"date": "2026-04-04",
"isOffDay": true
},
{
"name": "清明節翌日",
"date": "2026-04-06",
"isOffDay": true
},
{
"name": "復活節星期一翌日",
"date": "2026-04-07",
"isOffDay": true
},
{
"name": "勞動節",
"date": "2026-05-01",
"isOffDay": true
},
{
"name": "佛誕翌日",
"date": "2026-05-25",
"isOffDay": true
},
{
"name": "端午節",
"date": "2026-06-19",
"isOffDay": true
},
{
"name": "香港特別行政區成立紀念日",
"date": "2026-07-01",
"isOffDay": true
},
{
"name": "中秋節翌日",
"date": "2026-09-26",
"isOffDay": true
},
{
"name": "國慶日",
"date": "2026-10-01",
"isOffDay": true
},
{
"name": "重陽節翌日",
"date": "2026-10-19",
"isOffDay": true
},
{
"name": "聖誕節",
"date": "2026-12-25",
"isOffDay": true
},
{
"name": "聖誕節後第一個周日",
"date": "2026-12-26",
"isOffDay": true
}
]
}

16
hk/2027.ics Normal file
View File

@@ -0,0 +1,16 @@
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
CLASS:PUBLIC
X-WR-CALDESC:香港公众假期数据,来源:香港特别行政区政
府 1823.gov.hk。
X-WR-CALNAME:香港公众假期
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD
END:VTIMEZONE
END:VCALENDAR

9
hk/2027.json Normal file
View File

@@ -0,0 +1,9 @@
{
"$schema": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json",
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/hk/2027.json",
"year": 2027,
"papers": [
"https://www.1823.gov.hk/common/ical/tc.json"
],
"days": []
}

View File

@@ -8,292 +8,12 @@ X-WR-CALNAME:中国法定节假日
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART;VALUE=DATE-TIME:19700101T000000
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
SUMMARY:上班(补元旦假期)
DTSTART;VALUE=DATE:20181229
DTEND;VALUE=DATE:20181230
DTSTAMP;VALUE=DATE:20181229
UID:2018-12-29/2018-12-30/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20181230
DTEND;VALUE=DATE:20190102
DTSTAMP;VALUE=DATE:20181230
UID:2018-12-30/2019-01-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20190202
DTEND;VALUE=DATE:20190204
DTSTAMP;VALUE=DATE:20190202
UID:2019-02-02/2019-02-04/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:春节假期
DTSTART;VALUE=DATE:20190204
DTEND;VALUE=DATE:20190211
DTSTAMP;VALUE=DATE:20190204
UID:2019-02-04/2019-02-11/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明节假期
DTSTART;VALUE=DATE:20190405
DTEND;VALUE=DATE:20190406
DTSTAMP;VALUE=DATE:20190405
UID:2019-04-05/2019-04-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20190428
DTEND;VALUE=DATE:20190429
DTSTAMP;VALUE=DATE:20190428
UID:2019-04-28/2019-04-29/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:劳动节假期
DTSTART;VALUE=DATE:20190501
DTEND;VALUE=DATE:20190505
DTSTAMP;VALUE=DATE:20190501
UID:2019-05-01/2019-05-05/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20190505
DTEND;VALUE=DATE:20190506
DTSTAMP;VALUE=DATE:20190505
UID:2019-05-05/2019-05-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午节假期
DTSTART;VALUE=DATE:20190607
DTEND;VALUE=DATE:20190608
DTSTAMP;VALUE=DATE:20190607
UID:2019-06-07/2019-06-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:中秋节假期
DTSTART;VALUE=DATE:20190913
DTEND;VALUE=DATE:20190914
DTSTAMP;VALUE=DATE:20190913
UID:2019-09-13/2019-09-14/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20190929
DTEND;VALUE=DATE:20190930
DTSTAMP;VALUE=DATE:20190929
UID:2019-09-29/2019-09-30/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:国庆节假期
DTSTART;VALUE=DATE:20191001
DTEND;VALUE=DATE:20191008
DTSTAMP;VALUE=DATE:20191001
UID:2019-10-01/2019-10-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20191012
DTEND;VALUE=DATE:20191013
DTSTAMP;VALUE=DATE:20191012
UID:2019-10-12/2019-10-13/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20200101
DTEND;VALUE=DATE:20200102
DTSTAMP;VALUE=DATE:20200101
UID:2020-01-01/2020-01-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20200119
DTEND;VALUE=DATE:20200120
DTSTAMP;VALUE=DATE:20200119
UID:2020-01-19/2020-01-20/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:春节假期
DTSTART;VALUE=DATE:20200124
DTEND;VALUE=DATE:20200203
DTSTAMP;VALUE=DATE:20200124
UID:2020-01-24/2020-02-03/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20200203
DTEND;VALUE=DATE:20200204
DTSTAMP;VALUE=DATE:20200203
UID:2020-02-03/2020-02-04/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明节假期
DTSTART;VALUE=DATE:20200404
DTEND;VALUE=DATE:20200407
DTSTAMP;VALUE=DATE:20200404
UID:2020-04-04/2020-04-07/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20200426
DTEND;VALUE=DATE:20200427
DTSTAMP;VALUE=DATE:20200426
UID:2020-04-26/2020-04-27/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:劳动节假期
DTSTART;VALUE=DATE:20200501
DTEND;VALUE=DATE:20200506
DTSTAMP;VALUE=DATE:20200501
UID:2020-05-01/2020-05-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20200509
DTEND;VALUE=DATE:20200510
DTSTAMP;VALUE=DATE:20200509
UID:2020-05-09/2020-05-10/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午节假期
DTSTART;VALUE=DATE:20200625
DTEND;VALUE=DATE:20200628
DTSTAMP;VALUE=DATE:20200625
UID:2020-06-25/2020-06-28/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补端午节假期)
DTSTART;VALUE=DATE:20200628
DTEND;VALUE=DATE:20200629
DTSTAMP;VALUE=DATE:20200628
UID:2020-06-28/2020-06-29/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节、中秋节假期)
DTSTART;VALUE=DATE:20200927
DTEND;VALUE=DATE:20200928
DTSTAMP;VALUE=DATE:20200927
UID:2020-09-27/2020-09-28/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:国庆节、中秋节假期
DTSTART;VALUE=DATE:20201001
DTEND;VALUE=DATE:20201009
DTSTAMP;VALUE=DATE:20201001
UID:2020-10-01/2020-10-09/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节、中秋节假期)
DTSTART;VALUE=DATE:20201010
DTEND;VALUE=DATE:20201011
DTSTAMP;VALUE=DATE:20201010
UID:2020-10-10/2020-10-11/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20210101
DTEND;VALUE=DATE:20210104
DTSTAMP;VALUE=DATE:20210101
UID:2021-01-01/2021-01-04/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20210207
DTEND;VALUE=DATE:20210208
DTSTAMP;VALUE=DATE:20210207
UID:2021-02-07/2021-02-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:春节假期
DTSTART;VALUE=DATE:20210211
DTEND;VALUE=DATE:20210218
DTSTAMP;VALUE=DATE:20210211
UID:2021-02-11/2021-02-18/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20210220
DTEND;VALUE=DATE:20210221
DTSTAMP;VALUE=DATE:20210220
UID:2021-02-20/2021-02-21/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明节假期
DTSTART;VALUE=DATE:20210403
DTEND;VALUE=DATE:20210406
DTSTAMP;VALUE=DATE:20210403
UID:2021-04-03/2021-04-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20210425
DTEND;VALUE=DATE:20210426
DTSTAMP;VALUE=DATE:20210425
UID:2021-04-25/2021-04-26/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:劳动节假期
DTSTART;VALUE=DATE:20210501
DTEND;VALUE=DATE:20210506
DTSTAMP;VALUE=DATE:20210501
UID:2021-05-01/2021-05-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20210508
DTEND;VALUE=DATE:20210509
DTSTAMP;VALUE=DATE:20210508
UID:2021-05-08/2021-05-09/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午节假期
DTSTART;VALUE=DATE:20210612
DTEND;VALUE=DATE:20210615
DTSTAMP;VALUE=DATE:20210612
UID:2021-06-12/2021-06-15/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补中秋节假期)
DTSTART;VALUE=DATE:20210918
DTEND;VALUE=DATE:20210919
DTSTAMP;VALUE=DATE:20210918
UID:2021-09-18/2021-09-19/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:中秋节假期
DTSTART;VALUE=DATE:20210919
DTEND;VALUE=DATE:20210922
DTSTAMP;VALUE=DATE:20210919
UID:2021-09-19/2021-09-22/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20210926
DTEND;VALUE=DATE:20210927
DTSTAMP;VALUE=DATE:20210926
UID:2021-09-26/2021-09-27/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:国庆节假期
DTSTART;VALUE=DATE:20211001
DTEND;VALUE=DATE:20211008
DTSTAMP;VALUE=DATE:20211001
UID:2021-10-01/2021-10-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20211009
DTEND;VALUE=DATE:20211010
DTSTAMP;VALUE=DATE:20211009
UID:2021-10-09/2021-10-10/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20220101
DTEND;VALUE=DATE:20220104
@@ -454,4 +174,277 @@ DTEND;VALUE=DATE:20231009
DTSTAMP;VALUE=DATE:20231007
UID:2023-10-07/2023-10-09/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20240101
DTEND;VALUE=DATE:20240102
DTSTAMP;VALUE=DATE:20240101
UID:2024-01-01/2024-01-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20240204
DTEND;VALUE=DATE:20240205
DTSTAMP;VALUE=DATE:20240204
UID:2024-02-04/2024-02-05/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:春节假期
DTSTART;VALUE=DATE:20240210
DTEND;VALUE=DATE:20240218
DTSTAMP;VALUE=DATE:20240210
UID:2024-02-10/2024-02-18/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20240218
DTEND;VALUE=DATE:20240219
DTSTAMP;VALUE=DATE:20240218
UID:2024-02-18/2024-02-19/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明节假期
DTSTART;VALUE=DATE:20240404
DTEND;VALUE=DATE:20240407
DTSTAMP;VALUE=DATE:20240404
UID:2024-04-04/2024-04-07/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补清明节假期)
DTSTART;VALUE=DATE:20240407
DTEND;VALUE=DATE:20240408
DTSTAMP;VALUE=DATE:20240407
UID:2024-04-07/2024-04-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20240428
DTEND;VALUE=DATE:20240429
DTSTAMP;VALUE=DATE:20240428
UID:2024-04-28/2024-04-29/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:劳动节假期
DTSTART;VALUE=DATE:20240501
DTEND;VALUE=DATE:20240506
DTSTAMP;VALUE=DATE:20240501
UID:2024-05-01/2024-05-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20240511
DTEND;VALUE=DATE:20240512
DTSTAMP;VALUE=DATE:20240511
UID:2024-05-11/2024-05-12/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午节假期
DTSTART;VALUE=DATE:20240610
DTEND;VALUE=DATE:20240611
DTSTAMP;VALUE=DATE:20240610
UID:2024-06-10/2024-06-11/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补中秋节假期)
DTSTART;VALUE=DATE:20240914
DTEND;VALUE=DATE:20240915
DTSTAMP;VALUE=DATE:20240914
UID:2024-09-14/2024-09-15/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:中秋节假期
DTSTART;VALUE=DATE:20240915
DTEND;VALUE=DATE:20240918
DTSTAMP;VALUE=DATE:20240915
UID:2024-09-15/2024-09-18/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20240929
DTEND;VALUE=DATE:20240930
DTSTAMP;VALUE=DATE:20240929
UID:2024-09-29/2024-09-30/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:国庆节假期
DTSTART;VALUE=DATE:20241001
DTEND;VALUE=DATE:20241008
DTSTAMP;VALUE=DATE:20241001
UID:2024-10-01/2024-10-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20241012
DTEND;VALUE=DATE:20241013
DTSTAMP;VALUE=DATE:20241012
UID:2024-10-12/2024-10-13/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20250101
DTEND;VALUE=DATE:20250102
DTSTAMP;VALUE=DATE:20250101
UID:2025-01-01/2025-01-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20250126
DTEND;VALUE=DATE:20250127
DTSTAMP;VALUE=DATE:20250126
UID:2025-01-26/2025-01-27/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:春节假期
DTSTART;VALUE=DATE:20250128
DTEND;VALUE=DATE:20250205
DTSTAMP;VALUE=DATE:20250128
UID:2025-01-28/2025-02-05/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20250208
DTEND;VALUE=DATE:20250209
DTSTAMP;VALUE=DATE:20250208
UID:2025-02-08/2025-02-09/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明节假期
DTSTART;VALUE=DATE:20250404
DTEND;VALUE=DATE:20250407
DTSTAMP;VALUE=DATE:20250404
UID:2025-04-04/2025-04-07/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20250427
DTEND;VALUE=DATE:20250428
DTSTAMP;VALUE=DATE:20250427
UID:2025-04-27/2025-04-28/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:劳动节假期
DTSTART;VALUE=DATE:20250501
DTEND;VALUE=DATE:20250506
DTSTAMP;VALUE=DATE:20250501
UID:2025-05-01/2025-05-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午节假期
DTSTART;VALUE=DATE:20250531
DTEND;VALUE=DATE:20250603
DTSTAMP;VALUE=DATE:20250531
UID:2025-05-31/2025-06-03/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节、中秋节假期)
DTSTART;VALUE=DATE:20250928
DTEND;VALUE=DATE:20250929
DTSTAMP;VALUE=DATE:20250928
UID:2025-09-28/2025-09-29/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:国庆节、中秋节假期
DTSTART;VALUE=DATE:20251001
DTEND;VALUE=DATE:20251009
DTSTAMP;VALUE=DATE:20251001
UID:2025-10-01/2025-10-09/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节、中秋节假期)
DTSTART;VALUE=DATE:20251011
DTEND;VALUE=DATE:20251012
DTSTAMP;VALUE=DATE:20251011
UID:2025-10-11/2025-10-12/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:元旦假期
DTSTART;VALUE=DATE:20260101
DTEND;VALUE=DATE:20260104
DTSTAMP;VALUE=DATE:20260101
UID:2026-01-01/2026-01-04/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补元旦假期)
DTSTART;VALUE=DATE:20260104
DTEND;VALUE=DATE:20260105
DTSTAMP;VALUE=DATE:20260104
UID:2026-01-04/2026-01-05/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20260214
DTEND;VALUE=DATE:20260215
DTSTAMP;VALUE=DATE:20260214
UID:2026-02-14/2026-02-15/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:春节假期
DTSTART;VALUE=DATE:20260215
DTEND;VALUE=DATE:20260224
DTSTAMP;VALUE=DATE:20260215
UID:2026-02-15/2026-02-24/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补春节假期)
DTSTART;VALUE=DATE:20260228
DTEND;VALUE=DATE:20260301
DTSTAMP;VALUE=DATE:20260228
UID:2026-02-28/2026-03-01/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明节假期
DTSTART;VALUE=DATE:20260404
DTEND;VALUE=DATE:20260407
DTSTAMP;VALUE=DATE:20260404
UID:2026-04-04/2026-04-07/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:劳动节假期
DTSTART;VALUE=DATE:20260501
DTEND;VALUE=DATE:20260506
DTSTAMP;VALUE=DATE:20260501
UID:2026-05-01/2026-05-06/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补劳动节假期)
DTSTART;VALUE=DATE:20260509
DTEND;VALUE=DATE:20260510
DTSTAMP;VALUE=DATE:20260509
UID:2026-05-09/2026-05-10/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午节假期
DTSTART;VALUE=DATE:20260619
DTEND;VALUE=DATE:20260622
DTSTAMP;VALUE=DATE:20260619
UID:2026-06-19/2026-06-22/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20260920
DTEND;VALUE=DATE:20260921
DTSTAMP;VALUE=DATE:20260920
UID:2026-09-20/2026-09-21/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:中秋节假期
DTSTART;VALUE=DATE:20260925
DTEND;VALUE=DATE:20260928
DTSTAMP;VALUE=DATE:20260925
UID:2026-09-25/2026-09-28/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:国庆节假期
DTSTART;VALUE=DATE:20261001
DTEND;VALUE=DATE:20261008
DTSTAMP;VALUE=DATE:20261001
UID:2026-10-01/2026-10-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:上班(补国庆节假期)
DTSTART;VALUE=DATE:20261010
DTEND;VALUE=DATE:20261011
DTSTAMP;VALUE=DATE:20261010
UID:2026-10-10/2026-10-11/NateScarlet/holiday-cn
END:VEVENT
END:VCALENDAR

100
holiday-hk.ics Normal file
View File

@@ -0,0 +1,100 @@
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
CLASS:PUBLIC
X-WR-CALDESC:香港公众假期数据,来源:香港特别行政区政
府 1823.gov.hk。
X-WR-CALNAME:香港公众假期
BEGIN:VTIMEZONE
TZID:Asia/Shanghai
BEGIN:STANDARD
DTSTART:19700101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
SUMMARY:一月一日假期
DTSTART;VALUE=DATE:20260101
DTEND;VALUE=DATE:20260102
DTSTAMP;VALUE=DATE:20260101
UID:2026-01-01/2026-01-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:農曆年初一假期
DTSTART;VALUE=DATE:20260217
DTEND;VALUE=DATE:20260220
DTSTAMP;VALUE=DATE:20260217
UID:2026-02-17/2026-02-20/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:耶穌受難節假期
DTSTART;VALUE=DATE:20260403
DTEND;VALUE=DATE:20260405
DTSTAMP;VALUE=DATE:20260403
UID:2026-04-03/2026-04-05/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:清明節翌日假期
DTSTART;VALUE=DATE:20260406
DTEND;VALUE=DATE:20260408
DTSTAMP;VALUE=DATE:20260406
UID:2026-04-06/2026-04-08/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:勞動節假期
DTSTART;VALUE=DATE:20260501
DTEND;VALUE=DATE:20260502
DTSTAMP;VALUE=DATE:20260501
UID:2026-05-01/2026-05-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:佛誕翌日假期
DTSTART;VALUE=DATE:20260525
DTEND;VALUE=DATE:20260526
DTSTAMP;VALUE=DATE:20260525
UID:2026-05-25/2026-05-26/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:端午節假期
DTSTART;VALUE=DATE:20260619
DTEND;VALUE=DATE:20260620
DTSTAMP;VALUE=DATE:20260619
UID:2026-06-19/2026-06-20/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:香港特別行政區成立紀念日假期
DTSTART;VALUE=DATE:20260701
DTEND;VALUE=DATE:20260702
DTSTAMP;VALUE=DATE:20260701
UID:2026-07-01/2026-07-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:中秋節翌日假期
DTSTART;VALUE=DATE:20260926
DTEND;VALUE=DATE:20260927
DTSTAMP;VALUE=DATE:20260926
UID:2026-09-26/2026-09-27/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:國慶日假期
DTSTART;VALUE=DATE:20261001
DTEND;VALUE=DATE:20261002
DTSTAMP;VALUE=DATE:20261001
UID:2026-10-01/2026-10-02/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:重陽節翌日假期
DTSTART;VALUE=DATE:20261019
DTEND;VALUE=DATE:20261020
DTSTAMP;VALUE=DATE:20261019
UID:2026-10-19/2026-10-20/NateScarlet/holiday-cn
END:VEVENT
BEGIN:VEVENT
SUMMARY:聖誕節假期
DTSTART;VALUE=DATE:20261225
DTEND;VALUE=DATE:20261227
DTSTAMP;VALUE=DATE:20261225
UID:2026-12-25/2026-12-27/NateScarlet/holiday-cn
END:VEVENT
END:VCALENDAR

View File

@@ -1,3 +1,7 @@
{
"extends": ["config:base", ":automergeMinor"]
"extends": [
"config:best-practices",
":automergeMinor",
":disableDependencyDashboard"
]
}

View File

@@ -1,4 +1,9 @@
[
{
"year": 2025,
"description": "1月1日周三放假1天不调休。",
"expected": [{ "date": "2025-01-01", "isOffDay": true }]
},
{
"year": 2019,
"description": "2018年12月30日至2019年1月1日放假调休共3天。2018年12月29日星期六上班。",

View File

@@ -11,17 +11,16 @@ from typing import Iterator, List, Optional, Tuple
import bs4
import requests
SEARCH_URL = "http://sousuo.gov.cn/s.htm"
PAPER_EXCLUDE = [
"http://www.gov.cn/zhengce/content/2014-09/29/content_9102.htm",
"http://www.gov.cn/zhengce/content/2015-02/09/content_9466.htm",
"http://www.gov.cn/zhengce/zhengceku/2014-09/29/content_9102.htm",
"http://www.gov.cn/zhengce/zhengceku/2015-02/09/content_9466.htm",
]
PAPER_INCLUDE = {
2015: ["http://www.gov.cn/zhengce/content/2015-05/13/content_9742.htm"]
2015: ["http://www.gov.cn/zhengce/zhengceku/2015-05/13/content_9742.htm"]
}
PRE_PARSED_PAPERS = {
"http://www.gov.cn/zhengce/content/2015-05/13/content_9742.htm": [
"http://www.gov.cn/zhengce/zhengceku/2015-05/13/content_9742.htm": [
{
"name": "抗日战争暨世界反法西斯战争胜利70周年纪念日",
"date": date(2015, 9, 3),
@@ -43,7 +42,7 @@ PRE_PARSED_PAPERS = {
"isOffDay": False,
},
],
"http://www.gov.cn/zhengce/content/2020-01/27/content_5472352.htm": [
"http://www.gov.cn/zhengce/zhengceku/2020-01/27/content_5472352.htm": [
{
"name": "春节",
"date": date(2020, 1, 31),
@@ -77,6 +76,40 @@ def _raise_for_status_200(resp: requests.Response):
)
def _get_paper_urls(year: int) -> Iterator[str]:
has_next_page = True
page_index = 0
while has_next_page:
resp = requests.get(
"https://sousuo.www.gov.cn/search-gov/data",
params={
"t": "zhengcelibrary_gw",
"p": page_index,
"n": 5,
"q": "假期 %d" % (year,),
"pcodeJiguan": "国办发明电",
"puborg": "国务院办公厅",
"filetype": "通知",
"sort": "pubtime",
},
)
_raise_for_status_200(resp)
data = resp.json()
if data["code"] == 1001:
# no match
return
assert data["code"] == 200, "%s: %s: %s" % (
resp.url,
data["code"],
data["msg"],
)
for i in data["searchVO"]["listVO"]:
if str(year) in i["title"]:
yield i["url"]
page_index += 1
has_next_page = page_index < data["searchVO"]["totalpage"]
def get_paper_urls(year: int) -> List[str]:
"""Find year related paper urls.
@@ -84,29 +117,14 @@ def get_paper_urls(year: int) -> List[str]:
year (int): eg. 2018
Returns:
List[str]: Urls newlest first.
List[str]: Urls sort by publish time.
"""
resp = requests.get(
SEARCH_URL,
params={
"t": "paper",
"advance": "true",
"title": year,
"q": "假期",
"pcodeJiguan": "国办发明电",
"puborg": "国务院办公厅",
},
)
_raise_for_status_200(resp)
ret = re.findall(
r'<li class="res-list".*?<a href="(.+?)".*?</li>', resp.text, flags=re.S
)
ret = [i for i in ret if i not in PAPER_EXCLUDE]
ret = [i for i in _get_paper_urls(year) if i not in PAPER_EXCLUDE]
ret += PAPER_INCLUDE.get(year, [])
ret.sort()
if not ret and date.today().year >= year:
raise RuntimeError("could not found papers for %d" % year)
raise RuntimeError("could not found papers for %d" % (year,))
return ret
@@ -120,18 +138,19 @@ def get_paper(url: str) -> str:
str: Extracted paper text.
"""
assert re.match(
r"http://www.gov.cn/zhengce/content/\d{4}-\d{2}/\d{2}/content_\d+.htm", url
), "Site changed, need human verify"
response = requests.get(url)
_raise_for_status_200(response)
response.encoding = "utf-8"
soup = bs4.BeautifulSoup(response.text, features="html.parser")
container = soup.find("td", class_="b12c")
assert container, f"Can not get paper container from url: {url}"
ret = container.get_text().replace("\u3000\u3000", "\n")
assert ret, f"Can not get paper content from url: {url}"
container = soup.find(id="UCAP-CONTENT")
assert isinstance(
container, bs4.Tag
), f"Can not get paper container from url: {url}"
p = bs4.BeautifulSoup(
container.decode().replace("<br/>", "</p><p>"), features="html.parser"
).find_all("p")
ret = "\n".join((i.get_text().strip() for i in p))
assert ret, f"can not get paper content from url: {url}"
return ret
@@ -258,7 +277,7 @@ class DescriptionParser:
class SentenceParser:
"""Parser for holiday shift description sentence."""
def __init__(self, parent: DescriptionParser, sentence):
def __init__(self, parent: DescriptionParser, sentence: str):
self.parent = parent
self.sentence = sentence
@@ -297,7 +316,8 @@ class SentenceParser:
def _extract_dates_2(self, value: str) -> Iterator[date]:
value = re.sub(r".+?", "", value)
match = re.findall(
r"(?:(\d+)年)?(?:(\d+)月)?(\d+)日(?:至|-|—)(?:(\d+)年)?(?:(\d+)月)?(\d+)日", value
r"(?:(\d+)年)?(?:(\d+)月)?(\d+)日(?:至|-|—)(?:(\d+)年)?(?:(\d+)月)?(\d+)日",
value,
)
for groups in match:
groups = [_cast_int(i) for i in groups]
@@ -338,6 +358,8 @@ class SentenceParser:
yield i
def _parse_rest_1(self):
if self.sentence.startswith(""):
return
match = re.match(r"(.+)(放假|补休|调休|公休)+(?:\d+天)?$", self.sentence)
if match:
for i in self.extract_dates(match.group(1)):

45
scripts/fetch_hk.py Normal file
View File

@@ -0,0 +1,45 @@
"""Fetch Hong Kong public holiday data from 1823.gov.hk."""
import datetime
import requests
# Traditional Chinese names, consistent with CN data format
HK_ICAL_URL = "https://www.1823.gov.hk/common/ical/tc.json"
# Earliest year available from the 1823.gov.hk API
HK_START_YEAR = 2024
def fetch_hk_holiday(year: int) -> dict:
"""Fetch HK public holidays for a given year.
HK has no makeup work day (调休) concept, so all entries are isOffDay=True.
Data coverage starts from HK_START_YEAR.
"""
response = requests.get(HK_ICAL_URL)
response.raise_for_status()
data = response.json()
events = data["vcalendar"][0]["vevent"]
days = []
for event in events:
dtstart = event["dtstart"][0] # "YYYYMMDD"
date = datetime.date(int(dtstart[:4]), int(dtstart[4:6]), int(dtstart[6:8]))
if date.year != year:
continue
days.append(
{
"name": event["summary"],
"date": date.isoformat(),
"isOffDay": True,
}
)
days.sort(key=lambda d: d["date"])
return {
"year": year,
"papers": [HK_ICAL_URL],
"days": days,
}

View File

@@ -1,4 +1,5 @@
"""Test module `fetch_holidays`. """
import json
import pytest
@@ -16,8 +17,8 @@ from filetools import workspace_path
def test_get_paper_urls():
assert get_paper_urls(2019) == [
"http://www.gov.cn/zhengce/content/2018-12/06/content_5346276.htm",
"http://www.gov.cn/zhengce/content/2019-03/22/content_5375877.htm",
"http://www.gov.cn/zhengce/zhengceku/2018-12/06/content_5346276.htm",
"http://www.gov.cn/zhengce/zhengceku/2019-03/22/content_5375877.htm",
]
@@ -25,12 +26,39 @@ def test_get_rules():
assert list(
get_rules(
get_paper(
"http://www.gov.cn/zhengce/content/2019-03/22/content_5375877.htm"
"http://www.gov.cn/zhengce/zhengceku/2019-03/22/content_5375877.htm"
)
)
) == [("劳动节", "2019年5月1日至4日放假调休共4天。4月28日星期日、5月5日星期日上班。")]
def test_get_rules_2023():
got = list(
get_rules(
get_paper(
"http://www.gov.cn/zhengce/zhengceku/2022-12/08/content_5730844.htm"
)
)
)
assert got == [
("元旦", "2022年12月31日至2023年1月2日放假调休共3天。"),
(
"春节",
"1月21日至27日放假调休共7天。1月28日星期六、1月29日星期日上班。",
),
("清明节", "4月5日放假共1天。"),
(
"劳动节",
"4月29日至5月3日放假调休共5天。4月23日星期日、5月6日星期六上班。",
),
("端午节", "6月22日至24日放假调休共3天。6月25日星期日上班。"),
(
"中秋节、国庆节",
"9月29日至10月6日放假调休共8天。10月7日星期六、10月8日星期日上班。",
),
]
def _normalize(iterable):
return sorted(
json.loads(json.dumps(list(iterable), cls=CustomJSONEncoder)),
@@ -49,7 +77,6 @@ def _description_parsing_cases():
@pytest.mark.parametrize("case", _description_parsing_cases())
def test_parse_description(case):
year, description, expected = case["year"], case["description"], case["expected"]
assert _normalize(DescriptionParser(description, year).parse()) == _normalize(
expected

View File

@@ -6,5 +6,4 @@ __dirname__ = os.path.abspath(os.path.dirname(__file__))
def workspace_path(*other):
return os.path.join(os.path.dirname(__dirname__), *other)

View File

@@ -60,11 +60,16 @@ def _iter_date_ranges(days: Sequence[dict]) -> Iterator[Tuple[dict, dict]]:
yield fr, to
def generate_ics(days: Sequence[dict], filename: Text) -> None:
def generate_ics(
days: Sequence[dict],
filename: Text,
cal_name: str = "中国法定节假日",
cal_desc: str = "中国法定节假日数据,自动每日抓取国务院公告。",
) -> None:
"""Generate ics from days."""
cal = Calendar()
cal.add("X-WR-CALNAME", "中国法定节假日")
cal.add("X-WR-CALDESC", "中国法定节假日数据,自动每日抓取国务院公告。")
cal.add("X-WR-CALNAME", cal_name)
cal.add("X-WR-CALDESC", cal_desc)
cal.add("VERSION", "2.0")
cal.add("METHOD", "PUBLISH")
cal.add("CLASS", "PUBLIC")

View File

@@ -14,9 +14,32 @@ from zipfile import ZipFile
from tqdm import tqdm
from fetch import CustomJSONEncoder, fetch_holiday
from fetch_hk import HK_START_YEAR, fetch_hk_holiday
from generate_ics import generate_ics
from filetools import workspace_path
SCHEMA_URL = "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json"
GITHUB_RAW_BASE = "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master"
REGIONS = {
"cn": {
"fetch": fetch_holiday,
"start_year": 2007,
"subdir": None,
"main_ics_name": "holiday-cn.ics",
"cal_name": "中国法定节假日",
"cal_desc": "中国法定节假日数据,自动每日抓取国务院公告。",
},
"hk": {
"fetch": fetch_hk_holiday,
"start_year": HK_START_YEAR,
"subdir": "hk",
"main_ics_name": "holiday-hk.ics",
"cal_name": "香港公众假期",
"cal_desc": "香港公众假期数据,来源:香港特别行政区政府 1823.gov.hk。",
},
}
class ChinaTimezone(tzinfo):
"""Timezone of china."""
@@ -31,25 +54,34 @@ class ChinaTimezone(tzinfo):
return timedelta()
def update_data(year: int) -> Iterator[str]:
"""Update and store data for a year."""
def _region_paths(region: str, year: int):
"""Return (json_path, ics_path, id_url) for a region and year."""
subdir = REGIONS[region]["subdir"]
if subdir:
os.makedirs(workspace_path(subdir), exist_ok=True)
json_path = workspace_path(subdir, f"{year}.json")
ics_path = workspace_path(subdir, f"{year}.ics")
id_url = f"{GITHUB_RAW_BASE}/{subdir}/{year}.json"
else:
json_path = workspace_path(f"{year}.json")
ics_path = workspace_path(f"{year}.ics")
id_url = f"{GITHUB_RAW_BASE}/{year}.json"
return json_path, ics_path, id_url
json_filename = workspace_path(f"{year}.json")
ics_filename = workspace_path(f"{year}.ics")
with open(json_filename, "w", encoding="utf-8", newline="\n") as f:
data = fetch_holiday(year)
def update_data(year: int, region: str = "cn") -> Iterator[str]:
"""Update and store data for a year and region."""
cfg = REGIONS[region]
json_path, ics_path, id_url = _region_paths(region, year)
data = cfg["fetch"](year)
with open(json_path, "w", encoding="utf-8", newline="\n") as f:
json.dump(
dict(
(
(
"$schema",
"https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json",
),
(
"$id",
f"https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{year}.json",
),
("$schema", SCHEMA_URL),
("$id", id_url),
*data.items(),
)
),
@@ -59,25 +91,38 @@ def update_data(year: int) -> Iterator[str]:
cls=CustomJSONEncoder,
)
yield json_filename
generate_ics(data["days"], ics_filename)
yield ics_filename
yield json_path
generate_ics(
data["days"],
ics_path,
cal_name=cfg["cal_name"],
cal_desc=cfg["cal_desc"],
)
yield ics_path
def update_main_ics(fr_year, to_year):
def update_main_ics(fr_year: int, to_year: int, region: str = "cn"):
cfg = REGIONS[region]
subdir = cfg["subdir"]
all_days = []
for year in range(fr_year, to_year + 1):
if subdir:
filename = workspace_path(subdir, f"{year}.json")
else:
filename = workspace_path(f"{year}.json")
if not os.path.isfile(filename):
continue
with open(filename, "r", encoding="utf8") as inf:
data = json.loads(inf.read())
all_days.extend(data.get("days"))
all_days.extend(data.get("days", []))
filename = workspace_path("holiday-cn.ics")
filename = workspace_path(cfg["main_ics_name"])
generate_ics(
all_days,
filename,
cal_name=cfg["cal_name"],
cal_desc=cfg["cal_desc"],
)
return filename
@@ -87,30 +132,41 @@ def main():
parser.add_argument(
"--all",
action="store_true",
help="Update all years since 2007, default is this year and next year",
help="Update all years since each region's start year, default is this year and next year",
)
parser.add_argument(
"--release",
action="store_true",
help="create new release if repository data is not up to date",
)
parser.add_argument(
"--region",
choices=list(REGIONS.keys()),
default=None,
help="Region to update (default: all regions)",
)
args = parser.parse_args()
now = datetime.now(ChinaTimezone())
is_release = args.release
regions_to_update = list(REGIONS.keys()) if args.region is None else [args.region]
filenames = []
progress = tqdm(range(2007 if args.all else now.year, now.year + 2))
for i in progress:
progress.set_description(f"Updating {i} data")
filenames += list(update_data(i))
progress.set_description("Updating holiday-cn.ics")
filenames.append(update_main_ics(now.year - 4, now.year + 1))
for region in regions_to_update:
cfg = REGIONS[region]
year_start = cfg["start_year"] if args.all else max(cfg["start_year"], now.year)
progress = tqdm(range(year_start, now.year + 2))
for year in progress:
progress.set_description(f"Updating {region} {year}")
filenames += list(update_data(year, region))
progress.set_description(f"Updating {cfg['main_ics_name']}")
filenames.append(update_main_ics(now.year - 4, now.year + 1, region))
print("")
subprocess.run(["hub", "add", *filenames], check=True)
subprocess.run(["git", "add", *filenames], check=True)
diff = subprocess.run(
["hub", "diff", "--stat", "--cached", "*.json", "*.ics"],
["git", "diff", "--stat", "--cached"],
check=True,
stdout=subprocess.PIPE,
encoding="utf-8",
@@ -125,7 +181,7 @@ def main():
subprocess.run(
[
"hub",
"git",
"commit",
"-m",
"chore(release): update holiday data",
@@ -134,7 +190,7 @@ def main():
],
check=True,
)
subprocess.run(["hub", "push"], check=True)
subprocess.run(["git", "push"], check=True)
tag = now.strftime("%Y.%m.%d")
temp_note_fd, temp_note_name = mkstemp()
@@ -146,14 +202,13 @@ def main():
subprocess.run(
[
"hub",
"gh",
"release",
"create",
"-F",
temp_note_name,
"-a",
f"{zip_path}#JSON数据",
tag,
f"{zip_path}#JSON数据",
],
check=True,
)
@@ -161,13 +216,23 @@ def main():
def pack_data(file):
"""Pack data json in zip file."""
"""Pack all region JSON data into a zip file."""
zip_file = ZipFile(file, "w")
for i in os.listdir(workspace_path()):
if not re.match(r"\d+\.json", i):
# Root-level {year}.json files (CN)
for name in os.listdir(workspace_path()):
if re.match(r"\d+\.json", name):
zip_file.write(workspace_path(name), name)
# Subdirectory region files (e.g. hk/{year}.json)
for region, cfg in REGIONS.items():
subdir = cfg["subdir"]
if not subdir:
continue
zip_file.write(workspace_path(i), i)
subdir_path = workspace_path(subdir)
if not os.path.isdir(subdir_path):
continue
for name in os.listdir(subdir_path):
if re.match(r"\d+\.json", name):
zip_file.write(workspace_path(subdir, name), f"{subdir}/{name}")
if __name__ == "__main__":