121 lines
2.6 KiB
Ruby
121 lines
2.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "csv"
|
|
require "net/http"
|
|
require "oj"
|
|
|
|
require "provider/adapters/adapter"
|
|
|
|
class Provider
|
|
module Adapters
|
|
# Danmarks Nationalbank. Publishes daily exchange rates for 30 currencies
|
|
# against the Danish krone (DKK) via Statistics Denmark's Statbank API.
|
|
# Rates are quoted as DKK per 100 units of foreign currency.
|
|
class DNB < Adapter
|
|
URL = "https://api.statbank.dk/v1/data"
|
|
CURRENCIES = [
|
|
"EUR",
|
|
"USD",
|
|
"GBP",
|
|
"SEK",
|
|
"NOK",
|
|
"CHF",
|
|
"CAD",
|
|
"JPY",
|
|
"AUD",
|
|
"NZD",
|
|
"PLN",
|
|
"CZK",
|
|
"HUF",
|
|
"HKD",
|
|
"SGD",
|
|
"ZAR",
|
|
"BGN",
|
|
"RON",
|
|
"TRY",
|
|
"KRW",
|
|
"THB",
|
|
"MYR",
|
|
"PHP",
|
|
"IDR",
|
|
"CNY",
|
|
"BRL",
|
|
"MXN",
|
|
"INR",
|
|
"ILS",
|
|
"ISK",
|
|
"ATS",
|
|
"BEF",
|
|
"DEM",
|
|
"ESP",
|
|
"FIM",
|
|
"FRF",
|
|
"GRD",
|
|
"IEP",
|
|
"ITL",
|
|
"NLG",
|
|
"PTE",
|
|
"SIT",
|
|
"ROL",
|
|
"TRL",
|
|
].freeze
|
|
|
|
def fetch(after: nil, upto: nil)
|
|
tid = ">=#{format_date(after)}"
|
|
tid += "<=#{format_date(upto || Date.today)}" if upto
|
|
|
|
body = Oj.dump(
|
|
{
|
|
table: "DNVALD",
|
|
format: "BULK",
|
|
lang: "en",
|
|
valuePresentation: "Code",
|
|
variables: [
|
|
{ code: "VALUTA", values: CURRENCIES },
|
|
{ code: "KURTYP", values: ["KBH"] },
|
|
{ code: "Tid", values: [tid] },
|
|
],
|
|
},
|
|
mode: :compat,
|
|
)
|
|
|
|
uri = URI(URL)
|
|
response = Net::HTTP.post(uri, body, "Content-Type" => "application/json")
|
|
parse(response.body)
|
|
end
|
|
|
|
def parse(csv)
|
|
csv = csv.encode("UTF-8", "UTF-8", invalid: :replace, undef: :replace)
|
|
csv = csv.sub("\xEF\xBB\xBF", "")
|
|
rows = CSV.parse(csv, col_sep: ";", headers: true)
|
|
|
|
rows.filter_map do |row|
|
|
code = row["VALUTA"]
|
|
next unless code&.match?(/\A[A-Z]{3}\z/)
|
|
|
|
rate_str = row["INDHOLD"]
|
|
next if rate_str.nil? || rate_str.strip == ".."
|
|
|
|
rate = Float(rate_str)
|
|
next if rate.zero?
|
|
|
|
tid = row["TID"]
|
|
next unless tid
|
|
|
|
date = parse_date(tid)
|
|
{ date:, base: code, quote: "DKK", rate: rate / 100.0 }
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def format_date(date)
|
|
date.strftime("%YM%mD%d")
|
|
end
|
|
|
|
def parse_date(str)
|
|
Date.new(str[0, 4].to_i, str[5, 2].to_i, str[8, 2].to_i)
|
|
end
|
|
end
|
|
end
|
|
end
|