# Unitful: parsing currencies

**URL:** <https://discourse.julialang.org/t/unitful-parsing-currencies/84705>\
**Category:** General Usage\
**Tags:** unitful\
**Created:** [July 24, 2022, 11:52am UTC](https://discourse.julialang.org/t/unitful-parsing-currencies/84705 "2022-07-24T11:52:40Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![stepanzh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stepanzh/32/34851_2.png) [@stepanzh](https://discourse.julialang.org/u/stepanzh)\
**Post date:** [July 24, 2022, 11:52am UTC](https://discourse.julialang.org/t/unitful-parsing-currencies/84705/1 "2022-07-24T11:52:41Z")

</div>

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](https://docs.juliahub.com/Unitful/5WYj5/1.3.0/newunits/) 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

```julia
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
=#

```

---

<div class="post-metadata">

**Author:** ![Ricardo\_Rosa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ricardo_rosa/32/18564_2.png) [@Ricardo\_Rosa](https://discourse.julialang.org/u/Ricardo_Rosa)\
**Post date:** [January 9, 2023, 12:16am UTC](https://discourse.julialang.org/t/unitful-parsing-currencies/84705/2 "2023-01-09T00:16:49Z")

</div>

> [@stepanzh](#):
>
> `@unit RussianRouble "₽" RussianRoubleSign 1RUB false false`

Hey, I saw this now when googling something related to Unitful. I am not sure you are still into this, but let me try to see if I can help.

The thing is that you need to use ₽ itself to define the unit:

```julia
@unit ₽ "₽" RussianRoubleSign 1RUB false false

```

The term within quotes is just to say how it will be displayed. It is the first term that defines how it will be used for parsing.

I can add that symbol in `UnitfulAssets.jl` if it is of any help.

---

<div class="post-metadata">

**Author:** ![cmichelenstrofer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cmichelenstrofer/32/44392_2.png) [@cmichelenstrofer](https://discourse.julialang.org/u/cmichelenstrofer)\
**Post date:** [January 9, 2023, 3:31am UTC](https://discourse.julialang.org/t/unitful-parsing-currencies/84705/3 "2023-01-09T03:31:40Z")

</div>

Each currency should **not** be its own dimension, they should be different units of the same dimension (e.g. _UnitfulAssets.jl_ calls it `cash`). So you should create

1. A `cash` or `currency` dimension
2. A reference unit
3. any number of additional units

Having them all be the same dimension allows you to convert between them easily.

Also, why not just use UnitfulAssets.jl? You can add new currencies in a single line as described by the comment above (either as a pull request to that repo or in your code).

---

<div class="post-metadata">

**Author:** ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)\
**Post date:** [January 9, 2023, 7:44am UTC](https://discourse.julialang.org/t/unitful-parsing-currencies/84705/4 "2023-01-09T07:44:35Z")

</div>

> [@stepanzh](#):
>
> ```julia
> @refunit RUB "RUB" RussianRoubleRefUnit 𝐑𝐔𝐁 false false
> @unit RussianRouble "₽" RussianRoubleSign 1RUB false false
> 
> ```

This defines two separate units, just with the same value. I wouldn’t recommend that. Instead, you can create `₽` as an alias for `RUB` as follows:

```julia
@refunit RUB "RUB" RussianRoubleRefUnit 𝐑𝐔𝐁 false false
const ₽ = RUB

```

This is used in the Unitful package itself, for example to make the `angstrom` unit also accessible as `Å`.

---

<div class="post-metadata">

**Author:** ![Ricardo\_Rosa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ricardo_rosa/32/18564_2.png) [@Ricardo\_Rosa](https://discourse.julialang.org/u/Ricardo_Rosa)\
**Post date:** [January 11, 2023, 10:43am UTC](https://discourse.julialang.org/t/unitful-parsing-currencies/84705/5 "2023-01-11T10:43:27Z")

</div>

> [@sostock](#):
>
> This defines two separate units, just with the same value. I wouldn’t recommend that. Instead, you can create `₽` as an alias for `RUB` as follows:

Yeah, I agree, that is better. Thanks.

---

<div class="post-metadata">

**Author:** ![Ricardo\_Rosa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ricardo_rosa/32/18564_2.png) [@Ricardo\_Rosa](https://discourse.julialang.org/u/Ricardo_Rosa)\
**Post date:** [January 11, 2023, 10:54am UTC](https://discourse.julialang.org/t/unitful-parsing-currencies/84705/6 "2023-01-11T10:54:42Z")

</div>

Hmm, actually, one of the main points of that was to have a different display for the currency. If I use an alias for RUB instead of a different unit, as currently implemented for USD, then I get it still displayed as RUB:

```julia
julia> 1u"USD"
1 USD

julia> 1u"USdollar"
1 US$

julia> 1u"RUB"
1 RUB

julia> 1u"₽"
1 RUB

```

The problem with that is that the exchange rate of US$ is not attached to that of USD, they are treated as different units/currencies. But the idea was to have that in the case someone is not so much interested in exchange rates but rather on working on a specific currency, with a more common notation.
