对于日期为 2026 年 10 月 10 日(周六)的发票,使用 2026 年 10 月 9 日(周五)的 EUR/USD 汇率 1.1206:EUR 12,500 换算为 USD 14,007.50。因为周末没有汇率,所以请求前七天的数据,并取发票日期当天或之前的最后一行。
使用 API 完成操作
- 设置你的 API 密钥 获取免费密钥,并保存在环境变量
NARWHAL_API_KEY中。脚本会读取该变量,并通过Authorization: Bearer YOUR_KEY请求头发送密钥。Narwhal 的 REST API 和 MCP 使用同一个密钥;这里的请求发往 REST API。 - 请求发票日期及之前几天的数据 使用
GET /v1/fx/rates/EUR/observations,并带上currencies=USD、start_date和end_date。与脚本一样,把结束日期设为发票日期,开始日期为其减去七天。这样即使发票日期落在周末或节假日,响应中也会包含此前有汇率的日期。 - 读取最后一条观测值 用发票日期、基础币种和报价币种运行 Python 脚本。函数会取
observations中的最后一行,并同时返回它的日期和汇率。请把两者放在一起保存:发票日期是你要查询的日期,而返回的日期标明了换算所用的观测值。import os from datetime import date, timedelta import requests def rate_on(invoice: date, base: str, quote: str) -> tuple[str, float]: """The rate for the invoice date, or for the last day with a rate before it (weekends, holidays).""" start = invoice - timedelta(days=7) r = requests.get( f"https://api.narwhalapi.com/v1/fx/rates/{base}/observations", params={ "currencies": quote, "start_date": start.isoformat(), "end_date": invoice.isoformat(), "limit": 100, }, headers={"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"}, timeout=10, ) r.raise_for_status() last = r.json()["observations"][-1] return last["date"], float(last["rates"][0]["rate"]) day, rate = rate_on(date(2026, 10, 10), "EUR", "USD") # 10 October 2026 is a Saturday print(day, rate, "-> EUR 12,500 =", round(12500 * rate, 2), "USD") - 将发票金额乘以汇率 用返回的汇率换算发票金额。对于日期为 2026 年 10 月 10 日的发票,脚本返回 2026 年 10 月 9 日和汇率 1.1206。输出结果会把观测日期和换算后的金额放在一起。如果有数百张发票,请使用带七天窗口缓存的脚本。
使用电子表格或手动计算
如果只有少量发票,可以用一个存放已获取汇率的表格,包含一列日期和一列汇率。应用查找之前,先把日期按升序排序。将发票日期放在 A2,并在公式中用 dates 和 rates 表示对应的列。
=LOOKUP(A2, dates, rates)近似匹配会返回不晚于 A2 的最近日期的汇率。因此周六的发票会使用此前有汇率的那一天,无需另写周末公式。把发票金额乘以返回的汇率,并使用你需要的币种方向的汇率。表格方式与脚本遵循相同的规则:选取截至发票日期的最后一条可用观测值。请在会计政策中写明这条周末和节假日规则。
不同情况应选哪种方法
| 情况 | 最合适的方法 | 原因 |
|---|---|---|
| 少量发票 | 在已获取汇率的表格中查找 | 用日期近似匹配处理周末 |
| 数百张发票 | 带七天窗口缓存的脚本 | 对所有发票使用日期查找 |
| 法定汇率 | 主管机构公布的汇率 | Narwhal 提供的是市场每日观测汇率 |
税务机关或审计师接受哪种汇率,取决于你的会计政策。该政策可能要求使用发票日期、付款日期、月平均汇率或央行汇率。在使用日期查找之前,请先确定适用哪一种。Narwhal 提供的是市场每日观测汇率;如果政策要求法定汇率,请使用主管机构公布的汇率。这里按发票日期的计算,适用于政策要求采用该日期和这些市场观测值的情形。
应该按哪个货币对方向请求?
请求时把发票币种作为基础币种,把要换算成的币种作为报价币种。对于以 EUR 开具、要换算成 USD 的发票,请以 EUR 为基础币种、USD 为报价币种。返回的汇率是每 EUR 兑多少 USD,所以把 EUR 发票金额乘以该汇率。
基础币种放在 observations 端点的路径中,报价币种则放在 currencies 参数里。在 Python 调用中,发票日期之后的基础币种和报价币种参数就是同样的选择。把汇率放入表格时也要保持这个方向,这样 EUR 发票的查找结果就是每 EUR 兑多少 USD。
可以用 convert 端点查询发票日期的汇率吗?
过去的发票日期请使用 observations,因为 convert 端点没有日期参数。GET /v1/fx/convert?from=EUR&to=USD&amount=12500 只按当前汇率换算,不会选取发票日期当天适用的观测值。对于有日期的发票,请求 observations 的时间范围,并把金额乘以该日期当天或之前的最后一个汇率。
为什么响应是从我请求的日期之后才开始?
按发票查询时,范围需要包含发票日期,以及在该日期没有汇率时可用的更早观测值。所有账户都可读取完整历史。
错误使用 application/problem+json,包含 status、code、detail 和 request_id;请求失败时请阅读错误详情。
实例:2026 年 10 月 10 日开具的 EUR 12,500 发票
从发票日期 2026 年 10 月 10 日(周六)和金额 EUR 12,500 开始。请求截至该日期的七天窗口。由于发票日期落在周末,取此前的最后一条观测值:2026 年 10 月 9 日(周五)。当天的 EUR/USD 汇率是每 EUR 兑 USD 1.1206。
按 2026 年 10 月 9 日的汇率,把 EUR 12,500 乘以 1.1206,得到 2026 年 10 月 10 日发票的金额 USD 14,007.50。脚本会把观测日期输出为 2026-10-09,把换算后的金额输出为 14007.5 USD。
| 步骤 | 数值 |
|---|---|
| 发票日期 | 2026 年 10 月 10 日,周六 |
| 观测日期 | 2026 年 10 月 9 日,周五 |
| 2026 年 10 月 9 日的 EUR/USD 汇率 | 每 EUR 兑 USD 1.1206 |
| 换算 2026 年 10 月 10 日的发票 | 结果:EUR 12,500 × 1.1206 = USD 14,007.50 |
发布于。