Current section

Files

Jump to
birl src birl@duration.erl
Raw

src/birl@duration.erl

-module(birl@duration).
-compile(no_auto_import).
-export([new/1, accurate_new/1, decompose/1, accurate_decompose/1, parse/1]).
-export_type([duration/0, unit/0]).
-type duration() :: {duration, integer()}.
-type unit() :: milli_second |
second |
minute |
hour |
day |
week |
month |
year.
-spec new(list({integer(), unit()})) -> duration().
new(Values) ->
_pipe = Values,
_pipe@1 = gleam@list:fold(
_pipe,
0,
fun(Total, Current) ->
{Amount, Unit} = Current,
case Unit of
milli_second ->
Total + Amount;
second ->
Total + (Amount * 1000000);
minute ->
Total + (Amount * 60000000);
hour ->
Total + (Amount * 3600000000);
day ->
Total + (Amount * 86400000000);
week ->
Total + (Amount * 604800000000);
month ->
Total + (Amount * 2592000000000);
year ->
Total + (Amount * 31536000000000)
end
end
),
{duration, _pipe@1}.
-spec accurate_new(list({integer(), unit()})) -> duration().
accurate_new(Values) ->
_pipe = Values,
_pipe@1 = gleam@list:fold(
_pipe,
0,
fun(Total, Current) ->
{Amount, Unit} = Current,
case Unit of
milli_second ->
Total + Amount;
second ->
Total + (Amount * 1000000);
minute ->
Total + (Amount * 60000000);
hour ->
Total + (Amount * 3600000000);
day ->
Total + (Amount * 86400000000);
week ->
Total + (Amount * 604800000000);
month ->
Total + (Amount * 2629746000000);
year ->
Total + (Amount * 31556952000000)
end
end
),
{duration, _pipe@1}.
-spec decompose(duration()) -> list({integer(), unit()}).
decompose(Duration) ->
{duration, Value} = Duration,
{Years, Remaining} = extract(Value, 31536000000000),
{Months, Remaining@1} = extract(Remaining, 2592000000000),
{Days, Remaining@2} = extract(Remaining@1, 86400000000),
{Hours, Remaining@3} = extract(Remaining@2, 3600000000),
{Minutes, Remaining@4} = extract(Remaining@3, 60000000),
{Seconds, Remaining@5} = extract(Remaining@4, 1000000),
_pipe = [{Years, year},
{Months, month},
{Days, day},
{Hours, hour},
{Minutes, minute},
{Seconds, second},
{Remaining@5, milli_second}],
gleam@list:filter(_pipe, fun(Item) -> erlang:element(1, Item) > 0 end).
-spec accurate_decompose(duration()) -> list({integer(), unit()}).
accurate_decompose(Duration) ->
{duration, Value} = Duration,
{Years, Remaining} = extract(Value, 31556952000000),
{Months, Remaining@1} = extract(Remaining, 2629746000000),
{Days, Remaining@2} = extract(Remaining@1, 86400000000),
{Hours, Remaining@3} = extract(Remaining@2, 3600000000),
{Minutes, Remaining@4} = extract(Remaining@3, 60000000),
{Seconds, Remaining@5} = extract(Remaining@4, 1000000),
_pipe = [{Years, year},
{Months, month},
{Days, day},
{Hours, hour},
{Minutes, minute},
{Seconds, second},
{Remaining@5, milli_second}],
gleam@list:filter(_pipe, fun(Item) -> erlang:element(1, Item) > 0 end).
-spec parse(binary()) -> {ok, duration()} | {error, nil}.
parse(Expression) ->
{ok, Re@1} = case gleam@regex:from_string(<<"(\\d+)\\s*(\\w+)"/utf8>>) of
{ok, Re} -> {ok, Re};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"birl/duration"/utf8>>,
function => <<"parse"/utf8>>,
line => 183})
end,
{Accurate, Expression@2} = case gleam@string:starts_with(
Expression,
<<"accurate:"/utf8>>
) of
true ->
[_@1, Expression@1] = gleam@string:split(Expression, <<":"/utf8>>),
{true, Expression@1};
false ->
{false, Expression}
end,
case begin
_pipe = Expression@2,
_pipe@1 = gleam@string:split(_pipe, <<"+"/utf8>>),
_pipe@2 = gleam@list:map(_pipe@1, fun gleam@string:trim/1),
_pipe@3 = gleam@list:map(_pipe@2, fun gleam@string:lowercase/1),
_pipe@4 = gleam@list:map(
_pipe@3,
fun(_capture) -> gleam@regex:scan(Re@1, _capture) end
),
gleam@list:try_map(_pipe@4, fun(Item) -> case Item of
[{match, _@2, [{some, Amount_string}, {some, Unit}]}] ->
case gleam@int:parse(Amount_string) of
{error, _try@1} -> {error, _try@1};
{ok, Amount} ->
case gleam@list:find(
[{year,
[<<"y"/utf8>>,
<<"year"/utf8>>,
<<"years"/utf8>>]},
{month,
[<<"mon"/utf8>>,
<<"month"/utf8>>,
<<"months"/utf8>>]},
{week,
[<<"w"/utf8>>,
<<"week"/utf8>>,
<<"weeks"/utf8>>]},
{day,
[<<"d"/utf8>>,
<<"day"/utf8>>,
<<"days"/utf8>>]},
{hour,
[<<"h"/utf8>>,
<<"hour"/utf8>>,
<<"hours"/utf8>>]},
{minute,
[<<"m"/utf8>>,
<<"min"/utf8>>,
<<"minute"/utf8>>,
<<"minutes"/utf8>>]},
{second,
[<<"s"/utf8>>,
<<"sec"/utf8>>,
<<"secs"/utf8>>,
<<"second"/utf8>>,
<<"seconds"/utf8>>]},
{milli_second,
[<<"ms"/utf8>>,
<<"msec"/utf8>>,
<<"msecs"/utf8>>,
<<"millisecond"/utf8>>,
<<"milliseconds"/utf8>>]}],
fun(Item@1) ->
gleam@list:contains(
erlang:element(2, Item@1),
Unit
)
end
) of
{error, _try@2} -> {error, _try@2};
{ok, {Unit@1, _@3}} ->
_pipe@5 = {Amount, Unit@1},
{ok, _pipe@5}
end
end;
_@4 ->
{error, nil}
end end)
end of
{ok, Values} ->
_pipe@6 = case Accurate of
true ->
accurate_new(Values);
false ->
new(Values)
end,
{ok, _pipe@6};
{error, nil} ->
{error, nil}
end.
-spec extract(integer(), integer()) -> {integer(), integer()}.
extract(Duration, Unit) ->
{ok, Amount@1} = case gleam@int:divide(Duration, Unit) of
{ok, Amount} -> {ok, Amount};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"birl/duration"/utf8>>,
function => <<"extract"/utf8>>,
line => 226})
end,
{ok, Remaining@1} = case gleam@int:modulo(Duration, Unit) of
{ok, Remaining} -> {ok, Remaining};
_try@1 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@1,
module => <<"birl/duration"/utf8>>,
function => <<"extract"/utf8>>,
line => 227})
end,
{Amount@1, Remaining@1}.