diff --git a/scripts/fetchers/usd-cny-rate.fetcher.js b/scripts/fetchers/usd-cny-rate.fetcher.js new file mode 100644 index 0000000..c2b5034 --- /dev/null +++ b/scripts/fetchers/usd-cny-rate.fetcher.js @@ -0,0 +1,150 @@ +import axios from 'axios'; +import { fileURLToPath } from 'url'; + +const FRANKFURTER_API = 'https://api.frankfurter.app'; + +async function fetch(startDate = null, endDate = null) { + try { + const currentDate = new Date(); + + if (!startDate) { + startDate = new Date(currentDate); + startDate.setDate(startDate.getDate() - 30); + startDate = startDate.toISOString().split('T')[0]; + } + + if (!endDate) { + endDate = currentDate.toISOString().split('T')[0]; + } + + console.log('正在获取人民币美元汇率数据...'); + console.log(`时间范围: ${startDate} 至 ${endDate}`); + console.log(`数据源: Frankfurter API (欧洲央行汇率数据)`); + + const response = await axios.get(`${FRANKFURTER_API}/${startDate}..${endDate}`, { + params: { + from: 'USD', + to: 'CNY' + }, + headers: { + 'Accept': 'application/json' + } + }); + + const data = response.data; + console.log(`\nAPI状态: ${response.status}`); + console.log(`数据条数: ${Object.keys(data.rates || {}).length}`); + + const allRates = []; + + if (data.rates) { + for (const [date, rateObj] of Object.entries(data.rates)) { + const rateValue = rateObj.CNY; + allRates.push({ + date: date, + currency: 'USD/CNY', + centerPrice: parseFloat(rateValue.toFixed(4)), + sellingRate: parseFloat(rateValue.toFixed(4)), + buyingRate: parseFloat(rateValue.toFixed(4)), + source: '欧洲央行 (Frankfurter API)', + fetchTime: new Date().toISOString() + }); + } + } + + allRates.sort((a, b) => a.date.localeCompare(b.date)); + + console.log(`\n共获取到 ${allRates.length} 条汇率数据`); + + return { + currency: 'USD/CNY', + startDate, + endDate, + count: allRates.length, + data: allRates, + fetchTime: new Date().toISOString(), + note: '数据来源: 欧洲央行, 通过 Frankfurter API 提供' + }; + + } catch (error) { + console.error('获取汇率数据失败:', error.message); + if (error.response) { + console.error(`HTTP状态码: ${error.response.status}`); + console.error(`响应数据:`, error.response.data); + } + throw error; + } +} + +export { + fetch +}; + +const isMainModule = () => { + const currentFile = fileURLToPath(import.meta.url); + const mainFile = process.argv[1]; + return currentFile === mainFile; +}; + +function parseCommandLineArgs() { + const args = process.argv.slice(2); + let startDate = null; + let endDate = null; + + for (let i = 0; i < args.length; i++) { + if (args[i] === '--start' && i + 1 < args.length) { + startDate = args[i + 1]; + i++; + } else if (args[i] === '--end' && i + 1 < args.length) { + endDate = args[i + 1]; + i++; + } else if (args[i] === '--help') { + console.log('使用方法:'); + console.log(' bun usd-cny-rate.fetcher.js [选项]'); + console.log(''); + console.log('选项:'); + console.log(' --start YYYY-MM-DD 指定开始日期(默认:30天前)'); + console.log(' --end YYYY-MM-DD 指定结束日期(默认:今天)'); + console.log(' --help 显示帮助信息'); + console.log(''); + console.log('示例:'); + console.log(' bun usd-cny-rate.fetcher.js'); + console.log(' bun usd-cny-rate.fetcher.js --start 2024-01-01 --end 2024-01-31'); + process.exit(0); + } + } + + return { startDate, endDate }; +} + +if (isMainModule()) { + const { startDate, endDate } = parseCommandLineArgs(); + + console.log('='.repeat(50)); + console.log('人民币美元汇率获取脚本'); + console.log('='.repeat(50)); + + fetch(startDate, endDate) + .then(result => { + console.log('\n' + '='.repeat(50)); + console.log('获取结果:'); + console.log(` 货币对: ${result.currency}`); + console.log(` 开始日期: ${result.startDate}`); + console.log(` 结束日期: ${result.endDate}`); + console.log(` 数据条数: ${result.count}`); + console.log(` 获取时间: ${result.fetchTime}`); + console.log(` 提示: ${result.note}`); + if (result.count > 0) { + console.log('-'.repeat(50)); + console.log('汇率数据:'); + result.data.forEach(item => { + console.log(` ${item.date} 中间价: ${item.centerPrice}`); + }); + } + console.log('='.repeat(50)); + }) + .catch(error => { + console.error('执行失败:', error); + process.exit(1); + }); +}