frankfurter/lib/provider/adapters/bnr.rb

63 lines
1.8 KiB
Ruby
Raw Permalink Normal View History

2026-05-21 01:38:14 -06:00
# frozen_string_literal: true
require "net/http"
require "ox"
require "provider/adapters/adapter"
class Provider
module Adapters
# National Bank of Romania. Publishes daily reference rates for ~35
# currencies against the Romanian leu (RON). Yearly XML archives back to
# 2005 are kept current within the year. The 10-day feed is a redundant
# window over the same data, so we always use the yearly archive.
class BNR < Adapter
BASE_URL = "https://www.bnr.ro"
class << self
def backfill_range = 365
end
def fetch(after: nil, upto: nil)
end_date = upto || Date.today
records = if after.nil? || after.year == end_date.year
fetch_year(after&.year || end_date.year)
else
(after.year..end_date.year).flat_map { |year| fetch_year(year) }
end
records.select { |r| (after.nil? || r[:date] > after) && r[:date] <= end_date }
end
def parse(xml)
doc = Ox.load(xml)
doc.locate("DataSet/Body/Cube").flat_map do |cube|
date = Date.parse(cube[:date])
cube.locate("Rate").filter_map do |rate_node|
currency = rate_node[:currency]
next unless currency&.match?(/\A[A-Z]{3}\z/)
multiplier = rate_node[:multiplier]&.to_i || 1
rate_value = Float(rate_node.text, exception: false)
next unless rate_value
rate_value /= multiplier if multiplier > 1
rate_value *= GRAMS_PER_TROY_OUNCE if currency == "XAU"
next if rate_value.zero?
{ date:, base: currency, quote: "RON", rate: rate_value }
end
end
end
private
def fetch_year(year)
parse(Net::HTTP.get(URI("#{BASE_URL}/files/xml/years/nbrfxrates#{year}.xml")))
end
end
end
end