# Mizur
Pronounced `/'meʒə/`
**Mizur** is a tool to simplify the management, conversion
and mapping of units.
The manipulation of measurement units should (at best)
be typesafe.
![Mizur Logo](images/logo.png)
(A special thanks to [@fh-d](https://github.com/fh-d) for this awesome logo !)
- [Presentation](#content)
- [Some examples](#some-examples)
- [Installation](#installation)
- [Special thanks](#special-thanks)
## Some examples
### Basic example
Definition of a metric system for computing distances :
```elixir
defmodule Distance do
use Mizur.System
type m
type cm = m / 100
type mm = m / 1000
type km = m * 1000
end
```
Using this module provides the following functions:
- `Distance.m/0` : to reference the type `Distance.m`
- `Distance.cm/0` : to reference the type `Distance.cm`
- `Distance.mm/0` : to reference the type `Distance.mm`
- `Distance.km/0` : to reference the type `Distance.km`
and :
- `Distance.m/1` : to create packed values in the `Distance.m` type
- `Distance.cm/1` : to create packed values in the `Distance.cm` type
- `Distance.mm/1` : to create packed values in the `Distance.mm` type
- `Distance.km/1` : to create packed values in the `Distance.km` type
and sigils : `Distance.sigil_t(value, ['typename'])`.
#### Example of common Mizur usage
```elixir
a = Distance.m(200)
b = Distance.cm(200)
result = Mizur.add(a, b)
assert result = Distance.m(202)
```
### Using infix notation
You can use infix notation for operations on units of measurements
using `use Mizur.Infix`.
As with the `import` directive, you can use the `:except` and `:only` parameters
(exactly in the same way as using` import`).
The main difference with `import` is that `use` will overwrite the correct
operators of the `Kernel` module.
### Manage arithmetic operations on datetime
```elixir
defmodule MyTime do
use Mizur.System
type sec
type min = sec * 60
type hour = sec * 60 * 60
type day = sec * 60 * (60 * 24)
def now do
DateTime.utc_now()
|> DateTime.to_unix(:second)
|> sec()
end
def new(year, month, day, hour, min, sec) do
ndt = NaiveDateTime.new(year, month, day, hour, min, sec)
case ndt do
{:error, message} -> raise RuntimeError, message: "#{message}"
{:ok, value} ->
DateTime.from_naive!(value, "Etc/UTC")
|> DateTime.to_unix(:second)
|> sec()
end
end
def to_datetime(value) do
elt = Mizur.from(value, to: sec())
int = round(Mizur.unwrap(elt))
DateTime.from_unix!(int) #beurk, it is unsafe
end
end
use Mizur.Infix, only: [+: 2, -: 2]
import MyTime
# Create a typed_value of the current timestamp:
a = now()
# Add two days and four hour
b = a + ~t(2)day + ~t(4)hour # I use Sigils...
# Sub ten minuts
c = b - ~t(10)min
# Convert into DateTime
result = to_datetime(c)
```
### Other examples
The test module gives many usage examples :
[Test module](https://github.com/xvw/mizur/blob/master/test/mizur_test.exs)
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `mizur` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[{:mizur, "~> 0.1.1"}]
end
```
## Special Thanks
- [@julien-leclercq](https://github.com/julien-leclercq), a lot of help about unit-comprehension
- [@Fenntasy](https://github.com/Fenntasy), help for the design
- [@fh-d](https://github.com/fh-d), for the logo
- [@tgautier](https://github.com/tgautier) and the LilleFP team !
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/mizur/readme.html](https://hexdocs.pm/mizur/readme.html).