diff --git a/README.md b/README.md index bc7de52..ab14283 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ sqrt(144) 32 f to c 1 GiB to MiB 100 USD to DKK +1000 yen to DKK 0.5 BTC to ETH ``` @@ -109,6 +110,8 @@ Convert length, mass, temperature, volume, duration, speed, area, and data with Currency and crypto conversions require internet access and use [currency-api](https://github.com/fawazahmed0/exchange-api). These are **daily rates, not live market prices**; the snapshot date is shown with the answer. Treat them as estimates, not trading or payment quotes. Fetch failures show an error rather than silently using old rates; change the query to retry. +`yen` is accepted as an alias for `JPY` in either conversion direction, case-insensitively. + Rates are shared across queries and refreshed on the next currency query after the local day changes. While refreshing, a cached answer remains copyable and is labeled stale. Leaving the query or dismissing the launcher does not cancel that shared refresh. `ConjureKit.CurrencyCalculation` owns this lifetime policy; the launcher renders its result. Its checks use an injected clock and scripted rate fetches. diff --git a/Sources/ConjureKit/Calculator.swift b/Sources/ConjureKit/Calculator.swift index f7b35aa..d0d4a2f 100644 --- a/Sources/ConjureKit/Calculator.swift +++ b/Sources/ConjureKit/Calculator.swift @@ -105,6 +105,7 @@ public enum Calculator { private static func currencyCode(_ text: String, rates: CurrencyRates?) -> String? { let code = text.lowercased() + if code == "yen" { return "jpy" } guard (2...12).contains(code.utf8.count), code.utf8.allSatisfy({ (97...122).contains($0) || (48...57).contains($0) }), ConversionUnit.parse(text) == nil else { return nil } diff --git a/Tests/ConjureKitTests/CurrencyTests.swift b/Tests/ConjureKitTests/CurrencyTests.swift index 105d044..c57e0e8 100644 --- a/Tests/ConjureKitTests/CurrencyTests.swift +++ b/Tests/ConjureKitTests/CurrencyTests.swift @@ -11,6 +11,21 @@ func calculatorCrossConvertsCurrencyExpressionsAndPreservesSnapshotDate() throws #expect(result.detail == "2*50 USD → DKK · Daily snapshot 2026-01-02") } +@Test +func calculatorConvertsYenAsJPYInEitherDirection() { + let snapshot = CurrencyRates(date: "2026-01-02", rates: ["eur": 1, "jpy": 160, "dkk": 8]) + for (query, expected) in [ + ("1000 yen to dkk", "50 DKK"), + ("1000JPY to DKK", "50 DKK"), + ("1000YeN in dkk", "50 DKK"), + ("50 DKK as yen", "1000 JPY"), + ("2*500 yen to JPY", "1000 JPY"), + ] { + #expect(Calculator.isCurrencyQuery(query), "\(query)") + #expect(Calculator.evaluate(query, currencyRates: snapshot)?.copyValue == expected, "\(query)") + } +} + @Test func calculatorConvertsFiatAndCryptoWithCaseInsensitiveSeparators() { let snapshot = CurrencyRates(date: "2026-01-02", rates: [