# frozen_string_literal: true require "json" require "net/http" require "provider/adapters/adapter" class Provider module Adapters # Central Bank of the Republic of China (Taiwan). Publishes daily interbank # spot rates for 15+ currencies against the US dollar. Rates are captured at # 16:00 Taipei time (08:00 UTC). The API returns the full historical dataset # (no server-side date filtering); client-side filtering is applied. # Historical data available from 1993-01-05. class CBC < Adapter API_URL = "https://cpx.cbc.gov.tw/API/DataAPI/Get?FileName=BP01D01" # Column index => [quote, base] # Most rates are quoted as foreign currency per 1 USD (quote=X, base=USD). # GBP, AUD, EUR are quoted as USD per 1 unit (quote=USD, base=X). # Columns 15-17 (DEM, FRF, NLG) contain historical data pre-2002. COLUMNS = { 1 => ["TWD", "USD"], 2 => ["JPY", "USD"], 3 => ["USD", "GBP"], 4 => ["HKD", "USD"], 5 => ["KRW", "USD"], 6 => ["CAD", "USD"], 7 => ["SGD", "USD"], 8 => ["CNY", "USD"], 9 => ["USD", "AUD"], 10 => ["IDR", "USD"], 11 => ["THB", "USD"], 12 => ["MYR", "USD"], 13 => ["PHP", "USD"], 14 => ["USD", "EUR"], 15 => ["DEM", "USD"], 16 => ["FRF", "USD"], 17 => ["NLG", "USD"], 18 => ["VND", "USD"], }.freeze def fetch(after: nil, upto: nil) end_date = upto || Date.today response = Net::HTTP.get(URI(API_URL)) data = JSON.parse(response) rows = data.dig("data", "dataSets") || [] parse(rows, after, end_date) end def parse(rows, start_date = nil, end_date = nil) rows.each_with_object([]) do |row, result| next unless row.is_a?(Array) && row.length > 1 date = Date.strptime(row[0], "%Y%m%d") next if start_date && date < start_date next if end_date && date > end_date COLUMNS.each do |index, (quote, base)| value = row[index] next if value.nil? || value == "-" rate = Float(value) next if rate.zero? result << { date:, base:, quote:, rate: } end end end end end end