Current section
Files
Jump to
Current section
Files
src/tempo@offset.erl
-module(tempo@offset).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([new/1, to_string/1, from_string/1, literal/1, to_duration/1, local_minutes/0, local/0, local_nano/0]).
-spec validate(tempo:offset()) -> {ok, tempo:offset()} | {error, tempo:error()}.
validate(Offset) ->
case (erlang:element(2, Offset) >= -720) andalso (erlang:element(2, Offset)
=< 840) of
true ->
{ok, Offset};
false ->
{error, offset_out_of_bounds}
end.
-spec new(integer()) -> {ok, tempo:offset()} | {error, tempo:error()}.
new(Minutes) ->
_pipe = {offset, Minutes},
validate(_pipe).
-spec to_string(tempo:offset()) -> binary().
to_string(Offset) ->
{Is_negative, Hours} = case erlang:element(2, Offset) div 60 of
H when H =< 0 ->
{true, - H};
H@1 ->
{false, H@1}
end,
Mins = case erlang:element(2, Offset) rem 60 of
M when M < 0 ->
- M;
M@1 ->
M@1
end,
case {Is_negative, Hours, Mins} of
{_, 0, 0} ->
<<"-00:00"/utf8>>;
{_, 0, M@2} ->
<<"-00:"/utf8,
(begin
_pipe = gleam@int:to_string(M@2),
gleam@string:pad_left(_pipe, 2, <<"0"/utf8>>)
end)/binary>>;
{true, H@2, M@3} ->
<<<<<<"-"/utf8,
(begin
_pipe@1 = gleam@int:to_string(H@2),
gleam@string:pad_left(_pipe@1, 2, <<"0"/utf8>>)
end)/binary>>/binary,
":"/utf8>>/binary,
(begin
_pipe@2 = gleam@int:to_string(M@3),
gleam@string:pad_left(_pipe@2, 2, <<"0"/utf8>>)
end)/binary>>;
{false, H@3, M@4} ->
<<<<<<"+"/utf8,
(begin
_pipe@3 = gleam@int:to_string(H@3),
gleam@string:pad_left(_pipe@3, 2, <<"0"/utf8>>)
end)/binary>>/binary,
":"/utf8>>/binary,
(begin
_pipe@4 = gleam@int:to_string(M@4),
gleam@string:pad_left(_pipe@4, 2, <<"0"/utf8>>)
end)/binary>>
end.
-spec from_string(binary()) -> {ok, tempo:offset()} | {error, tempo:error()}.
from_string(Offset) ->
_pipe = case Offset of
<<"Z"/utf8>> ->
{ok, {offset, 0}};
<<"z"/utf8>> ->
{ok, {offset, 0}};
_ ->
gleam@result:'try'(case gleam@string:split(Offset, <<":"/utf8>>) of
[Hour, Minute] ->
case {gleam@string:length(Hour),
gleam@string:length(Minute)} of
{3, 2} ->
{ok,
{gleam@string:slice(Hour, 0, 1),
gleam@string:slice(Hour, 1, 2),
Minute}};
{_, _} ->
{error, offset_invalid_format}
end;
_ ->
case gleam@string:length(Offset) of
5 ->
{ok,
{gleam@string:slice(Offset, 0, 1),
gleam@string:slice(Offset, 1, 2),
gleam@string:slice(Offset, 3, 2)}};
3 ->
{ok,
{gleam@string:slice(Offset, 0, 1),
gleam@string:slice(Offset, 1, 2),
<<"0"/utf8>>}};
_ ->
{error, offset_invalid_format}
end
end, fun(_use0) ->
{Sign, Hour@1, Minute@1} = _use0,
case {Sign,
gleam@int:parse(Hour@1),
gleam@int:parse(Minute@1)} of
{_, {ok, 0}, {ok, 0}} ->
{ok, {offset, 0}};
{<<"-"/utf8>>, {ok, Hour@2}, {ok, Minute@2}} when (Hour@2 =< 24) andalso (Minute@2 =< 60) ->
{ok, {offset, - ((Hour@2 * 60) + Minute@2)}};
{<<"+"/utf8>>, {ok, Hour@3}, {ok, Minute@3}} when (Hour@3 =< 24) andalso (Minute@3 =< 60) ->
{ok, {offset, (Hour@3 * 60) + Minute@3}};
{_, _, _} ->
{error, offset_invalid_format}
end
end)
end,
gleam@result:'try'(_pipe, fun validate/1).
-spec literal(binary()) -> tempo:offset().
literal(Offset) ->
case from_string(Offset) of
{ok, Offset@1} ->
Offset@1;
{error, offset_invalid_format} ->
erlang:error(#{gleam_error => panic,
message => <<"Invalid offset literal format"/utf8>>,
module => <<"tempo/offset"/utf8>>,
function => <<"literal"/utf8>>,
line => 22});
{error, offset_out_of_bounds} ->
erlang:error(#{gleam_error => panic,
message => <<"Invalid offset literal value"/utf8>>,
module => <<"tempo/offset"/utf8>>,
function => <<"literal"/utf8>>,
line => 23});
{error, _} ->
erlang:error(#{gleam_error => panic,
message => <<"Invalid offset literal"/utf8>>,
module => <<"tempo/offset"/utf8>>,
function => <<"literal"/utf8>>,
line => 24})
end.
-spec to_duration(tempo:offset()) -> tempo:duration().
to_duration(Offset) ->
_pipe = - erlang:element(2, Offset) * 60000000000,
{duration, _pipe}.
-spec local_minutes() -> integer().
local_minutes() ->
tempo_ffi:local_offset().
-spec local() -> tempo:offset().
local() ->
_pipe = tempo_ffi:local_offset(),
{offset, _pipe}.
-spec local_nano() -> integer().
local_nano() ->
tempo_ffi:local_offset() * 60000000000.