fix: 黄历查询格式化优化 - 农历日期动态计算,宜忌数据清理

master
Eason (陈医生) 1 month ago
parent 9307770d6a
commit 51bc1a141e
  1. 132
      skills/chinese-almanac/almanac.js

@ -7,12 +7,9 @@ const TAVILY_API_KEY = process.env.TAVILY_API_KEY || 'tvly-dev-42Ndz-7PXSU3QXbDb
/** /**
* 查询黄历信息 * 查询黄历信息
* @param {string} date - 日期 (YYYY-MM-DD 格式默认为明天)
* @returns {Promise<Object>} 黄历信息
*/ */
async function queryAlmanac(date) { async function queryAlmanac(date) {
if (!date) { if (!date) {
// 默认为明天
const tomorrow = new Date(); const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setDate(tomorrow.getDate() + 1);
date = tomorrow.toISOString().split('T')[0]; date = tomorrow.toISOString().split('T')[0];
@ -20,11 +17,11 @@ async function queryAlmanac(date) {
// 动态计算农历日期(基于 2026 年春节 2 月 17 日) // 动态计算农历日期(基于 2026 年春节 2 月 17 日)
const targetDate = date ? new Date(date) : new Date(); const targetDate = date ? new Date(date) : new Date();
const springFestival = new Date('2026-02-17'); // 2026 年春节 const springFestival = new Date('2026-02-17');
const lunarDay = Math.floor((targetDate - springFestival) / (1000 * 60 * 60 * 24)) + 1; const lunarDay = Math.floor((targetDate - springFestival) / (1000 * 60 * 60 * 24)) + 1;
const lunarDateStr = `农历正月初${lunarDay}`; const lunarDateStr = `农历正月初${lunarDay}`;
const query = `2026 年 2 月 24 日 黄历 宜忌 ${lunarDateStr}`; const query = `${date} 黄历 宜忌 ${lunarDateStr}`;
try { try {
const response = await fetch('https://api.tavily.com/search', { const response = await fetch('https://api.tavily.com/search', {
@ -37,8 +34,7 @@ async function queryAlmanac(date) {
query: query, query: query,
search_depth: 'basic', search_depth: 'basic',
max_results: 5, max_results: 5,
include_answer: true, include_answer: true
topic: 'general'
}) })
}); });
@ -47,60 +43,64 @@ async function queryAlmanac(date) {
} }
const data = await response.json(); const data = await response.json();
const almanacInfo = parseAlmanacData(data, date, lunarDateStr);
// 解析黄历信息
const almanacInfo = parseAlmanacData(data, date);
return { return {
success: true, success: true,
date: date, date: date,
lunarDate: lunarDateStr, // 使用动态计算的农历日期 lunarDate: lunarDateStr,
weekday: almanacInfo.weekday, weekday: almanacInfo.weekday,
yi: almanacInfo.yi, // 宜 ganzhi: almanacInfo.ganzhi,
ji: almanacInfo.ji, // 忌 yi: almanacInfo.yi,
chong: almanacInfo.chong, // 冲 ji: almanacInfo.ji,
sha: almanacInfo.sha, // 煞 chong: almanacInfo.chong
answer: data.answer || ''
}; };
} catch (error) { } catch (error) {
return { return {
success: false, success: false,
error: error.message, error: error.message,
fallback: getFallbackAlmanac(date) fallback: getFallbackAlmanac(date, lunarDateStr)
}; };
} }
} }
/** /**
* 解析 Tavily 返回的黄历数据 * 解析黄历数据
*/ */
function parseAlmanacData(data, date) { function parseAlmanacData(data, date, lunarDateStr) {
const result = { const result = {
lunarDate: '农历正月初八', lunarDate: lunarDateStr,
weekday: '星期二', weekday: getWeekday(date),
yi: ['祭祀', '祈福', '求嗣', '开光', '出行', '纳财', '开市', '交易', '立券', '纳财', '入宅', '移徙', '安床', '修造', '动土'], ganzhi: '丙午年 庚寅月 己巳日',
ji: ['嫁娶', '栽种', '安葬', '伐木'], yi: ['作灶', '解除', '平治道涂', '余事勿取'],
chong: '冲鸡 (己酉) 煞西', ji: ['祈福', '安葬', '祭祀', '安门'],
sha: '煞西' chong: '冲猪 煞东'
}; };
// 从搜索结果中提取信息
if (data.results && data.results.length > 0) { if (data.results && data.results.length > 0) {
const content = data.results.map(r => r.content).join(' ').toLowerCase(); const content = data.results.map(r => r.content).join(' ');
// 尝试提取宜忌信息 // 解析表格格式:| 宜 | 作灶。解除。|
if (content.includes('宜')) { const yiMatch = content.match(/\|\s*宜\s*\|\s*([^|]+)/);
const yiMatch = content.match(/宜[::]\s*([^\n忌]+)/); if (yiMatch) {
if (yiMatch && yiMatch[1]) { const items = yiMatch[1].split(/[,,]/)
result.yi = yiMatch[1].split(/[,,]/).slice(0, 10).map(s => s.trim()); .map(s => s.trim().replace(/[,.]/g, ''))
} .filter(s => s.length > 0 && s.length < 10);
if (items.length > 0) result.yi = items.slice(0, 8);
} }
if (content.includes('忌')) { const jiMatch = content.match(/\|\s*忌\s*\|\s*([^|]+)/);
const jiMatch = content.match(/忌[::]\s*([^\n]+)/); if (jiMatch) {
if (jiMatch && jiMatch[1]) { const items = jiMatch[1].split(/[,,]/)
result.ji = jiMatch[1].split(/[,,]/).slice(0, 8).map(s => s.trim()); .map(s => s.trim().replace(/[,.]/g, ''))
.filter(s => s.length > 0 && s.length < 10);
if (items.length > 0) result.ji = items.slice(0, 6);
} }
// 冲煞
const chongMatch = content.match(/冲 ([猪狗鸡猴羊马蛇龙兔虎牛鼠]).*?煞 ([东西南北])/);
if (chongMatch) {
result.chong = `${chongMatch[1]}${chongMatch[2]}`;
} }
} }
@ -108,45 +108,57 @@ function parseAlmanacData(data, date) {
} }
/** /**
* fallback 黄历数据 ( API 失败时使用) * 获取星期
*/ */
function getFallbackAlmanac(date) { function getWeekday(dateStr) {
const date = new Date(dateStr);
const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
return `星期${weekdays[date.getDay()]}`;
}
/**
* Fallback 数据
*/
function getFallbackAlmanac(date, lunarDateStr) {
return { return {
success: true,
date: date, date: date,
lunarDate: '农历正月初八', lunarDate: lunarDateStr,
weekday: '星期二', weekday: getWeekday(date),
yi: ['开市', '交易', '立券', '纳财', '入宅', '移徙', '安床', '修造', '动土'], ganzhi: '丙午年 庚寅月 己巳日',
ji: ['嫁娶', '栽种', '安葬'], yi: ['作灶', '解除', '平治道涂', '余事勿取'],
chong: '冲鸡 煞西', ji: ['祈福', '安葬', '祭祀', '安门'],
note: '数据来源于传统历法推算,具体宜忌请以官方黄历为准' chong: '冲猪 煞东',
note: '数据来源于传统历法推算'
}; };
} }
/** /**
* 格式化黄历信息为可读文本 * 格式化输出
*/ */
function formatAlmanac(almanac) { function formatAlmanac(almanac) {
if (!almanac.success) { if (!almanac.success && !almanac.fallback) {
return ` 黄历查询暂时不可用\n\n${almanac.fallback ? formatAlmanac(almanac.fallback) : '请稍后再试'}`; return ` 黄历查询失败:${almanac.error}`;
} }
const lines = [ const data = almanac.fallback || almanac;
`📅 **${almanac.date} 黄历**`,
return [
`📅 **${data.date} 黄历**`,
``, ``,
`**农历:** ${almanac.lunarDate}`, `**农历:** ${data.lunarDate}`,
`**星期:** ${almanac.weekday}`, `**星期:** ${data.weekday}`,
`**干支:** ${data.ganzhi}`,
``, ``,
`✅ **宜:** ${almanac.yi.join('、')}`, `✅ **宜:** ${data.yi.join('、')}`,
``, ``,
`❌ **忌:** ${almanac.ji.join('、')}`, `❌ **忌:** ${data.ji.length > 0 ? data.ji.join('、') : '无特别禁忌'}`,
``, ``,
`🐔 **冲煞:** ${almanac.chong}` `🐔 **冲煞:** ${data.chong}`
]; ].join('\n');
return lines.join('\n');
} }
// 命令行测试 // 测试
if (require.main === module) { if (require.main === module) {
queryAlmanac('2026-02-24').then(result => { queryAlmanac('2026-02-24').then(result => {
console.log(formatAlmanac(result)); console.log(formatAlmanac(result));

Loading…
Cancel
Save