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 asUnitful.Quantity(1, RUB)
; -
"1 USD"
and"1 US$"
must be parsed asUnitful.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
=#