Unitful: parsing currencies

I have a table with cash operations. String representation of an operation contains a value and a currency name, e.g. 1.5 US$ or 1.5 RUB. I’ve decided to use Unitful.jl: Defining new units for keeping different currencies.

I want to write a function parsecash(s) -> Unitful.Quantity which will take care about currencies names as they stored in table and my “Unitful” currencies.

How can I parse different strings which represents same currencies? So,

  • "1 RUB" and "1 ₽" must be parsed as Unitful.Quantity(1, RUB);
  • "1 USD" and "1 US$" must be parsed as Unitful.Quantity(1, USD).

My code seems to parse "1.5 USD" and "1.5 RUB" correctly, but it can’t parse their aliases "1.5 US$" and "1.5 ₽".

Here is what I came with

using Unitful

# This is how UnitfulAssets.jl https://github.com/rmsrosa/UnitfulAssets.jl defines currencies

@dimension 𝐑𝐔𝐁 "𝐑𝐔𝐁" RussianRoubleCurrency
@refunit RUB "RUB" RussianRoubleRefUnit 𝐑𝐔𝐁 false false
@unit RussianRouble "₽" RussianRoubleSign 1RUB false false

@dimension 𝐔𝐒𝐃 "𝐔𝐒𝐃" USDollarCurrency
@refunit USD "USD" USDollarRefUnit 𝐔𝐒𝐃 false false
@unit USDollar "US\$" USDollarSign 1USD false false

# Seems unneeded (?)
# const localpromotion = Unitful.promotion
# function __init__()
#     Unitful.register(@__MODULE__)
#     merge!(Unitful.promotion, localpromotion)
# end
# __init__()

function parsecash(s)
    qstr, abbr = rsplit(s; limit=2)
    q = parse(Float64, qstr)
    return Quantity(q, uparse(abbr; unit_context=@__MODULE__))
end

@show parsecash("1.5 RUB")  # OK
@show parsecash("1.5 USD")  # OK

@show parsecash("1.5 RUB") + parsecash("1.5 RUB")  # OK

@show parsecash("1.5 ₽")
#=
ERROR: LoadError: ArgumentError: Symbol ₽ could not be found in unit modules Module[Main]
Stacktrace:
 [1] lookup_units(unitmods::Vector{Module}, sym::Symbol)
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/user.jl:707
 [2] lookup_units
   @ ~/.julia/packages/Unitful/SUQzL/src/user.jl:719 [inlined]
 [3] uparse(str::SubString{String}; unit_context::Module)
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/user.jl:662
 [4] parsecash(s::String)
   @ Main ~/Temp/discourse.jl:21
 [5] top-level scope
   @ show.jl:955
=#


@show parsecash("1.5 US\$")
#=
ERROR: LoadError: ArgumentError: Expr head incomplete must equal :call or :tuple
Stacktrace:
 [1] lookup_units(unitmods::Module, ex::Expr)
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/user.jl:688
 [2] uparse(str::SubString{String}; unit_context::Module)
   @ Unitful ~/.julia/packages/Unitful/SUQzL/src/user.jl:662
 [3] parsecash(s::String)
   @ Main ~/Temp/discourse.jl:21
 [4] top-level scope
   @ show.jl:955
=#