CustomCalendar generates Chinese iCalendar (.ics) subscription files for iOS, macOS, and other calendar clients.
It includes public holidays, adjusted workdays, lunar calendar data, Ganzhi, solar terms, Xiu, Yi/Ji, Caiwei, moon phases, anniversaries, and combined calendars.
Generated files live in dist/.
| File | Calendar name | Contents |
|---|---|---|
holidays.ics |
国定节假日 | Chinese public holidays |
workdays.ics |
调休上班 | Adjusted workdays |
lunar_date.ics |
农历日期 | Lunar month and day |
lunar_ganzhi.ics |
天干地支 | Year, month, and day Ganzhi |
lunar_date_ganzhi.ics |
农历日期+天干地支 | Lunar date and Ganzhi in one event |
lunar_jieqi.ics |
二十四节气 | Solar terms |
lunar_xingxiu.ics |
二十八星宿 | Xiu |
xingxiu_moon_phases.ics |
星宿+月相 | Xiu and moon phase in one event |
lunar_yiji.ics |
宜忌吉凶 | Daily Yi/Ji |
lunar_caiwei.ics |
财位 | Daily Caiwei |
moon_phases.ics |
月相 | Moon phase |
anniversaries.ics |
纪念日 | Custom anniversaries from config.yaml |
all_in_one.ics |
汇总日历 | Combined calendar with all original sources |
Do not subscribe to all_in_one.ics together with the single-source files unless duplicate-looking events are acceptable.
Calendar data is generated locally from the Python dependencies in requirements.txt and the user configuration in config.yaml.
| Data | Source |
|---|---|
| Public holidays and adjusted workdays | chinesecalendar |
| Lunar date, Ganzhi, solar terms, Xiu, Yi/Ji, and Caiwei | lunar-python |
| Moon phases | astral |
| Custom anniversaries | config.yaml |
| iCalendar serialization | icalendar |
Future public-holiday arrangements depend on the chinesecalendar package. If an official future-year holiday schedule has not been published or is not included by the dependency yet, the generator falls back to normal weekend/workday logic for unsupported years.
Lunar and almanac fields follow the algorithms and rule tables provided by lunar-python. Lunar dates, Ganzhi, and solar terms are generally suitable for everyday calendar reference, but almanac-style fields such as Xiu, Yi/Ji, and Caiwei may differ from Hong Kong TV programs, printed Tong Shu, calendar publishers, or other almanac sources because those sources can use different rule traditions and presentation conventions.
Use a stable raw URL such as:
https://raw.githubusercontent.com/mangataw/CustomCalendar/main/dist/holidays.ics
Replace holidays.ics with any file listed above.
On iOS:
- Open Settings.
- Go to Calendar > Accounts > Add Account > Other.
- Choose Add Subscribed Calendar.
- Paste the raw
.icsURL.
iOS controls the actual refresh interval. This project keeps the URL and event UIDs stable so that refreshed .ics content can be matched to existing subscribed events.
UID stability is the key for subscribed-calendar updates.
Each event UID is generated from:
YYYYMMDD-event_type@kaze.calendar.github
Examples:
20250101-lunar_date@kaze.calendar.github
20250101-lunar_date_ganzhi@kaze.calendar.github
20250101-xingxiu_moon_phase@kaze.calendar.github
20250618-anniv_important_day@kaze.calendar.github
Custom anniversaries must have a stable id in config.yaml. Changing an anniversary title only changes the visible summary. Changing its id changes the UID, so calendar clients may treat it as a different event.
The generated events also include:
DTSTAMP
LAST-MODIFIED
SEQUENCE:0
TRANSP:TRANSPARENT
Calendars include:
VERSION:2.0
PRODID:-//Kaze//Calendar Generator//CN
CALSCALE:GREGORIAN
X-WR-CALNAME
X-WR-TIMEZONE:Asia/Shanghai
Edit config.yaml:
calendar_range:
years_backward: 1
years_forward: 2
anniversaries:
- id: "important_day"
date: "06-18"
title: "某个重要的纪念日"
start_year: 2023The default range generates last year, this year, and next year.
python -m pip install -r requirements.txt
python generator.pypython -m unittest tests.test_generated_icsThe tests check that generated calendars contain standard metadata, that UIDs are unique and ASCII-only, and that the combined calendars are generated with stable UID patterns.
.github/workflows/generate.yml runs the generator every December 1 and can also be triggered manually from GitHub Actions.
The workflow commits changes under dist/*.ics, so subscribed clients can receive updated content from the same raw URLs.