Current section
Files
Jump to
Current section
Files
src/tempo@datetime.erl
-module(tempo@datetime).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([new/3, now_utc/0, from_string/1, literal/1, to_string/1, from_unix_utc/1, from_unix_milli_utc/1, from_unix_micro_utc/1, get_date/1, get_time/1, get_offset/1, drop_offset/1, drop_time/1, to_second_precision/1, to_milli_precision/1, to_micro_precision/1, to_nano_precision/1, add/2, apply_offset/1, to_unix_utc/1, to_unix_milli_utc/1, to_unix_micro_utc/1, to_utc/1, compare/2, is_earlier/2, is_earlier_or_equal/2, is_equal/2, is_later/2, is_later_or_equal/2, difference/2, to_period/2, subtract/2, to_offset/2, to_local/1, now_local/0, now_text/0, to_local_time/1, to_local_date/1, time_left_in_day/1]).
-spec new(tempo:date(), tempo:time(), tempo:offset()) -> tempo:date_time().
new(Date, Time, Offset) ->
{date_time, tempo@naive_datetime:new(Date, Time), Offset}.
-spec now_utc() -> tempo:date_time().
now_utc() ->
Now_ts_nano = tempo_ffi:now(),
new(
tempo@date:from_unix_utc(Now_ts_nano div 1000000000),
tempo@time:from_unix_nano_utc(Now_ts_nano),
{offset, 0}
).
-spec split_time_and_offset(binary()) -> {ok, {binary(), binary()}} |
{error, tempo:error()}.
split_time_and_offset(Time_with_offset) ->
case gleam@string:slice(Time_with_offset, -1, 1) of
<<"Z"/utf8>> ->
_pipe = {gleam@string:drop_right(Time_with_offset, 1), <<"Z"/utf8>>},
{ok, _pipe};
<<"z"/utf8>> ->
_pipe@1 = {gleam@string:drop_right(Time_with_offset, 1),
<<"Z"/utf8>>},
{ok, _pipe@1};
_ ->
case gleam@string:split(Time_with_offset, <<"-"/utf8>>) of
[Time, Offset] ->
_pipe@2 = {Time, <<"-"/utf8, Offset/binary>>},
{ok, _pipe@2};
_ ->
case gleam@string:split(Time_with_offset, <<"+"/utf8>>) of
[Time@1, Offset@1] ->
_pipe@3 = {Time@1, <<"+"/utf8, Offset@1/binary>>},
{ok, _pipe@3};
_ ->
{error, date_time_invalid_format}
end
end
end.
-spec from_string(binary()) -> {ok, tempo:date_time()} | {error, tempo:error()}.
from_string(Datetime) ->
case gleam@string:split(Datetime, <<"T"/utf8>>) of
[Date, Time] ->
gleam@result:'try'(
tempo@date:from_string(Date),
fun(Date@1) ->
gleam@result:'try'(
split_time_and_offset(Time),
fun(_use0) ->
{Time@1, Offset} = _use0,
gleam@result:'try'(
tempo@time:from_string(Time@1),
fun(Time@2) ->
gleam@result:map(
tempo@offset:from_string(Offset),
fun(Offset@1) ->
new(Date@1, Time@2, Offset@1)
end
)
end
)
end
)
end
);
[Date@2] ->
_pipe = tempo@date:from_string(Date@2),
gleam@result:map(
_pipe,
fun(_capture) ->
new(_capture, {time, 0, 0, 0, 0}, {offset, 0})
end
);
_ ->
{error, date_time_invalid_format}
end.
-spec literal(binary()) -> tempo:date_time().
literal(Datetime) ->
case from_string(Datetime) of
{ok, Datetime@1} ->
Datetime@1;
{error, date_time_invalid_format} ->
erlang:error(#{gleam_error => panic,
message => <<"Invalid datetime literal format"/utf8>>,
module => <<"tempo/datetime"/utf8>>,
function => <<"literal"/utf8>>,
line => 49});
{error, date_time_out_of_bounds} ->
erlang:error(#{gleam_error => panic,
message => <<"Invalid datetime literal value"/utf8>>,
module => <<"tempo/datetime"/utf8>>,
function => <<"literal"/utf8>>,
line => 51});
{error, _} ->
erlang:error(#{gleam_error => panic,
message => <<"Invalid datetime literal"/utf8>>,
module => <<"tempo/datetime"/utf8>>,
function => <<"literal"/utf8>>,
line => 52})
end.
-spec to_string(tempo:date_time()) -> binary().
to_string(Datetime) ->
<<(begin
_pipe = erlang:element(2, Datetime),
tempo@naive_datetime:to_string(_pipe)
end)/binary,
(case erlang:element(2, erlang:element(3, Datetime)) of
0 ->
<<"Z"/utf8>>;
_ ->
_pipe@1 = erlang:element(3, Datetime),
tempo@offset:to_string(_pipe@1)
end)/binary>>.
-spec from_unix_utc(integer()) -> tempo:date_time().
from_unix_utc(Unix_ts) ->
new(
tempo@date:from_unix_utc(Unix_ts),
tempo@time:from_unix_utc(Unix_ts),
{offset, 0}
).
-spec from_unix_milli_utc(integer()) -> tempo:date_time().
from_unix_milli_utc(Unix_ts) ->
new(
tempo@date:from_unix_milli_utc(Unix_ts),
tempo@time:from_unix_milli_utc(Unix_ts),
{offset, 0}
).
-spec from_unix_micro_utc(integer()) -> tempo:date_time().
from_unix_micro_utc(Unix_ts) ->
new(
tempo@date:from_unix_micro_utc(Unix_ts),
tempo@time:from_unix_micro_utc(Unix_ts),
{offset, 0}
).
-spec get_date(tempo:date_time()) -> tempo:date().
get_date(Datetime) ->
erlang:element(2, erlang:element(2, Datetime)).
-spec get_time(tempo:date_time()) -> tempo:time().
get_time(Datetime) ->
erlang:element(3, erlang:element(2, Datetime)).
-spec get_offset(tempo:date_time()) -> tempo:offset().
get_offset(Datetime) ->
erlang:element(3, Datetime).
-spec drop_offset(tempo:date_time()) -> tempo:naive_date_time().
drop_offset(Datetime) ->
erlang:element(2, Datetime).
-spec drop_time(tempo:date_time()) -> tempo:date_time().
drop_time(Datetime) ->
{date_time,
tempo@naive_datetime:drop_time(erlang:element(2, Datetime)),
erlang:element(3, Datetime)}.
-spec to_second_precision(tempo:date_time()) -> tempo:date_time().
to_second_precision(Datetime) ->
new(
erlang:element(2, erlang:element(2, Datetime)),
begin
_pipe = erlang:element(3, erlang:element(2, Datetime)),
tempo@time:to_second_precision(_pipe)
end,
erlang:element(3, Datetime)
).
-spec to_milli_precision(tempo:date_time()) -> tempo:date_time().
to_milli_precision(Datetime) ->
new(
erlang:element(2, erlang:element(2, Datetime)),
begin
_pipe = erlang:element(3, erlang:element(2, Datetime)),
tempo@time:to_milli_precision(_pipe)
end,
erlang:element(3, Datetime)
).
-spec to_micro_precision(tempo:date_time()) -> tempo:date_time().
to_micro_precision(Datetime) ->
new(
erlang:element(2, erlang:element(2, Datetime)),
begin
_pipe = erlang:element(3, erlang:element(2, Datetime)),
tempo@time:to_micro_precision(_pipe)
end,
erlang:element(3, Datetime)
).
-spec to_nano_precision(tempo:date_time()) -> tempo:date_time().
to_nano_precision(Datetime) ->
new(
erlang:element(2, erlang:element(2, Datetime)),
begin
_pipe = erlang:element(3, erlang:element(2, Datetime)),
tempo@time:to_nano_precision(_pipe)
end,
erlang:element(3, Datetime)
).
-spec add(tempo:date_time(), tempo:duration()) -> tempo:date_time().
add(Datetime, Duration_to_add) ->
_pipe = Datetime,
_pipe@1 = drop_offset(_pipe),
_pipe@2 = tempo@naive_datetime:add(_pipe@1, Duration_to_add),
tempo@naive_datetime:set_offset(_pipe@2, erlang:element(3, Datetime)).
-spec apply_offset(tempo:date_time()) -> tempo:naive_date_time().
apply_offset(Datetime) ->
_pipe = Datetime,
_pipe@1 = add(_pipe, tempo@offset:to_duration(erlang:element(3, Datetime))),
drop_offset(_pipe@1).
-spec to_unix_utc(tempo:date_time()) -> integer().
to_unix_utc(Datetime) ->
Utc_dt = begin
_pipe = Datetime,
apply_offset(_pipe)
end,
tempo@date:to_unix_utc(erlang:element(2, Utc_dt)) + (tempo@time:to_nanoseconds(
erlang:element(3, Utc_dt)
)
div 1000000000).
-spec to_unix_milli_utc(tempo:date_time()) -> integer().
to_unix_milli_utc(Datetime) ->
Utc_dt = begin
_pipe = Datetime,
apply_offset(_pipe)
end,
tempo@date:to_unix_milli_utc(erlang:element(2, Utc_dt)) + (tempo@time:to_nanoseconds(
erlang:element(3, Utc_dt)
)
div 1000000).
-spec to_unix_micro_utc(tempo:date_time()) -> integer().
to_unix_micro_utc(Datetime) ->
Utc_dt = begin
_pipe = Datetime,
apply_offset(_pipe)
end,
tempo@date:to_unix_micro_utc(erlang:element(2, Utc_dt)) + (tempo@time:to_nanoseconds(
erlang:element(3, Utc_dt)
)
div 1000).
-spec to_utc(tempo:date_time()) -> tempo:date_time().
to_utc(Datetime) ->
_pipe = Datetime,
_pipe@1 = add(_pipe, tempo@offset:to_duration(erlang:element(3, Datetime))),
_pipe@2 = drop_offset(_pipe@1),
tempo@naive_datetime:set_offset(_pipe@2, {offset, 0}).
-spec compare(tempo:date_time(), tempo:date_time()) -> gleam@order:order().
compare(A, B) ->
_pipe = apply_offset(A),
tempo@naive_datetime:compare(_pipe, apply_offset(B)).
-spec is_earlier(tempo:date_time(), tempo:date_time()) -> boolean().
is_earlier(A, B) ->
compare(A, B) =:= lt.
-spec is_earlier_or_equal(tempo:date_time(), tempo:date_time()) -> boolean().
is_earlier_or_equal(A, B) ->
(compare(A, B) =:= lt) orelse (compare(A, B) =:= eq).
-spec is_equal(tempo:date_time(), tempo:date_time()) -> boolean().
is_equal(A, B) ->
compare(A, B) =:= eq.
-spec is_later(tempo:date_time(), tempo:date_time()) -> boolean().
is_later(A, B) ->
compare(A, B) =:= gt.
-spec is_later_or_equal(tempo:date_time(), tempo:date_time()) -> boolean().
is_later_or_equal(A, B) ->
(compare(A, B) =:= gt) orelse (compare(A, B) =:= eq).
-spec difference(tempo:date_time(), tempo:date_time()) -> tempo:period().
difference(A, B) ->
_pipe = apply_offset(A),
tempo@naive_datetime:difference(_pipe, apply_offset(B)).
-spec to_period(tempo:date_time(), tempo:date_time()) -> tempo:period().
to_period(Start, End) ->
_pipe = apply_offset(Start),
tempo@naive_datetime:to_period(_pipe, apply_offset(End)).
-spec subtract(tempo:date_time(), tempo:duration()) -> tempo:date_time().
subtract(Datetime, Duration_to_subtract) ->
_pipe = Datetime,
_pipe@1 = drop_offset(_pipe),
_pipe@2 = tempo@naive_datetime:subtract(_pipe@1, Duration_to_subtract),
tempo@naive_datetime:set_offset(_pipe@2, erlang:element(3, Datetime)).
-spec to_offset(tempo:date_time(), tempo:offset()) -> tempo:date_time().
to_offset(Datetime, Offset) ->
_pipe = Datetime,
_pipe@1 = to_utc(_pipe),
_pipe@2 = subtract(_pipe@1, tempo@offset:to_duration(Offset)),
_pipe@3 = drop_offset(_pipe@2),
tempo@naive_datetime:set_offset(_pipe@3, Offset).
-spec to_local(tempo:date_time()) -> tempo:uncertain_conversion(tempo:date_time()).
to_local(Datetime) ->
gleam@bool:lazy_guard(
erlang:element(3, Datetime) =:= tempo@offset:local(),
fun() -> {precise, Datetime} end,
fun() ->
Local_dt = begin
_pipe = Datetime,
to_offset(_pipe, tempo@offset:local())
end,
case erlang:element(2, erlang:element(2, Local_dt)) =:= tempo@date:current_local(
) of
true ->
{precise, Local_dt};
false ->
{imprecise, Local_dt}
end
end
).
-spec now_local() -> tempo:date_time().
now_local() ->
case begin
_pipe = now_utc(),
to_local(_pipe)
end of
{precise, Datetime} ->
Datetime;
{imprecise, Datetime@1} ->
Datetime@1
end.
-spec now_text() -> binary().
now_text() ->
_pipe = now_local(),
_pipe@1 = drop_offset(_pipe),
_pipe@2 = tempo@naive_datetime:to_milli_precision(_pipe@1),
_pipe@3 = tempo@naive_datetime:to_string(_pipe@2),
gleam@string:replace(_pipe@3, <<"T"/utf8>>, <<" "/utf8>>).
-spec to_local_time(tempo:date_time()) -> tempo:uncertain_conversion(tempo:time()).
to_local_time(Datetime) ->
case to_local(Datetime) of
{precise, Datetime@1} ->
_pipe = erlang:element(3, erlang:element(2, Datetime@1)),
{precise, _pipe};
{imprecise, Datetime@2} ->
_pipe@1 = erlang:element(3, erlang:element(2, Datetime@2)),
{imprecise, _pipe@1}
end.
-spec to_local_date(tempo:date_time()) -> tempo:uncertain_conversion(tempo:date()).
to_local_date(Datetime) ->
case to_local(Datetime) of
{precise, Datetime@1} ->
_pipe = erlang:element(2, erlang:element(2, Datetime@1)),
{precise, _pipe};
{imprecise, Datetime@2} ->
_pipe@1 = erlang:element(2, erlang:element(2, Datetime@2)),
{imprecise, _pipe@1}
end.
-spec time_left_in_day(tempo:date_time()) -> tempo:time().
time_left_in_day(Datetime) ->
_pipe = erlang:element(3, erlang:element(2, Datetime)),
tempo@time:left_in_day(_pipe).