0
# Utilities and Constants
1
2
Comprehensive utility functions and constants for Chinese calendar calculations, holiday determinations, astronomical calculations, and supporting data structures.
3
4
## Capabilities
5
6
### Lunar Calendar Utilities (LunarUtil)
7
8
Core utility class containing constants and helper functions for lunar calendar calculations.
9
10
#### Essential Constants
11
12
```python { .api }
13
class LunarUtil:
14
# Heavenly Stems (天干) - 10 elements
15
GAN: tuple = ('甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸')
16
17
# Earthly Branches (地支) - 12 elements
18
ZHI: tuple = ('子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥')
19
20
# 60 Stem-Branch Combinations (六十甲子)
21
JIA_ZI: tuple # 60 combinations starting with 甲子
22
23
# Chinese Zodiac Animals (生肖)
24
SHENGXIAO: tuple = ('鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪')
25
26
# Chinese Number Names
27
NUMBER: tuple = ('〇', '一', '二', '三', '四', '五', '六', '七', '八', '九')
28
29
# Chinese Month Names
30
MONTH: tuple = ('正月', '二月', '三月', '四月', '五月', '六月',
31
'七月', '八月', '九月', '十月', '十一月', '十二月')
32
33
# Chinese Day Names
34
DAY: tuple # 30 day names (初一, 初二, ..., 三十)
35
```
36
37
#### Sexagenary Cycle Constants
38
39
```python { .api }
40
class LunarUtil:
41
# 10-day cycles (旬)
42
XUN: tuple = ('甲子', '甲戌', '甲申', '甲午', '甲辰', '甲寅')
43
44
# Void periods within cycles (旬空)
45
XUN_KONG: tuple = ('戌亥', '申酉', '午未', '辰巳', '寅卯', '子丑')
46
```
47
48
#### Festival Constants
49
50
```python { .api }
51
class LunarUtil:
52
# Major Lunar Festivals
53
FESTIVAL: dict # Lunar festivals by month-day
54
55
# Other Lunar Festivals
56
OTHER_FESTIVAL: dict # Additional lunar observances
57
```
58
59
#### Positional Constants
60
61
```python { .api }
62
class LunarUtil:
63
# Deity Position Arrays
64
POSITION_XI: tuple # Joy god positions by day stem
65
POSITION_YANG_GUI: tuple # Yang noble person positions
66
POSITION_YIN_GUI: tuple # Yin noble person positions
67
POSITION_FU: tuple # Fortune god positions
68
POSITION_FU_2: tuple # Alternative fortune god positions
69
POSITION_CAI: tuple # Wealth god positions
70
POSITION_CAI_2: tuple # Alternative wealth god positions
71
72
# Tai Sui positions
73
POSITION_TAI_SUI_YEAR: tuple # Yearly Tai Sui positions
74
POSITION_TAI_SUI_MONTH: tuple # Monthly Tai Sui positions
75
76
# Fetal god positions
77
POSITION_TAI: tuple # Daily fetal god positions
78
```
79
80
#### Fortune-telling Constants
81
82
```python { .api }
83
class LunarUtil:
84
# Five Elements for Stems
85
WU_XING_GAN: tuple = ('木', '木', '火', '火', '土', '土', '金', '金', '水', '水')
86
87
# Five Elements for Branches
88
WU_XING_ZHI: tuple = ('水', '土', '木', '木', '土', '火', '火', '土', '金', '金', '土', '水')
89
90
# Sound Classifications (纳音)
91
NAYIN: tuple # 60 sound classifications for Jia Zi combinations
92
93
# Ten Gods (十神)
94
SHI_SHEN: tuple = ('比肩', '劫财', '食神', '伤官', '偏财', '正财', '七杀', '正官', '偏印', '正印')
95
96
# Twelve Growth Phases (十二长生)
97
CHANG_SHENG: tuple = ('长生', '沐浴', '冠带', '临官', '帝旺', '衰', '病', '死', '墓', '绝', '胎', '养')
98
```
99
100
#### Utility Methods
101
102
```python { .api }
103
class LunarUtil:
104
@staticmethod
105
def find(array: tuple, target: str, offset: int = 0) -> int: ...
106
# Find element in array starting from offset, returns index or -1
107
108
@staticmethod
109
def getJiaZiIndex(gan_zhi: str) -> int: ...
110
# Get index (0-59) of stem-branch combination in 60-cycle
111
112
@staticmethod
113
def getXun(gan_zhi: str) -> str: ...
114
# Get 10-day cycle (旬) for given stem-branch
115
116
@staticmethod
117
def getXunKong(gan_zhi: str) -> str: ...
118
# Get void period (旬空) for given stem-branch
119
120
@staticmethod
121
def getDayYi(month_gan_zhi: str, day_gan_zhi: str) -> list: ...
122
# Get auspicious activities for month-day combination
123
124
@staticmethod
125
def getDayJi(month_gan_zhi: str, day_gan_zhi: str) -> list: ...
126
# Get inauspicious activities for month-day combination
127
128
@staticmethod
129
def getTimeYi(day_gan_zhi: str, time_gan_zhi: str) -> list: ...
130
# Get auspicious activities for day-time combination
131
132
@staticmethod
133
def getTimeJi(day_gan_zhi: str, time_gan_zhi: str) -> list: ...
134
# Get inauspicious activities for day-time combination
135
```
136
137
### Solar Calendar Utilities (SolarUtil)
138
139
Utility functions and constants for solar (Gregorian) calendar calculations.
140
141
#### Solar Calendar Constants
142
143
```python { .api }
144
class SolarUtil:
145
# Week Day Names in Chinese
146
WEEK: tuple = ('日', '一', '二', '三', '四', '五', '六')
147
148
# Days in Each Month (non-leap year)
149
DAYS_OF_MONTH: tuple = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
150
151
# Western Zodiac Signs
152
XING_ZUO: tuple = ('白羊', '金牛', '双子', '巨蟹', '狮子', '处女',
153
'天秤', '天蝎', '射手', '摩羯', '水瓶', '双鱼')
154
```
155
156
#### Solar Festival Constants
157
158
```python { .api }
159
class SolarUtil:
160
# Major Solar Festivals
161
FESTIVAL: dict # Solar festivals by month-day
162
163
# Week-based Festivals (e.g., Mother's Day)
164
WEEK_FESTIVAL: dict # Festivals defined by week position
165
166
# Other Solar Festivals
167
OTHER_FESTIVAL: dict # Additional solar observances
168
```
169
170
#### Solar Utility Methods
171
172
```python { .api }
173
class SolarUtil:
174
@staticmethod
175
def isLeapYear(year: int) -> bool: ...
176
# Check if given year is a leap year
177
178
@staticmethod
179
def getDaysOfMonth(year: int, month: int) -> int: ...
180
# Get number of days in given month of given year
181
182
@staticmethod
183
def getDaysBetween(year1: int, month1: int, day1: int,
184
year2: int, month2: int, day2: int) -> int: ...
185
# Calculate number of days between two solar dates
186
```
187
188
### Holiday Utilities (HolidayUtil)
189
190
Chinese holiday calculation utilities for official holidays and work day determinations.
191
192
```python { .api }
193
class HolidayUtil:
194
@staticmethod
195
def getHolidays(year: int) -> dict: ...
196
# Get all holidays for given year as dict {date: holiday_name}
197
198
# Individual holiday calculation methods
199
@staticmethod
200
def getNewYearHoliday(year: int) -> list: ... # New Year holidays
201
202
@staticmethod
203
def getSpringFestivalHoliday(year: int) -> list: ... # Spring Festival holidays
204
205
@staticmethod
206
def getTombSweepingDayHoliday(year: int) -> list: ... # Qingming holidays
207
208
@staticmethod
209
def getLaborDayHoliday(year: int) -> list: ... # Labor Day holidays
210
211
@staticmethod
212
def getDragonBoatFestivalHoliday(year: int) -> list: ... # Dragon Boat holidays
213
214
@staticmethod
215
def getMidAutumnFestivalHoliday(year: int) -> list: ... # Mid-Autumn holidays
216
217
@staticmethod
218
def getNationalDayHoliday(year: int) -> list: ... # National Day holidays
219
```
220
221
### Astronomical Utilities (ShouXingUtil)
222
223
Precise astronomical calculations for solar terms, moon phases, and calendar conversions.
224
225
```python { .api }
226
class ShouXingUtil:
227
# Julian day conversion utilities
228
@staticmethod
229
def solarToJulian(year: int, month: int, day: int) -> int: ...
230
# Convert solar date to Julian day number
231
232
@staticmethod
233
def julianToSolar(julian_day: int) -> tuple: ...
234
# Convert Julian day to solar date (year, month, day)
235
236
# Solar term calculations
237
@staticmethod
238
def getTerm(year: int, term_index: int) -> float: ...
239
# Get precise Julian day for solar term (0-23 index)
240
241
@staticmethod
242
def getTermName(term_index: int) -> str: ...
243
# Get name of solar term by index
244
245
# Moon phase calculations
246
@staticmethod
247
def getMoonPhase(year: int, month: int) -> float: ...
248
# Get new moon Julian day for given month
249
250
# Lunar calendar conversion utilities
251
@staticmethod
252
def getLunarMonthDays(year: int, month: int) -> int: ...
253
# Get number of days in lunar month
254
255
@staticmethod
256
def getLeapMonth(year: int) -> int: ...
257
# Get leap month number for lunar year (0 if none)
258
```
259
260
### Religious Calendar Utilities
261
262
#### Buddhist Utilities (FotoUtil)
263
264
```python { .api }
265
class FotoUtil:
266
# Buddhist constellation calculation
267
@staticmethod
268
def getXiu(month: int, day: int) -> str: ...
269
# Get 28-constellation name for given lunar month-day
270
271
# Buddhist festival constants
272
XIU_28: tuple # 28 constellation names
273
XIU_LUCK: tuple # Luck classifications for constellations
274
XIU_SONG: tuple # Verses for each constellation
275
```
276
277
#### Taoist Utilities (TaoUtil)
278
279
```python { .api }
280
class TaoUtil:
281
# Taoist festival calculations
282
@staticmethod
283
def getFestival(month: int, day: int) -> list: ...
284
# Get Taoist festivals for given lunar month-day
285
286
# Taoist festival constants
287
FESTIVAL: dict # Taoist festivals by month-day
288
```
289
290
## Usage Examples
291
292
### Working with Constants
293
294
```python
295
from lunar_python.util import LunarUtil, SolarUtil
296
297
# Access basic constants
298
print("=== Chinese Calendar Constants ===")
299
print(f"Heavenly Stems: {LunarUtil.GAN}")
300
print(f"Earthly Branches: {LunarUtil.ZHI}")
301
print(f"Zodiac Animals: {LunarUtil.SHENGXIAO}")
302
print(f"Chinese Months: {LunarUtil.MONTH}")
303
304
# Solar calendar constants
305
print(f"\nWeek Days: {SolarUtil.WEEK}")
306
print(f"Zodiac Signs: {SolarUtil.XING_ZUO}")
307
```
308
309
### Sexagenary Cycle Calculations
310
311
```python
312
from lunar_python.util import LunarUtil
313
314
# Working with 60-cycle combinations
315
gan_zhi = "甲子"
316
index = LunarUtil.getJiaZiIndex(gan_zhi)
317
print(f"{gan_zhi} is at index {index} in the 60-cycle")
318
319
# Get cycle information
320
xun = LunarUtil.getXun(gan_zhi)
321
xun_kong = LunarUtil.getXunKong(gan_zhi)
322
print(f"10-day cycle (旬): {xun}")
323
print(f"Void period (旬空): {xun_kong}")
324
325
# Find elements in arrays
326
gan_index = LunarUtil.find(LunarUtil.GAN, "甲")
327
zhi_index = LunarUtil.find(LunarUtil.ZHI, "子")
328
print(f"甲 is at index {gan_index} in stems")
329
print(f"子 is at index {zhi_index} in branches")
330
```
331
332
### Solar Calendar Utilities
333
334
```python
335
from lunar_python.util import SolarUtil
336
337
# Leap year calculations
338
years = [2020, 2021, 2023, 2024]
339
for year in years:
340
is_leap = SolarUtil.isLeapYear(year)
341
print(f"{year}: {'Leap year' if is_leap else 'Regular year'}")
342
343
# Days in month calculations
344
print(f"\n=== Days in February ===")
345
for year in [2020, 2021, 2023, 2024]:
346
days = SolarUtil.getDaysOfMonth(year, 2)
347
print(f"February {year}: {days} days")
348
349
# Calculate days between dates
350
days_diff = SolarUtil.getDaysBetween(2023, 1, 1, 2023, 12, 31)
351
print(f"\nDays from 2023-01-01 to 2023-12-31: {days_diff}")
352
```
353
354
### Activity Recommendations
355
356
```python
357
from lunar_python.util import LunarUtil
358
from lunar_python import Lunar
359
360
# Get activity recommendations for a specific date
361
lunar = Lunar.fromYmd(2023, 4, 11)
362
month_gz = lunar.getMonthInGanZhi()
363
day_gz = lunar.getDayInGanZhi()
364
time_gz = lunar.getTimeInGanZhi()
365
366
# Daily activities
367
yi_activities = LunarUtil.getDayYi(month_gz, day_gz)
368
ji_activities = LunarUtil.getDayJi(month_gz, day_gz)
369
370
print(f"=== Activities for {lunar.toString()} ===")
371
print("Auspicious activities:")
372
for activity in yi_activities:
373
print(f" ✓ {activity}")
374
375
print("\nInauspicious activities:")
376
for activity in ji_activities:
377
print(f" ✗ {activity}")
378
379
# Time-specific activities
380
time_yi = LunarUtil.getTimeYi(day_gz, time_gz)
381
time_ji = LunarUtil.getTimeJi(day_gz, time_gz)
382
383
if time_yi:
384
print(f"\nAuspicious for {time_gz} time:")
385
for activity in time_yi:
386
print(f" ✓ {activity}")
387
388
if time_ji:
389
print(f"\nInauspicious for {time_gz} time:")
390
for activity in time_ji:
391
print(f" ✗ {activity}")
392
```
393
394
### Holiday Calculations
395
396
```python
397
from lunar_python.util import HolidayUtil
398
399
# Get all holidays for a year
400
holidays = HolidayUtil.getHolidays(2024)
401
402
print("=== 2024 Chinese Holidays ===")
403
for date, holiday_name in sorted(holidays.items()):
404
print(f"{date}: {holiday_name}")
405
406
# Get specific holiday periods
407
spring_festival = HolidayUtil.getSpringFestivalHoliday(2024)
408
national_day = HolidayUtil.getNationalDayHoliday(2024)
409
410
print(f"\nSpring Festival 2024: {len(spring_festival)} days")
411
for holiday in spring_festival:
412
print(f" {holiday}")
413
414
print(f"\nNational Day 2024: {len(national_day)} days")
415
for holiday in national_day:
416
print(f" {holiday}")
417
```
418
419
### Astronomical Calculations
420
421
```python
422
from lunar_python.util import ShouXingUtil
423
424
# Solar term calculations for 2024
425
print("=== 2024 Solar Terms ===")
426
for i in range(24):
427
term_name = ShouXingUtil.getTermName(i)
428
julian_day = ShouXingUtil.getTerm(2024, i)
429
430
# Convert Julian day back to solar date
431
year, month, day = ShouXingUtil.julianToSolar(int(julian_day))
432
print(f"{term_name}: {year}-{month:02d}-{day:02d}")
433
434
# Leap month calculation
435
for year in [2023, 2024, 2025]:
436
leap_month = ShouXingUtil.getLeapMonth(year)
437
if leap_month > 0:
438
print(f"Lunar year {year} has leap month: {leap_month}")
439
else:
440
print(f"Lunar year {year} has no leap month")
441
```
442
443
### Festival Lookups
444
445
```python
446
from lunar_python.util import LunarUtil, SolarUtil
447
448
# Lunar festivals
449
print("=== Some Lunar Festivals ===")
450
lunar_festivals = {
451
(1, 1): "春节 (Spring Festival)",
452
(1, 15): "元宵节 (Lantern Festival)",
453
(5, 5): "端午节 (Dragon Boat Festival)",
454
(8, 15): "中秋节 (Mid-Autumn Festival)"
455
}
456
457
for (month, day), name in lunar_festivals.items():
458
key = f"{month}-{day}"
459
if key in LunarUtil.FESTIVAL:
460
print(f" Lunar {month}/{day}: {name}")
461
462
# Solar festivals
463
print("\n=== Some Solar Festivals ===")
464
solar_festivals = {
465
(1, 1): "元旦 (New Year's Day)",
466
(2, 14): "情人节 (Valentine's Day)",
467
(10, 1): "国庆节 (National Day)",
468
(12, 25): "圣诞节 (Christmas)"
469
}
470
471
for (month, day), name in solar_festivals.items():
472
key = f"{month}-{day}"
473
if key in SolarUtil.FESTIVAL:
474
print(f" Solar {month}/{day}: {name}")
475
```
476
477
### Five Elements and Fortune Analysis
478
479
```python
480
from lunar_python.util import LunarUtil
481
from lunar_python import Lunar
482
483
lunar = Lunar.fromYmd(2023, 4, 11)
484
485
# Get stem and branch indices
486
year_gan_idx = LunarUtil.find(LunarUtil.GAN, lunar.getYearGan())
487
year_zhi_idx = LunarUtil.find(LunarUtil.ZHI, lunar.getYearZhi())
488
day_gan_idx = LunarUtil.find(LunarUtil.GAN, lunar.getDayGan())
489
490
# Get five elements
491
year_gan_wuxing = LunarUtil.WU_XING_GAN[year_gan_idx]
492
year_zhi_wuxing = LunarUtil.WU_XING_ZHI[year_zhi_idx]
493
494
print(f"=== Five Elements Analysis ===")
495
print(f"Year stem {lunar.getYearGan()}: {year_gan_wuxing}")
496
print(f"Year branch {lunar.getYearZhi()}: {year_zhi_wuxing}")
497
498
# Get sound classification (纳音)
499
year_jz_idx = LunarUtil.getJiaZiIndex(lunar.getYearInGanZhi())
500
year_nayin = LunarUtil.NAYIN[year_jz_idx]
501
print(f"Year NaYin: {year_nayin}")
502
503
# Growth phase analysis
504
day_jz_idx = LunarUtil.getJiaZiIndex(lunar.getDayInGanZhi())
505
growth_phase_idx = (day_jz_idx + year_gan_idx) % 12 # Simplified calculation
506
growth_phase = LunarUtil.CHANG_SHENG[growth_phase_idx]
507
print(f"Growth phase: {growth_phase}")
508
```