Current section
Files
Jump to
Current section
Files
src/birl@duration.erl
-module(birl@duration).
-compile([no_auto_import, nowarn_unused_vars]).
-export([new/1, accurate_new/1, parse/1, decompose/1, accurate_decompose/1]).
-export_type([duration/0, unit/0]).
-type duration() :: {duration, integer()}.
-type unit() :: micro_second |
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) -> case Current of
{Amount, micro_second} ->
Total + Amount;
{Amount@1, milli_second} ->
Total + (Amount@1 * 1000);
{Amount@2, second} ->
Total + (Amount@2 * 1000000);
{Amount@3, minute} ->
Total + (Amount@3 * 60000000);
{Amount@4, hour} ->
Total + (Amount@4 * 3600000000);
{Amount@5, day} ->
Total + (Amount@5 * 86400000000);
{Amount@6, week} ->
Total + (Amount@6 * 604800000000);
{Amount@7, month} ->
Total + (Amount@7 * 2592000000000);
{Amount@8, year} ->
Total + (Amount@8 * 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) -> case Current of
{Amount, micro_second} ->
Total + Amount;
{Amount@1, milli_second} ->
Total + (Amount@1 * 1000);
{Amount@2, second} ->
Total + (Amount@2 * 1000000);
{Amount@3, minute} ->
Total + (Amount@3 * 60000000);
{Amount@4, hour} ->
Total + (Amount@4 * 3600000000);
{Amount@5, day} ->
Total + (Amount@5 * 86400000000);
{Amount@6, week} ->
Total + (Amount@6 * 604800000000);
{Amount@7, month} ->
Total + (Amount@7 * 2629746000000);
{Amount@8, year} ->
Total + (Amount@8 * 31556952000000)
end end),
{duration, _pipe@1}.
-spec parse(binary()) -> {ok, duration()} | {error, nil}.
parse(Expression) ->
_assert_subject = gleam@regex:from_string(<<"(\\d+)\\s*(\\w+)"/utf8>>),
{ok, Re} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"birl/duration"/utf8>>,
function => <<"parse"/utf8>>,
line => 204})
end,
{Accurate, Expression@2} = case gleam@string:starts_with(
Expression,
<<"accurate:"/utf8>>
) of
true ->
[_, 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, _capture) end
),
gleam@list:try_map(_pipe@4, fun(Item) -> case Item of
[{match, _, [{some, Amount_string}, {some, Unit}]}] ->
gleam@result:then(
gleam@int:parse(Amount_string),
fun(Amount) ->
gleam@result:then(
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
),
fun(_use0) ->
{Unit@1, _} = _use0,
_pipe@5 = {Amount, Unit@1},
{ok, _pipe@5}
end
)
end
);
_ ->
{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) ->
{case Unit of
0 -> 0;
Gleam@denominator -> Duration div Gleam@denominator
end, case Unit of
0 -> 0;
Gleam@denominator@1 -> Duration rem Gleam@denominator@1
end}.
-spec decompose(duration()) -> list({integer(), unit()}).
decompose(Duration) ->
{duration, Value} = Duration,
Absolute_value = gleam@int:absolute_value(Value),
{Years, Remaining} = extract(Absolute_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),
{Milli_seconds, Remaining@6} = extract(Remaining@5, 1000),
_pipe = [{Years, year},
{Months, month},
{Days, day},
{Hours, hour},
{Minutes, minute},
{Seconds, second},
{Milli_seconds, milli_second},
{Remaining@6, micro_second}],
_pipe@1 = gleam@list:filter(
_pipe,
fun(Item) -> erlang:element(1, Item) > 0 end
),
gleam@list:map(_pipe@1, fun(Item@1) -> case Value < 0 of
true ->
{-1 * erlang:element(1, Item@1), erlang:element(2, Item@1)};
false ->
Item@1
end end).
-spec accurate_decompose(duration()) -> list({integer(), unit()}).
accurate_decompose(Duration) ->
{duration, Value} = Duration,
Absolute_value = gleam@int:absolute_value(Value),
{Years, Remaining} = extract(Absolute_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),
{Milli_seconds, Remaining@6} = extract(Remaining@5, 1000),
_pipe = [{Years, year},
{Months, month},
{Days, day},
{Hours, hour},
{Minutes, minute},
{Seconds, second},
{Milli_seconds, milli_second},
{Remaining@6, micro_second}],
_pipe@1 = gleam@list:filter(
_pipe,
fun(Item) -> erlang:element(1, Item) > 0 end
),
gleam@list:map(_pipe@1, fun(Item@1) -> case Value < 0 of
true ->
{-1 * erlang:element(1, Item@1), erlang:element(2, Item@1)};
false ->
Item@1
end end).