fix: chinese-almanac 使用 lunar-javascript 库 - 修复农历日期计算错误

master
Eason (陈医生) 1 month ago
parent 32dd8bd75d
commit a13dc38246
  1. 91
      skills/chinese-almanac/almanac.js

@ -1,27 +1,44 @@
/**
* Chinese Almanac (黄历) Query Skill
* 使用 Tavily API 查询每日黄历信息
* 使用 Tavily API 查询黄历 + lunar-javascript 计算农历
*/
const { Solar, Lunar } = require('lunar-javascript');
const TAVILY_API_KEY = process.env.TAVILY_API_KEY || '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';
/**
* 计算农历日期使用专业库
* lunar-javascript 会自动处理时区直接传入日期即可
*/
function getLunarDate(jsDate) {
// 使用 local time 创建 Solar 对象,lunar-javascript 会正确处理
const solar = Solar.fromYmd(jsDate.getFullYear(), jsDate.getMonth() + 1, jsDate.getDate());
const lunar = solar.getLunar();
return {
lunarDate: lunar.toString(), // 如:二〇二六年正月初十
lunarDay: lunar.getDayInChinese(), // 如:初十
lunarMonth: lunar.getMonthInChinese(), // 如:正月
lunarYear: lunar.getYearInChinese() // 如:二〇二六
};
}
/**
* 查询黄历信息
*/
async function queryAlmanac(date) {
let targetDate;
if (!date) {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
date = tomorrow.toISOString().split('T')[0];
targetDate = new Date();
targetDate.setDate(targetDate.getDate() + 1); // 明天
} else {
targetDate = new Date(date);
}
// 动态计算农历日期(基于 2026 年春节 2 月 17 日)
const targetDate = date ? new Date(date) : new Date();
const springFestival = new Date('2026-02-17');
const lunarDay = Math.floor((targetDate - springFestival) / (1000 * 60 * 60 * 24)) + 1;
const lunarDateStr = `农历正月初${lunarDay}`;
// 使用专业库计算农历
const lunarInfo = getLunarDate(targetDate);
const query = `${date} 黄历 宜忌 ${lunarDateStr}`;
const query = `${targetDate.toISOString().split('T')[0]} 黄历 宜忌 ${lunarInfo.lunarDate}`;
try {
const response = await fetch('https://api.tavily.com/search', {
@ -43,12 +60,12 @@ async function queryAlmanac(date) {
}
const data = await response.json();
const almanacInfo = parseAlmanacData(data, date, lunarDateStr);
const almanacInfo = parseAlmanacData(data, targetDate, lunarInfo);
return {
success: true,
date: date,
lunarDate: lunarDateStr,
date: targetDate.toISOString().split('T')[0],
lunarDate: lunarInfo.lunarDate,
weekday: almanacInfo.weekday,
ganzhi: almanacInfo.ganzhi,
yi: almanacInfo.yi,
@ -59,7 +76,7 @@ async function queryAlmanac(date) {
return {
success: false,
error: error.message,
fallback: getFallbackAlmanac(date, lunarDateStr)
fallback: getFallbackAlmanac(targetDate, lunarInfo)
};
}
}
@ -67,11 +84,11 @@ async function queryAlmanac(date) {
/**
* 解析黄历数据
*/
function parseAlmanacData(data, date, lunarDateStr) {
function parseAlmanacData(data, date, lunarInfo) {
const result = {
lunarDate: lunarDateStr,
lunarDate: lunarInfo.lunarDate,
weekday: getWeekday(date),
ganzhi: '丙午年 庚寅月 己巳日',
ganzhi: '丙午年 庚寅月 ' + getDayGanZhi(date),
yi: ['作灶', '解除', '平治道涂', '余事勿取'],
ji: ['祈福', '安葬', '祭祀', '安门'],
chong: '冲猪 煞东'
@ -110,22 +127,40 @@ function parseAlmanacData(data, date, lunarDateStr) {
/**
* 获取星期
*/
function getWeekday(dateStr) {
const date = new Date(dateStr);
function getWeekday(date) {
const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
return `星期${weekdays[date.getDay()]}`;
}
/**
* 获取日干支简化版
*/
function getDayGanZhi(date) {
// 2026-02-17 是己巳日
const baseDate = new Date('2026-02-17');
const ganzhi = ['甲子','乙丑','丙寅','丁卯','戊辰','己巳','庚午','辛未','壬申','癸酉',
'甲戌','乙亥','丙子','丁丑','戊寅','己卯','庚辰','辛巳','壬午','癸未',
'甲申','乙酉','丙戌','丁亥','戊子','己丑','庚寅','辛卯','壬辰','癸巳',
'甲午','乙未','丙申','丁酉','戊戌','己亥','庚子','辛丑','壬寅','癸卯',
'甲辰','乙巳','丙午','丁未','戊申','己酉','庚戌','辛亥','壬子','癸丑',
'甲寅','乙卯','丙辰','丁巳','戊午','己未','庚申','辛酉','壬戌','癸亥'];
const daysSince = Math.floor((date - baseDate) / (1000*60*60*24));
const baseIndex = 5; // 己巳是第 5 个(从 0 开始)
const index = (baseIndex + daysSince) % 60;
return ganzhi[index >= 0 ? index : 60 + index] + '日';
}
/**
* Fallback 数据
*/
function getFallbackAlmanac(date, lunarDateStr) {
function getFallbackAlmanac(date, lunarInfo) {
return {
success: true,
date: date,
lunarDate: lunarDateStr,
date: date.toISOString().split('T')[0],
lunarDate: lunarInfo.lunarDate,
weekday: getWeekday(date),
ganzhi: '丙午年 庚寅月 己巳日',
ganzhi: '丙午年 庚寅月 ' + getDayGanZhi(date),
yi: ['作灶', '解除', '平治道涂', '余事勿取'],
ji: ['祈福', '安葬', '祭祀', '安门'],
chong: '冲猪 煞东',
@ -160,9 +195,15 @@ function formatAlmanac(almanac) {
// 测试
if (require.main === module) {
queryAlmanac('2026-02-24').then(result => {
console.log('=== 黄历查询测试(使用 lunar-javascript 库)===\n');
const arg = process.argv[2] || 'tomorrow';
queryAlmanac(arg === 'today' ? null : (arg === 'tomorrow' ? undefined : arg))
.then(result => {
console.log(formatAlmanac(result));
console.log('\n详细信息:');
console.log(`农历:${result.lunarDate}`);
});
}
module.exports = { queryAlmanac, formatAlmanac };
module.exports = { queryAlmanac, formatAlmanac, getLunarDate };

Loading…
Cancel
Save