Comprehensive Chinese lunar calendar library with Solar calendar conversion and traditional Chinese calendar features.
79
Comprehensive utility functions and constants for Chinese calendar calculations, holiday determinations, astronomical calculations, and supporting data structures.
Core utility class containing constants and helper functions for lunar calendar calculations.
class LunarUtil:
# Heavenly Stems (天干) - 10 elements
GAN: tuple = ('甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸')
# Earthly Branches (地支) - 12 elements
ZHI: tuple = ('子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥')
# 60 Stem-Branch Combinations (六十甲子)
JIA_ZI: tuple # 60 combinations starting with 甲子
# Chinese Zodiac Animals (生肖)
SHENGXIAO: tuple = ('鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪')
# Chinese Number Names
NUMBER: tuple = ('〇', '一', '二', '三', '四', '五', '六', '七', '八', '九')
# Chinese Month Names
MONTH: tuple = ('正月', '二月', '三月', '四月', '五月', '六月',
'七月', '八月', '九月', '十月', '十一月', '十二月')
# Chinese Day Names
DAY: tuple # 30 day names (初一, 初二, ..., 三十)class LunarUtil:
# 10-day cycles (旬)
XUN: tuple = ('甲子', '甲戌', '甲申', '甲午', '甲辰', '甲寅')
# Void periods within cycles (旬空)
XUN_KONG: tuple = ('戌亥', '申酉', '午未', '辰巳', '寅卯', '子丑')class LunarUtil:
# Major Lunar Festivals
FESTIVAL: dict # Lunar festivals by month-day
# Other Lunar Festivals
OTHER_FESTIVAL: dict # Additional lunar observancesclass LunarUtil:
# Deity Position Arrays
POSITION_XI: tuple # Joy god positions by day stem
POSITION_YANG_GUI: tuple # Yang noble person positions
POSITION_YIN_GUI: tuple # Yin noble person positions
POSITION_FU: tuple # Fortune god positions
POSITION_FU_2: tuple # Alternative fortune god positions
POSITION_CAI: tuple # Wealth god positions
POSITION_CAI_2: tuple # Alternative wealth god positions
# Tai Sui positions
POSITION_TAI_SUI_YEAR: tuple # Yearly Tai Sui positions
POSITION_TAI_SUI_MONTH: tuple # Monthly Tai Sui positions
# Fetal god positions
POSITION_TAI: tuple # Daily fetal god positionsclass LunarUtil:
# Five Elements for Stems
WU_XING_GAN: tuple = ('木', '木', '火', '火', '土', '土', '金', '金', '水', '水')
# Five Elements for Branches
WU_XING_ZHI: tuple = ('水', '土', '木', '木', '土', '火', '火', '土', '金', '金', '土', '水')
# Sound Classifications (纳音)
NAYIN: tuple # 60 sound classifications for Jia Zi combinations
# Ten Gods (十神)
SHI_SHEN: tuple = ('比肩', '劫财', '食神', '伤官', '偏财', '正财', '七杀', '正官', '偏印', '正印')
# Twelve Growth Phases (十二长生)
CHANG_SHENG: tuple = ('长生', '沐浴', '冠带', '临官', '帝旺', '衰', '病', '死', '墓', '绝', '胎', '养')class LunarUtil:
@staticmethod
def find(array: tuple, target: str, offset: int = 0) -> int: ...
# Find element in array starting from offset, returns index or -1
@staticmethod
def getJiaZiIndex(gan_zhi: str) -> int: ...
# Get index (0-59) of stem-branch combination in 60-cycle
@staticmethod
def getXun(gan_zhi: str) -> str: ...
# Get 10-day cycle (旬) for given stem-branch
@staticmethod
def getXunKong(gan_zhi: str) -> str: ...
# Get void period (旬空) for given stem-branch
@staticmethod
def getDayYi(month_gan_zhi: str, day_gan_zhi: str) -> list: ...
# Get auspicious activities for month-day combination
@staticmethod
def getDayJi(month_gan_zhi: str, day_gan_zhi: str) -> list: ...
# Get inauspicious activities for month-day combination
@staticmethod
def getTimeYi(day_gan_zhi: str, time_gan_zhi: str) -> list: ...
# Get auspicious activities for day-time combination
@staticmethod
def getTimeJi(day_gan_zhi: str, time_gan_zhi: str) -> list: ...
# Get inauspicious activities for day-time combinationUtility functions and constants for solar (Gregorian) calendar calculations.
class SolarUtil:
# Week Day Names in Chinese
WEEK: tuple = ('日', '一', '二', '三', '四', '五', '六')
# Days in Each Month (non-leap year)
DAYS_OF_MONTH: tuple = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
# Western Zodiac Signs
XING_ZUO: tuple = ('白羊', '金牛', '双子', '巨蟹', '狮子', '处女',
'天秤', '天蝎', '射手', '摩羯', '水瓶', '双鱼')class SolarUtil:
# Major Solar Festivals
FESTIVAL: dict # Solar festivals by month-day
# Week-based Festivals (e.g., Mother's Day)
WEEK_FESTIVAL: dict # Festivals defined by week position
# Other Solar Festivals
OTHER_FESTIVAL: dict # Additional solar observancesclass SolarUtil:
@staticmethod
def isLeapYear(year: int) -> bool: ...
# Check if given year is a leap year
@staticmethod
def getDaysOfMonth(year: int, month: int) -> int: ...
# Get number of days in given month of given year
@staticmethod
def getDaysBetween(year1: int, month1: int, day1: int,
year2: int, month2: int, day2: int) -> int: ...
# Calculate number of days between two solar datesChinese holiday calculation utilities for official holidays and work day determinations.
class HolidayUtil:
@staticmethod
def getHolidays(year: int) -> dict: ...
# Get all holidays for given year as dict {date: holiday_name}
# Individual holiday calculation methods
@staticmethod
def getNewYearHoliday(year: int) -> list: ... # New Year holidays
@staticmethod
def getSpringFestivalHoliday(year: int) -> list: ... # Spring Festival holidays
@staticmethod
def getTombSweepingDayHoliday(year: int) -> list: ... # Qingming holidays
@staticmethod
def getLaborDayHoliday(year: int) -> list: ... # Labor Day holidays
@staticmethod
def getDragonBoatFestivalHoliday(year: int) -> list: ... # Dragon Boat holidays
@staticmethod
def getMidAutumnFestivalHoliday(year: int) -> list: ... # Mid-Autumn holidays
@staticmethod
def getNationalDayHoliday(year: int) -> list: ... # National Day holidaysPrecise astronomical calculations for solar terms, moon phases, and calendar conversions.
class ShouXingUtil:
# Julian day conversion utilities
@staticmethod
def solarToJulian(year: int, month: int, day: int) -> int: ...
# Convert solar date to Julian day number
@staticmethod
def julianToSolar(julian_day: int) -> tuple: ...
# Convert Julian day to solar date (year, month, day)
# Solar term calculations
@staticmethod
def getTerm(year: int, term_index: int) -> float: ...
# Get precise Julian day for solar term (0-23 index)
@staticmethod
def getTermName(term_index: int) -> str: ...
# Get name of solar term by index
# Moon phase calculations
@staticmethod
def getMoonPhase(year: int, month: int) -> float: ...
# Get new moon Julian day for given month
# Lunar calendar conversion utilities
@staticmethod
def getLunarMonthDays(year: int, month: int) -> int: ...
# Get number of days in lunar month
@staticmethod
def getLeapMonth(year: int) -> int: ...
# Get leap month number for lunar year (0 if none)class FotoUtil:
# Buddhist constellation calculation
@staticmethod
def getXiu(month: int, day: int) -> str: ...
# Get 28-constellation name for given lunar month-day
# Buddhist festival constants
XIU_28: tuple # 28 constellation names
XIU_LUCK: tuple # Luck classifications for constellations
XIU_SONG: tuple # Verses for each constellationclass TaoUtil:
# Taoist festival calculations
@staticmethod
def getFestival(month: int, day: int) -> list: ...
# Get Taoist festivals for given lunar month-day
# Taoist festival constants
FESTIVAL: dict # Taoist festivals by month-dayfrom lunar_python.util import LunarUtil, SolarUtil
# Access basic constants
print("=== Chinese Calendar Constants ===")
print(f"Heavenly Stems: {LunarUtil.GAN}")
print(f"Earthly Branches: {LunarUtil.ZHI}")
print(f"Zodiac Animals: {LunarUtil.SHENGXIAO}")
print(f"Chinese Months: {LunarUtil.MONTH}")
# Solar calendar constants
print(f"\nWeek Days: {SolarUtil.WEEK}")
print(f"Zodiac Signs: {SolarUtil.XING_ZUO}")from lunar_python.util import LunarUtil
# Working with 60-cycle combinations
gan_zhi = "甲子"
index = LunarUtil.getJiaZiIndex(gan_zhi)
print(f"{gan_zhi} is at index {index} in the 60-cycle")
# Get cycle information
xun = LunarUtil.getXun(gan_zhi)
xun_kong = LunarUtil.getXunKong(gan_zhi)
print(f"10-day cycle (旬): {xun}")
print(f"Void period (旬空): {xun_kong}")
# Find elements in arrays
gan_index = LunarUtil.find(LunarUtil.GAN, "甲")
zhi_index = LunarUtil.find(LunarUtil.ZHI, "子")
print(f"甲 is at index {gan_index} in stems")
print(f"子 is at index {zhi_index} in branches")from lunar_python.util import SolarUtil
# Leap year calculations
years = [2020, 2021, 2023, 2024]
for year in years:
is_leap = SolarUtil.isLeapYear(year)
print(f"{year}: {'Leap year' if is_leap else 'Regular year'}")
# Days in month calculations
print(f"\n=== Days in February ===")
for year in [2020, 2021, 2023, 2024]:
days = SolarUtil.getDaysOfMonth(year, 2)
print(f"February {year}: {days} days")
# Calculate days between dates
days_diff = SolarUtil.getDaysBetween(2023, 1, 1, 2023, 12, 31)
print(f"\nDays from 2023-01-01 to 2023-12-31: {days_diff}")from lunar_python.util import LunarUtil
from lunar_python import Lunar
# Get activity recommendations for a specific date
lunar = Lunar.fromYmd(2023, 4, 11)
month_gz = lunar.getMonthInGanZhi()
day_gz = lunar.getDayInGanZhi()
time_gz = lunar.getTimeInGanZhi()
# Daily activities
yi_activities = LunarUtil.getDayYi(month_gz, day_gz)
ji_activities = LunarUtil.getDayJi(month_gz, day_gz)
print(f"=== Activities for {lunar.toString()} ===")
print("Auspicious activities:")
for activity in yi_activities:
print(f" ✓ {activity}")
print("\nInauspicious activities:")
for activity in ji_activities:
print(f" ✗ {activity}")
# Time-specific activities
time_yi = LunarUtil.getTimeYi(day_gz, time_gz)
time_ji = LunarUtil.getTimeJi(day_gz, time_gz)
if time_yi:
print(f"\nAuspicious for {time_gz} time:")
for activity in time_yi:
print(f" ✓ {activity}")
if time_ji:
print(f"\nInauspicious for {time_gz} time:")
for activity in time_ji:
print(f" ✗ {activity}")from lunar_python.util import HolidayUtil
# Get all holidays for a year
holidays = HolidayUtil.getHolidays(2024)
print("=== 2024 Chinese Holidays ===")
for date, holiday_name in sorted(holidays.items()):
print(f"{date}: {holiday_name}")
# Get specific holiday periods
spring_festival = HolidayUtil.getSpringFestivalHoliday(2024)
national_day = HolidayUtil.getNationalDayHoliday(2024)
print(f"\nSpring Festival 2024: {len(spring_festival)} days")
for holiday in spring_festival:
print(f" {holiday}")
print(f"\nNational Day 2024: {len(national_day)} days")
for holiday in national_day:
print(f" {holiday}")from lunar_python.util import ShouXingUtil
# Solar term calculations for 2024
print("=== 2024 Solar Terms ===")
for i in range(24):
term_name = ShouXingUtil.getTermName(i)
julian_day = ShouXingUtil.getTerm(2024, i)
# Convert Julian day back to solar date
year, month, day = ShouXingUtil.julianToSolar(int(julian_day))
print(f"{term_name}: {year}-{month:02d}-{day:02d}")
# Leap month calculation
for year in [2023, 2024, 2025]:
leap_month = ShouXingUtil.getLeapMonth(year)
if leap_month > 0:
print(f"Lunar year {year} has leap month: {leap_month}")
else:
print(f"Lunar year {year} has no leap month")from lunar_python.util import LunarUtil, SolarUtil
# Lunar festivals
print("=== Some Lunar Festivals ===")
lunar_festivals = {
(1, 1): "春节 (Spring Festival)",
(1, 15): "元宵节 (Lantern Festival)",
(5, 5): "端午节 (Dragon Boat Festival)",
(8, 15): "中秋节 (Mid-Autumn Festival)"
}
for (month, day), name in lunar_festivals.items():
key = f"{month}-{day}"
if key in LunarUtil.FESTIVAL:
print(f" Lunar {month}/{day}: {name}")
# Solar festivals
print("\n=== Some Solar Festivals ===")
solar_festivals = {
(1, 1): "元旦 (New Year's Day)",
(2, 14): "情人节 (Valentine's Day)",
(10, 1): "国庆节 (National Day)",
(12, 25): "圣诞节 (Christmas)"
}
for (month, day), name in solar_festivals.items():
key = f"{month}-{day}"
if key in SolarUtil.FESTIVAL:
print(f" Solar {month}/{day}: {name}")from lunar_python.util import LunarUtil
from lunar_python import Lunar
lunar = Lunar.fromYmd(2023, 4, 11)
# Get stem and branch indices
year_gan_idx = LunarUtil.find(LunarUtil.GAN, lunar.getYearGan())
year_zhi_idx = LunarUtil.find(LunarUtil.ZHI, lunar.getYearZhi())
day_gan_idx = LunarUtil.find(LunarUtil.GAN, lunar.getDayGan())
# Get five elements
year_gan_wuxing = LunarUtil.WU_XING_GAN[year_gan_idx]
year_zhi_wuxing = LunarUtil.WU_XING_ZHI[year_zhi_idx]
print(f"=== Five Elements Analysis ===")
print(f"Year stem {lunar.getYearGan()}: {year_gan_wuxing}")
print(f"Year branch {lunar.getYearZhi()}: {year_zhi_wuxing}")
# Get sound classification (纳音)
year_jz_idx = LunarUtil.getJiaZiIndex(lunar.getYearInGanZhi())
year_nayin = LunarUtil.NAYIN[year_jz_idx]
print(f"Year NaYin: {year_nayin}")
# Growth phase analysis
day_jz_idx = LunarUtil.getJiaZiIndex(lunar.getDayInGanZhi())
growth_phase_idx = (day_jz_idx + year_gan_idx) % 12 # Simplified calculation
growth_phase = LunarUtil.CHANG_SHENG[growth_phase_idx]
print(f"Growth phase: {growth_phase}")Install with Tessl CLI
npx tessl i tessl/pypi-lunar-pythondocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10