高精度农历历法库 — 干支 · 生肖 · 节气 · 节日 · 格式化 · 多语言
基于天文算法的农历计算,支持中国、日本、韩国、越南四种农历变体,以及简体中文、繁體中文(台灣/香港)、日本語、한국어、Tiếng Việt 六种语言。
import { ChineseDate } from 'chinese-lunar-date'
const date = ChineseDate.fromGregorian(2024, 6, 21)
date.yearGanZhi // "甲辰"
date.zodiac // "龙"
date.zodiacEmoji // "🐉"
date.formatFull() // "甲辰龙年 五月初六"
CalendarConfig 配置驱动,同一套算法适配不同纪元和时区历史,而非四套独立实现ChineseDate 等)为不可变值对象,底层算法全部为纯函数,两种模式可独立使用| chinese-lunar-date | date-chinese | lunar-javascript | |
|---|---|---|---|
| 精度 | 天文算法(VSOP87) | 天文算法 | 查表法 |
| TypeScript | 原生 TS,完整类型 | JSDoc 标注 | 社区 @types |
| API 风格 | 不可变值对象 | 函数式 + 内部类 | 可变对象 |
| 干支 | 年月日三柱 | 仅年柱 | 年月日三柱 |
| 生肖 | 6 种语言 + Emoji | 无 | 仅中文 |
| 节气 | 24 节气,6 种语言 | 无 | 仅中文 |
| 节日 | 13 个,按地区筛选 | 无 | 仅中文 |
| 多历法 | 中 / 日 / 韩 / 越 | 仅中国 | 仅中国 |
| 繁体中文 | zh-TW / zh-HK 分别适配 | 无 | 无 |
| 格式化 | 5 种内置 + 自定义模式 | 无 | 有限 |
| 体积 (gzip) | ~16 KB | ~15 KB | ~20 KB |
with() / addDays() 返回新实例zh-CN / zh-TW / zh-HK / ja-JP / ko-KR / vi-VNnpm install chinese-lunar-date
import { ChineseDate } from 'chinese-lunar-date'
// 从公历创建
const date = ChineseDate.fromGregorian(2024, 6, 21)
// 从 JavaScript Date 创建
const date2 = ChineseDate.fromDate(new Date(2024, 5, 21))
// 今天的农历
const today = ChineseDate.today()
// 从 LunarDateValue 创建
const date3 = ChineseDate.fromValue({ cycle: 78, year: 34, month: 5, leap: false, day: 6 })
const date = ChineseDate.fromGregorian(2024, 6, 21)
// 农历日期
date.cycle // 78 — 六十甲子周期序号
date.year // 34 — 周期内年序(34 → 甲辰)
date.month // 5 — 五月
date.leap // false — 非闰月
date.day // 6 — 初六
date.gregorianYear // 2024
// 天干地支
date.yearGanZhi // "甲辰"
date.monthGanZhi // "庚午"
date.dayGanZhi // "甲寅"
date.ganZhiInfo // { year: {gan:0,zhi:4}, month: {gan:6,zhi:6}, day: {gan:0,zhi:2} }
// 生肖
date.zodiac // "龙"
date.zodiacEmoji // "🐉"
date.zodiacIndex // 4
// 节日 & 节气
date.festivals // [] — 这天没有节日
date.getSolarTermName('zh-CN') // null — 这天不是节气
const date = ChineseDate.fromGregorian(2024, 6, 21)
// 内置格式
date.formatFull() // "甲辰龙年 五月初六"
date.formatFull('zh-TW') // "甲辰龍年 五月初六"
date.formatFull('ja-JP') // "甲辰辰年 五月初六"
date.formatGanZhi() // "甲辰年 庚午月 甲寅日"
date.formatCompact() // "78/34/5/0/6"
date.formatISO() // "78-34-5-0-6"
// 自定义模式
date.format('{Ygz}{Z}年 {Mname}{Dname}', 'zh-CN') // "甲辰龙年 五月初六"
date.format('{Ygz}{Z}年 {Mname}{Dname}', 'zh-TW') // "甲辰龍年 五月初六"
date.format('{GY}年{GM}月{GD}日', 'zh-CN') // "2024年6月21日"
const date = ChineseDate.fromGregorian(2024, 6, 21)
// 日期加减 — 返回新实例,原实例不变
const tomorrow = date.addDays(1)
const yesterday = date.addDays(-1)
const nextMonth = date.addMonths(1)
const lastYear = date.addYears(-1)
// 修改部分字段
const firstDay = date.with({ day: 1 }) // 五月初一
// 比较
tomorrow.isAfter(date) // true
yesterday.isBefore(date) // true
date.equals(tomorrow) // false
const date = ChineseDate.fromGregorian(2024, 6, 21)
// 转为公历
date.toGregorian() // { year: 2024, month: 6, day: 21 }
// 转为 JavaScript Date
date.toDate() // Date object
// 序列化
date.toJSON() // { cycle: 78, year: 34, month: 5, leap: false, day: 6 }
JSON.stringify(date) // '{"cycle":78,"year":34,"month":5,"leap":false,"day":6}'
四种农历变体,各有不同的纪元和时区历史:
import { ChineseDate, JapaneseDate, KoreanDate, VietnameseDate } from 'chinese-lunar-date'
// 中国农历 (UTC+8)
const cn = ChineseDate.fromGregorian(2024, 6, 21)
cn.yearGanZhi // "甲辰"
// 日本旧历 (UTC+9)
const jp = JapaneseDate.fromGregorian(2024, 6, 21)
jp.yearGanZhi // "甲辰" — 同一天可能因时区差异而不同
// 韩国农历 (UTC+8:30/9,檀君纪元)
const kr = KoreanDate.fromGregorian(2024, 6, 21)
// 越南农历 (UTC+7/8)
const vn = VietnameseDate.fromGregorian(2024, 6, 21)
注意:由于时区差异,同一公历日期在不同历法中可能对应不同的农历日期。例如,当新月发生在 UTC+8 的午夜附近时,日本 (UTC+9) 可能已经进入下一天。
import { ChineseDate, solarTermName } from 'chinese-lunar-date'
// 获取指定节气的公历日期
ChineseDate.solarTerm(5, 2024) // { year: 2024, month: 4, day: 4 } — 清明
ChineseDate.qingming(2024) // 同上
// 全年 24 节气
ChineseDate.solarTermsInYear(2024, 'zh-CN')
// [
// { index: 1, name: "立春", date: { year: 2024, month: 2, day: 4 }, jde: ... },
// { index: 2, name: "雨水", date: { year: 2024, month: 2, day: 19 }, jde: ... },
// ...
// ]
// 节气名称 — 6 种语言
solarTermName(3, 'zh-CN') // "惊蛰"
solarTermName(3, 'zh-TW') // "驚蟄"
solarTermName(3, 'zh-HK') // "驚蟄"
solarTermName(3, 'ja-JP') // "啓蟄"
solarTermName(3, 'ko-KR') // "경칩"
solarTermName(3, 'vi-VN') // "Kinh trập"
// 查找某日是否为节气
const date = ChineseDate.fromGregorian(2024, 4, 4)
date.getSolarTermName('zh-CN') // "清明"
import { ChineseDate } from 'chinese-lunar-date'
// 获取指定节日的公历日期
ChineseDate.festivalDate('spring', 2024) // { year: 2024, month: 2, day: 10 }
ChineseDate.festivalDate('mid-autumn', 2024) // { year: 2024, month: 9, day: 17 }
// 全年节日 — 按地区自动筛选
ChineseDate.festivalsInYear(2024, 'zh-CN')
// [{ name: "春节", key: "spring", date: {...} }, ...]
ChineseDate.festivalsInYear(2024, 'zh-HK')
// [{ name: "農曆新年", key: "spring", date: {...} }, ...] — 香港称「農曆新年」
// 查看某日是否为节日
const date = ChineseDate.fromGregorian(2024, 2, 10)
date.getFestivals('zh-CN') // [{ name: "春节", key: "spring", ... }]
date.getFestivals('zh-HK') // [{ name: "農曆新年", key: "spring", ... }]
内置节日列表
| Key | 农历日期 | zh-CN | zh-TW | zh-HK |
|---|---|---|---|---|
spring |
正月初一 | 春节 | 春節 | 農曆新年 |
lantern |
正月十五 | 元宵节 | 元宵節 | 元宵節 |
dragon-head |
二月初二 | 龙抬头 | 龍抬頭 | 龍抬頭 |
shangsi |
三月初三 | 上巳节 | 上巳節 | 上巳節 |
dragon-boat |
五月初五 | 端午节 | 端午節 | 端午節 |
qixi |
七月初七 | 七夕节 | 七夕 | 七夕 |
ghost |
七月十五 | 中元节 | 中元節 | 中元節 |
mid-autumn |
八月十五 | 中秋节 | 中秋節 | 中秋節 |
double-ninth |
九月初九 | 重阳节 | 重陽節 | 重陽節 |
laba |
腊月初八 | 腊八节 | 臘八節 | 臘八節 |
little-new-year-north |
腊月廿三 | 小年(北方) | — | — |
little-new-year-south |
腊月廿四 | 小年(南方) | 小年 | 小年 |
new-year-eve |
腊月三十 | 除夕 | 除夕 | 除夕 |
import { getLocale, availableLocales, isLocaleSupported } from 'chinese-lunar-date'
availableLocales() // ["zh-CN", "zh-TW", "zh-HK", "ja-JP", "ko-KR", "vi-VN"]
isLocaleSupported('zh-MO') // false
const loc = getLocale('ja-JP')
loc.gan // ["甲", "乙", "丙", ...]
loc.zhi // ["子", "丑", "寅", ...]
loc.zodiac // ["鼠", "牛", "虎", "兔", "竜", "蛇", "馬", "羊", "猿", "鶏", "犬", "猪"]
loc.monthNames(12, false) // "師走"
loc.dayNames(15) // "十五"
loc.solarTerms // ["立春", "雨水", "啓蟄", ...]
繁体中文地区差异
| 项目 | zh-CN | zh-TW | zh-HK |
|---|---|---|---|
| 生肖 | 龙 马 鸡 猪 | 龍 馬 雞 豬 | 龍 馬 雞 豬 |
| 闰月 | 闰 | 閏 | 閏 |
| 腊月 | 腊月 | 臘月 | 臘月 |
| 春节 | 春节 | 春節 | 農曆新年 |
| 节气 | 惊蛰 谷雨 处暑 小满 芒种 | 驚蟄 穀雨 處暑 小滿 芒種 | 驚蟄 穀雨 處暑 小滿 芒種 |
| 小年 | 分南北方 | 统一(廿四) | 统一(廿四) |
import {
yearGanZhi, monthGanZhi, dayGanZhi,
formatGanZhi, parseGanZhi, allGanZhi, ganZhiToCycleIndex
} from 'chinese-lunar-date'
// 获取干支索引对
const pair = yearGanZhi({ cycle: 78, year: 34, month: 7, leap: false, day: 28 })
// { gan: 3, zhi: 9 } → 丁酉
// 格式化
formatGanZhi(pair) // "丁酉"
// 解析
parseGanZhi('甲子') // { gan: 0, zhi: 0 }
// 六十甲子序号
ganZhiToCycleIndex(parseGanZhi('甲子')) // 1
ganZhiToCycleIndex(parseGanZhi('癸亥')) // 60
// 六十甲子表
allGanZhi() // ["甲子", "乙丑", ..., "癸亥"]
import { zodiac, zodiacEmoji, zodiacFromGregorianYear, zodiacList } from 'chinese-lunar-date'
// 多语言生肖名称
zodiac({ cycle: 78, year: 34, month: 7, leap: false, day: 28 }, 'zh-CN') // "鸡"
zodiac({ cycle: 78, year: 34, month: 7, leap: false, day: 28 }, 'zh-TW') // "雞"
zodiac({ cycle: 78, year: 34, month: 7, leap: false, day: 28 }, 'ja-JP') // "鶏"
zodiac({ cycle: 78, year: 34, month: 7, leap: false, day: 28 }, 'ko-KR') // "닭"
zodiac({ cycle: 78, year: 34, month: 7, leap: false, day: 28 }, 'vi-VN') // "Dậu"
// Emoji
zodiacEmoji({ cycle: 78, year: 34, month: 7, leap: false, day: 28 }) // "🐔"
// 从公历年快速获取
zodiacFromGregorianYear(2024, 'zh-CN') // "龙"
// 生肖列表
zodiacList('zh-CN') // ["鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"]
zodiacList('ko-KR') // ["쥐", "소", "호랑이", "토끼", "용", "뱀", "말", "양", "원숭이", "닭", "개", "돼지"]
const date = ChineseDate.fromGregorian(2024, 7, 3)
date.format('{Ygz}{Z}年 {Mname}{Dname}', 'zh-CN')
// "甲辰龙年 五月廿八"
date.format('{Ygz}{Z}年 {Mname}{Dname}', 'zh-TW')
// "甲辰龍年 五月廿八"
| Token | 输出 | 示例 |
|---|---|---|
{CY} |
周期序号 | 78 |
{Y} |
周期内年序 | 34 |
{Ygz} |
年干支 | 甲辰 |
{Z} |
生肖 | 龙 / 龍 |
{M} |
月份数字 | 5 |
{Mname} |
月份名称 | 五月 |
{L} |
闰月标记 | 闰 / 閏 |
{D} |
日期数字 | 28 |
{Dname} |
日期名称 | 廿八 |
{GY} |
公历年 | 2024 |
{GM} |
公历月 | 7 |
{GD} |
公历日 | 3 |
{W} |
星期几 (0-6) | 3 |
{Wname} |
星期几全称 | 星期三 |
{Wshort} |
星期几简称 | 三 |
import { parseCompact, parseISO } from 'chinese-lunar-date'
parseCompact('78/34/5/0/6') // { cycle: 78, year: 34, month: 5, leap: false, day: 6 }
parseCompact('78/34/2/1/15') // { cycle: 78, year: 34, month: 2, leap: true, day: 15 }
parseISO('78-34-5-0-6') // { cycle: 78, year: 34, month: 5, leap: false, day: 6 }
parseISO('invalid') // null
如需更细粒度的控制,可直接使用核心算法函数:
import {
gregorianToLunar, lunarToGregorian, lunarToJDE, fromJDE,
newYear, yearFromEpochCycle, solarTermJDE,
nextNewMoon, previousNewMoon, midnight,
inMajorSolarTerm, isLeapMonth,
CHINESE_CONFIG, JAPANESE_CONFIG, KOREAN_CONFIG, VIETNAMESE_CONFIG
} from 'chinese-lunar-date'
// 公历 → 农历
const lunar = gregorianToLunar(CHINESE_CONFIG, 2024, 6, 21)
// { cycle: 78, year: 34, month: 5, leap: false, day: 6 }
// 农历 → 公历
const greg = lunarToGregorian(CHINESE_CONFIG, lunar)
// { year: 2024, month: 6, day: 21 }
// 使用不同历法配置
const jpLunar = gregorianToLunar(JAPANESE_CONFIG, 2024, 6, 21)
const krLunar = gregorianToLunar(KOREAN_CONFIG, 2024, 6, 21)
const vnLunar = gregorianToLunar(VIETNAMESE_CONFIG, 2024, 6, 21)
// 春节 JDE
const nyJDE = newYear(CHINESE_CONFIG, 2024)
<script src="dist/chinese-lunar-date.iife.js"></script>
<script>
// 所有 API 挂载在全局 ChineseLunarDate 对象上
const date = ChineseLunarDate.ChineseDate.fromGregorian(2024, 6, 21)
console.log(date.formatFull()) // "甲辰龙年 五月初六"
console.log(date.formatFull('zh-TW')) // "甲辰龍年 五月初六"
console.log(date.zodiac) // "龙"
console.log(date.zodiacEmoji) // "🐉"
// 低级 API 同样可用
const lunar = ChineseLunarDate.gregorianToLunar(ChineseLunarDate.CHINESE_CONFIG, 2024, 6, 21)
console.log(lunar) // { cycle: 78, year: 34, month: 5, leap: false, day: 6 }
</script>
不可变农历日期对象,继承自 LunarDate 基类。
静态构造方法
| 方法 | 说明 |
|---|---|
fromGregorian(y, m, d) |
从公历日期创建 |
fromDate(date) |
从 JavaScript Date 创建 |
fromValue(value) |
从 LunarDateValue 对象创建 |
fromJDE(jde) |
从儒略日创建 |
today() |
获取今天的农历日期 |
实例属性
| 属性 | 类型 | 说明 |
|---|---|---|
cycle |
number |
六十甲子周期序号(1 起始) |
year |
number |
周期内年序(1-60) |
month |
number |
月(1-12) |
leap |
boolean |
是否闰月 |
day |
number |
日(1-30) |
calendarType |
CalendarType |
历法类型 |
gregorianYear |
number |
对应的公历年 |
yearGanZhi |
string |
年干支,如 "甲辰" |
monthGanZhi |
string |
月干支,如 "庚午" |
dayGanZhi |
string |
日干支,如 "甲寅" |
yearGanZhiPair |
GanZhiPair |
年干支索引对 |
monthGanZhiPair |
GanZhiPair |
月干支索引对 |
dayGanZhiPair |
GanZhiPair |
日干支索引对 |
ganZhiInfo |
GanZhiInfo |
年月日干支完整信息 |
zodiac |
string |
生肖(简体中文) |
zodiacEmoji |
string |
生肖 Emoji |
zodiacIndex |
number |
生肖索引(0-11) |
festivals |
FestivalInfo[] |
当日节日(简体中文) |
实例方法
| 方法 | 说明 |
|---|---|
toGregorian() |
转为公历 { year, month, day } |
toDate() |
转为 JavaScript Date |
toJDE() |
转为儒略日 |
with(patch) |
返回修改部分字段的新实例 |
addDays(n) |
加减天数,返回新实例 |
addMonths(n) |
加减月数,返回新实例 |
addYears(n) |
加减年数,返回新实例 |
equals(other) |
判等 |
isBefore(other) |
是否早于 |
isAfter(other) |
是否晚于 |
getZodiac(locale) |
获取指定语言的生肖 |
getFestivals(locale) |
获取指定语言的节日 |
getSolarTermName(locale) |
若当日为节气日则返回名称,否则 null |
format(pattern, locale) |
自定义模式格式化 |
formatFull(locale) |
完整格式,如 "甲辰龙年 五月初六" |
formatCompact() |
紧凑格式,如 "78/34/5/0/6" |
formatISO() |
ISO 格式,如 "78-34-5-0-6" |
formatGanZhi(locale) |
干支格式,如 "甲辰年 庚午月 甲寅日" |
toJSON() |
序列化为 LunarDateValue |
toString() |
默认字符串(等同 formatFull()) |
静态方法(历法相关)
| 方法 | 说明 |
|---|---|
newYear(gyear) |
获取春节公历日期 |
solarTerm(term, gyear) |
获取指定节气公历日期(1-24) |
solarTermsInYear(gyear, locale) |
获取全年 24 节气 |
qingming(gyear) |
获取清明公历日期 |
festivalDate(key, gyear) |
获取指定节日公历日期 |
festivalsInYear(gyear, locale) |
获取全年节日 |
interface LunarDateValue {
cycle: number // 六十甲子周期序号(1 起始)
year: number // 周期内年序(1-60)
month: number // 月(1-12)
leap: boolean // 是否闰月
day: number // 日(1-30)
}
interface GregorianDate {
year: number
month: number
day: number
}
type CalendarType = 'chinese' | 'korean' | 'japanese' | 'vietnamese'
interface GanZhiPair {
gan: number // 天干索引(0-9)
zhi: number // 地支索引(0-11)
}
interface GanZhiInfo {
year: GanZhiPair
month: GanZhiPair
day: GanZhiPair
}
interface SolarTermInfo {
index: number // 节气序号(1-24)
date: GregorianDate // 公历日期
jde: number // 儒略日
}
interface FestivalInfo {
name: string // 节日名称(本地化)
key: string // 节日标识
month: number // 农历月
day: number // 农历日
leap: boolean // 是否闰月
}
type LocaleCode = 'zh-CN' | 'zh-TW' | 'zh-HK' | 'ja-JP' | 'ko-KR' | 'vi-VN'
npm run build # 编译 ESM + CJS + IIFE
npm run build:types # 生成 .d.ts 类型声明
npm run test # 运行测试
npm run clean # 清除 dist
src/
├── types.ts # 核心类型定义
├── core/
│ ├── astronomy-lite.ts # 自研轻量天文模块(VSOP87 截断数据)
│ ├── config.ts # 四种历法配置(纪元 + 时区历史)
│ └── algorithm.ts # 核心算法(公历 ↔ 农历转换)
├── ganzhi.ts # 天干地支
├── zodiac.ts # 生肖
├── solar-term.ts # 24 节气
├── festival.ts # 传统节日
├── locale.ts # 多语言 / 多地区
├── format.ts # 格式化 + 解析
├── chinese-numerals.ts # 中文数字
├── lunar-date.ts # 不可变值对象 API
└── index.ts # 主入口
设计原则
with() / addDays() 返回新实例CalendarConfig 区分(纪元年、时区历史规则)如果您在使用过程中遇到问题,或有功能建议、商务合作等需求,欢迎通过邮件联系我们:
MIT License
Copyright (c) 2025 北京锋通科技有限公司 (郭玉峰, 吴琼)