chinese-lunar-date

高精度农历历法库 — 干支 · 生肖 · 节气 · 节日 · 格式化 · 多语言

基于天文算法的农历计算,支持中国、日本、韩国、越南四种农历变体,以及简体中文、繁體中文(台灣/香港)、日本語、한국어、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()  // "甲辰龙年 五月初六"

本项目独创

为什么选择 chinese-lunar-date?

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

特性

安装

npm 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) 可能已经进入下一天。

24 节气

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

低级 API

如需更细粒度的控制,可直接使用核心算法函数:

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)

浏览器使用(IIFE)

<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>

API 参考

值对象类

`ChineseDate` / `JapaneseDate` / `KoreanDate` / `VietnameseDate`

不可变农历日期对象,继承自 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              # 主入口

设计原则

反馈与协作

如果您在使用过程中遇到问题,或有功能建议、商务合作等需求,欢迎通过邮件联系我们:

📧 gyfinjava@163.com

License

MIT License

Copyright (c) 2025 北京锋通科技有限公司 (郭玉峰, 吴琼)