frankfurter/lib/provider/adapters/nbrb.rb

74 lines
2.3 KiB
Ruby
Raw Normal View History

2026-05-21 01:38:14 -06:00
# frozen_string_literal: true
require "net/http"
require "oj"
require "provider/adapters/adapter"
class Provider
module Adapters
# National Bank of the Republic of Belarus. Publishes daily rates for ~30 currencies against BYN.
# BYN was redenominated on 2016-07-01; earlier data uses different currency IDs.
class NBRB < Adapter
RATES_URL = "https://api.nbrb.by/exrates/rates"
CHUNK_DAYS = 365
def fetch(after: nil, upto: nil)
currencies = current_currencies
currencies.flat_map do |cur_id, iso, scale|
chunked_dynamics(cur_id, iso, scale, after, upto || Date.today)
end
end
private
def parse_daily(data)
data.filter_map do |row|
date = Date.parse(row.fetch("Date"))
next if date.saturday? || date.sunday?
iso = row.fetch("Cur_Abbreviation")
scale = Integer(row.fetch("Cur_Scale"))
rate = Float(row.fetch("Cur_OfficialRate"))
next if scale.zero?
{ date:, base: iso, quote: "BYN", rate: rate / scale }
end
end
def current_currencies
data = Oj.load(Net::HTTP.get(URI("#{RATES_URL}?periodicity=0")), mode: :strict)
data.map { |row| [row.fetch("Cur_ID"), row.fetch("Cur_Abbreviation"), Integer(row.fetch("Cur_Scale"))] }
end
def chunked_dynamics(cur_id, iso, scale, start_date, end_date)
records = []
chunk_start = start_date
while chunk_start <= end_date
chunk_end = [chunk_start + CHUNK_DAYS - 1, end_date].min
records.concat(fetch_dynamics(cur_id, iso, scale, chunk_start, chunk_end))
chunk_start = chunk_end + 1
end
records
end
def fetch_dynamics(cur_id, iso, scale, start_date, end_date)
url = URI("#{RATES_URL}/dynamics/#{cur_id}")
url.query = URI.encode_www_form(startDate: start_date.to_s, endDate: end_date.to_s)
data = Oj.load(Net::HTTP.get(url), mode: :strict)
return [] unless data.is_a?(Array)
data.filter_map do |row|
date = Date.parse(row.fetch("Date"))
next if date.saturday? || date.sunday?
rate = Float(row.fetch("Cur_OfficialRate"))
{ date:, base: iso, quote: "BYN", rate: rate / scale }
end
end
end
end
end