-module(birl@duration). -compile(no_auto_import). -export([new/1, accurate_new/1, decompose/1, accurate_decompose/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 * 1000); minute -> Total + (Amount * 60000); hour -> Total + (Amount * 3600000); day -> Total + (Amount * 86400000); week -> Total + (Amount * 604800000); month -> Total + (Amount * 2592000000); year -> Total + (Amount * 31536000000) 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 * 1000); minute -> Total + (Amount * 60000); hour -> Total + (Amount * 3600000); day -> Total + (Amount * 86400000); week -> Total + (Amount * 604800000); month -> Total + (Amount * 2629746000); year -> Total + (Amount * 31556952000) end end ), {duration, _pipe@1}. -spec decompose(duration()) -> list({integer(), unit()}). decompose(Duration) -> {duration, Value} = Duration, {Years, Remaining} = extract(Value, 31536000000), {Months, Remaining@1} = extract(Remaining, 2592000000), {Days, Remaining@2} = extract(Remaining@1, 86400000), {Hours, Remaining@3} = extract(Remaining@2, 3600000), {Minutes, Remaining@4} = extract(Remaining@3, 60000), {Seconds, Remaining@5} = extract(Remaining@4, 1000), _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, 31556952000), {Months, Remaining@1} = extract(Remaining, 2629746000), {Days, Remaining@2} = extract(Remaining@1, 86400000), {Hours, Remaining@3} = extract(Remaining@2, 3600000), {Minutes, Remaining@4} = extract(Remaining@3, 60000), {Seconds, Remaining@5} = extract(Remaining@4, 1000), _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 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 => 126}) 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 => 127}) end, {Amount@1, Remaining@1}.