-module(calendar@datetime). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/calendar/datetime.gleam"). -export([new/12, new_utc/8, new_utc_simple/6, from_naive_datetime/5, to_naive_datetime/1, to_date/1, to_time/1, to_local_timestamp/1, to_utc_timestamp/1, compare/2, from_utc_timestamp/2, add_seconds/2, to_string/1, to_iso8601/1, new_from_date_and_time/2, new_from_date_and_time_with_tz/6, from_naive_utc/1, from_naive_with_timezone/5, shift_zone/5, to_erl/1, from_erl/5, before/2, 'after'/2, shift/2, truncate/2, convert/2, from_gregorian_seconds/3, to_gregorian_seconds/1, from_unix/3, utc_now_with_precision/2, utc_now/0, now/4, add/3, to_unix/2, diff/3, to_iso8601_basic/1, to_iso8601_with_format/2, from_iso8601/1, from_iso8601_with_calendar/2]). -export_type([date_time/0, date_time_error/0, date_time_format/0, time_unit/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type date_time() :: {date_time, integer(), integer(), integer(), integer(), integer(), integer(), binary(), binary(), integer(), integer(), {integer(), integer()}, binary()}. -type date_time_error() :: invalid_date_time | invalid_date | invalid_time | invalid_format | time_zone_not_found | utc_only_time_zone_database | ambiguous_time | gap_in_time. -type date_time_format() :: extended | basic. -type time_unit() :: native | second | millisecond | microsecond | nanosecond. -file("src/calendar/datetime.gleam", 66). ?DOC(" Creates a new DateTime struct.\n"). -spec new( integer(), integer(), integer(), integer(), integer(), integer(), binary(), binary(), integer(), integer(), {integer(), integer()}, binary() ) -> {ok, date_time()} | {error, date_time_error()}. new( Year, Month, Day, Hour, Minute, Second, Time_zone, Zone_abbr, Utc_offset, Std_offset, Microsecond, Calendar ) -> case calendar@date:new(Year, Month, Day, Calendar) of {error, _} -> {error, invalid_date}; {ok, _} -> case calendar@time:new(Hour, Minute, Second, Microsecond, Calendar) of {error, _} -> {error, invalid_time}; {ok, _} -> {ok, {date_time, Year, Month, Day, Hour, Minute, Second, Time_zone, Zone_abbr, Utc_offset, Std_offset, Microsecond, Calendar}} end end. -file("src/calendar/datetime.gleam", 108). ?DOC(" Creates a UTC DateTime from date and time components.\n"). -spec new_utc( integer(), integer(), integer(), integer(), integer(), integer(), {integer(), integer()}, binary() ) -> {ok, date_time()} | {error, date_time_error()}. new_utc(Year, Month, Day, Hour, Minute, Second, Microsecond, Calendar) -> new( Year, Month, Day, Hour, Minute, Second, <<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, 0, 0, Microsecond, Calendar ). -file("src/calendar/datetime.gleam", 135). ?DOC(" Creates a simple UTC DateTime with default values.\n"). -spec new_utc_simple( integer(), integer(), integer(), integer(), integer(), integer() ) -> {ok, date_time()} | {error, date_time_error()}. new_utc_simple(Year, Month, Day, Hour, Minute, Second) -> new_utc( Year, Month, Day, Hour, Minute, Second, {0, 0}, <<"Calendar.ISO"/utf8>> ). -file("src/calendar/datetime.gleam", 147). ?DOC(" Creates a DateTime from a NaiveDateTime and timezone information.\n"). -spec from_naive_datetime( calendar@naive_datetime:naive_date_time(), binary(), binary(), integer(), integer() ) -> date_time(). from_naive_datetime(Ndt, Time_zone, Zone_abbr, Utc_offset, Std_offset) -> {date_time, erlang:element(2, Ndt), erlang:element(3, Ndt), erlang:element(4, Ndt), erlang:element(5, Ndt), erlang:element(6, Ndt), erlang:element(7, Ndt), Time_zone, Zone_abbr, Utc_offset, Std_offset, erlang:element(8, Ndt), erlang:element(9, Ndt)}. -file("src/calendar/datetime.gleam", 234). ?DOC(" Extracts the NaiveDateTime part from a DateTime.\n"). -spec to_naive_datetime(date_time()) -> calendar@naive_datetime:naive_date_time(). to_naive_datetime(Dt) -> case calendar@naive_datetime:new( erlang:element(2, Dt), erlang:element(3, Dt), erlang:element(4, Dt), erlang:element(5, Dt), erlang:element(6, Dt), erlang:element(7, Dt), erlang:element(12, Dt), erlang:element(13, Dt) ) of {ok, Ndt} -> Ndt; {error, _} -> erlang:error(#{gleam_error => panic, message => <<"Invalid datetime in valid DateTime struct"/utf8>>, file => <>, module => <<"calendar/datetime"/utf8>>, function => <<"to_naive_datetime"/utf8>>, line => 248}) end. -file("src/calendar/datetime.gleam", 253). ?DOC(" Extracts the Date part from a DateTime.\n"). -spec to_date(date_time()) -> calendar@date:date(). to_date(Dt) -> case calendar@date:new( erlang:element(2, Dt), erlang:element(3, Dt), erlang:element(4, Dt), erlang:element(13, Dt) ) of {ok, D} -> D; {error, _} -> erlang:error(#{gleam_error => panic, message => <<"Invalid date in valid DateTime struct"/utf8>>, file => <>, module => <<"calendar/datetime"/utf8>>, function => <<"to_date"/utf8>>, line => 256}) end. -file("src/calendar/datetime.gleam", 261). ?DOC(" Extracts the Time part from a DateTime.\n"). -spec to_time(date_time()) -> calendar@time:time(). to_time(Dt) -> case calendar@time:new( erlang:element(5, Dt), erlang:element(6, Dt), erlang:element(7, Dt), erlang:element(12, Dt), erlang:element(13, Dt) ) of {ok, T} -> T; {error, _} -> erlang:error(#{gleam_error => panic, message => <<"Invalid time in valid DateTime struct"/utf8>>, file => <>, module => <<"calendar/datetime"/utf8>>, function => <<"to_time"/utf8>>, line => 264}) end. -file("src/calendar/datetime.gleam", 281). ?DOC(" Convert DateTime to local timestamp.\n"). -spec to_local_timestamp(date_time()) -> integer(). to_local_timestamp(Dt) -> Date_part = to_date(Dt), Date_timestamp = calendar@date:to_timestamp(Date_part), Time_seconds = ((erlang:element(5, Dt) * 3600) + (erlang:element(6, Dt) * 60)) + erlang:element(7, Dt), Date_timestamp + Time_seconds. -file("src/calendar/datetime.gleam", 275). ?DOC(" Convert DateTime to UTC timestamp.\n"). -spec to_utc_timestamp(date_time()) -> integer(). to_utc_timestamp(Dt) -> Local_timestamp = to_local_timestamp(Dt), Local_timestamp - (erlang:element(10, Dt) + erlang:element(11, Dt)). -file("src/calendar/datetime.gleam", 268). -spec compare(date_time(), date_time()) -> gleam@order:order(). compare(Dt1, Dt2) -> Utc1 = to_utc_timestamp(Dt1), Utc2 = to_utc_timestamp(Dt2), gleam@int:compare(Utc1, Utc2). -file("src/calendar/datetime.gleam", 289). ?DOC(" Create DateTime from UTC timestamp.\n"). -spec from_utc_timestamp(integer(), binary()) -> {ok, date_time()} | {error, date_time_error()}. from_utc_timestamp(Timestamp, Time_zone) -> case Time_zone =:= <<"Etc/UTC"/utf8>> of true -> case calendar@naive_datetime:from_timestamp(Timestamp) of {error, _} -> {error, invalid_date_time}; {ok, Ndt} -> {ok, from_naive_datetime( Ndt, <<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, 0, 0 )} end; false -> {error, utc_only_time_zone_database} end. -file("src/calendar/datetime.gleam", 307). ?DOC(" Add seconds to a DateTime (adjusts UTC time).\n"). -spec add_seconds(date_time(), integer()) -> {ok, date_time()} | {error, date_time_error()}. add_seconds(Dt, Seconds) -> Utc_timestamp = to_utc_timestamp(Dt), from_utc_timestamp(Utc_timestamp + Seconds, erlang:element(8, Dt)). -file("src/calendar/datetime.gleam", 316). ?DOC(" Helper functions\n"). -spec pad_left(binary(), integer(), binary()) -> binary(). pad_left(Str, Width, Pad_char) -> Current_length = string:length(Str), case Current_length >= Width of true -> Str; false -> <<(gleam@string:repeat(Pad_char, Width - Current_length))/binary, Str/binary>> end. -file("src/calendar/datetime.gleam", 324). -spec pad_microseconds(integer(), integer()) -> binary(). pad_microseconds(Microseconds, Precision) -> Ms_str = erlang:integer_to_binary(Microseconds), Padded = case string:length(Ms_str) < Precision of true -> <<(gleam@string:repeat( <<"0"/utf8>>, Precision - string:length(Ms_str) ))/binary, Ms_str/binary>>; false -> Ms_str end, gleam@string:slice(Padded, 0, Precision). -file("src/calendar/datetime.gleam", 333). -spec format_offset(integer()) -> binary(). format_offset(Total_offset) -> case Total_offset =:= 0 of true -> <<"+00:00"/utf8>>; false -> Sign = case Total_offset >= 0 of true -> <<"+"/utf8>>; false -> <<"-"/utf8>> end, Abs_offset = case Total_offset < 0 of true -> - Total_offset; false -> Total_offset end, Hours = Abs_offset div 3600, Minutes = (Abs_offset rem 3600) div 60, <<<<<> ))/binary>>/binary, ":"/utf8>>/binary, (pad_left(erlang:integer_to_binary(Minutes), 2, <<"0"/utf8>>))/binary>> end. -file("src/calendar/datetime.gleam", 171). ?DOC(" Converts a DateTime to a string with timezone information.\n"). -spec to_string(date_time()) -> binary(). to_string(Dt) -> Date_part = <<<<<<<<(pad_left( erlang:integer_to_binary(erlang:element(2, Dt)), 4, <<"0"/utf8>> ))/binary, "-"/utf8>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(3, Dt)), 2, <<"0"/utf8>> ))/binary>>/binary, "-"/utf8>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(4, Dt)), 2, <<"0"/utf8>> ))/binary>>, Time_part = <<<<<<<<(pad_left( erlang:integer_to_binary(erlang:element(5, Dt)), 2, <<"0"/utf8>> ))/binary, ":"/utf8>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(6, Dt)), 2, <<"0"/utf8>> ))/binary>>/binary, ":"/utf8>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(7, Dt)), 2, <<"0"/utf8>> ))/binary>>, {Ms, Precision} = erlang:element(12, Dt), Microsecond_part = case (Ms =:= 0) orelse (Precision =:= 0) of true -> <<""/utf8>>; false -> <<"."/utf8, (pad_microseconds(Ms, Precision))/binary>> end, Offset_part = format_offset(erlang:element(10, Dt) + erlang:element(11, Dt)), <<<<<<<<<<<>/binary, Time_part/binary>>/binary, Microsecond_part/binary>>/binary, Offset_part/binary>>/binary, " "/utf8>>/binary, (erlang:element(9, Dt))/binary>>. -file("src/calendar/datetime.gleam", 204). ?DOC(" Converts a DateTime to ISO8601 format with timezone.\n"). -spec to_iso8601(date_time()) -> binary(). to_iso8601(Dt) -> Date_part = <<<<<<<<(pad_left( erlang:integer_to_binary(erlang:element(2, Dt)), 4, <<"0"/utf8>> ))/binary, "-"/utf8>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(3, Dt)), 2, <<"0"/utf8>> ))/binary>>/binary, "-"/utf8>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(4, Dt)), 2, <<"0"/utf8>> ))/binary>>, Time_part = <<<<<<<<(pad_left( erlang:integer_to_binary(erlang:element(5, Dt)), 2, <<"0"/utf8>> ))/binary, ":"/utf8>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(6, Dt)), 2, <<"0"/utf8>> ))/binary>>/binary, ":"/utf8>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(7, Dt)), 2, <<"0"/utf8>> ))/binary>>, {Ms, Precision} = erlang:element(12, Dt), Microsecond_part = case (Ms =:= 0) orelse (Precision =:= 0) of true -> <<""/utf8>>; false -> <<"."/utf8, (pad_microseconds(Ms, Precision))/binary>> end, Offset_part = case erlang:element(8, Dt) =:= <<"Etc/UTC"/utf8>> of true -> <<"Z"/utf8>>; false -> format_offset(erlang:element(10, Dt) + erlang:element(11, Dt)) end, <<<<<<<>/binary, Time_part/binary>>/binary, Microsecond_part/binary>>/binary, Offset_part/binary>>. -file("src/calendar/datetime.gleam", 377). ?DOC(" Creates a DateTime from Date and Time structs with UTC timezone.\n"). -spec new_from_date_and_time(calendar@date:date(), calendar@time:time()) -> {ok, date_time()} | {error, date_time_error()}. new_from_date_and_time(Date_val, Time_val) -> case erlang:element(5, Date_val) =:= erlang:element(6, Time_val) of false -> {error, invalid_date_time}; true -> new_utc( erlang:element(2, Date_val), erlang:element(3, Date_val), erlang:element(4, Date_val), erlang:element(2, Time_val), erlang:element(3, Time_val), erlang:element(4, Time_val), erlang:element(5, Time_val), erlang:element(5, Date_val) ) end. -file("src/calendar/datetime.gleam", 398). ?DOC(" Creates a DateTime from Date and Time structs with specified timezone.\n"). -spec new_from_date_and_time_with_tz( calendar@date:date(), calendar@time:time(), binary(), binary(), integer(), integer() ) -> {ok, date_time()} | {error, date_time_error()}. new_from_date_and_time_with_tz( Date_val, Time_val, Time_zone, Zone_abbr, Utc_offset, Std_offset ) -> case erlang:element(5, Date_val) =:= erlang:element(6, Time_val) of false -> {error, invalid_date_time}; true -> new( erlang:element(2, Date_val), erlang:element(3, Date_val), erlang:element(4, Date_val), erlang:element(2, Time_val), erlang:element(3, Time_val), erlang:element(4, Time_val), Time_zone, Zone_abbr, Utc_offset, Std_offset, erlang:element(5, Time_val), erlang:element(5, Date_val) ) end. -file("src/calendar/datetime.gleam", 448). ?DOC(" Creates a DateTime from NaiveDateTime with UTC timezone.\n"). -spec from_naive_utc(calendar@naive_datetime:naive_date_time()) -> date_time(). from_naive_utc(Ndt) -> from_naive_datetime(Ndt, <<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, 0, 0). -file("src/calendar/datetime.gleam", 453). ?DOC(" Creates a DateTime from NaiveDateTime with specified timezone.\n"). -spec from_naive_with_timezone( calendar@naive_datetime:naive_date_time(), binary(), binary(), integer(), integer() ) -> {ok, date_time()} | {error, date_time_error()}. from_naive_with_timezone(Ndt, Time_zone, Zone_abbr, Utc_offset, Std_offset) -> {ok, from_naive_datetime(Ndt, Time_zone, Zone_abbr, Utc_offset, Std_offset)}. -file("src/calendar/datetime.gleam", 464). ?DOC(" Shifts a DateTime to a different timezone.\n"). -spec shift_zone(date_time(), binary(), binary(), integer(), integer()) -> {ok, date_time()} | {error, date_time_error()}. shift_zone(Dt, Time_zone, Zone_abbr, Utc_offset, Std_offset) -> case Time_zone =:= erlang:element(8, Dt) of true -> {ok, Dt}; false -> Utc_timestamp = to_utc_timestamp(Dt), Adjusted_timestamp = (Utc_timestamp + Utc_offset) + Std_offset, case calendar@naive_datetime:from_timestamp(Adjusted_timestamp) of {error, _} -> {error, invalid_date_time}; {ok, Ndt} -> {ok, from_naive_datetime( Ndt, Time_zone, Zone_abbr, Utc_offset, Std_offset )} end end. -file("src/calendar/datetime.gleam", 553). ?DOC(" Converts DateTime to Erlang datetime tuple.\n"). -spec to_erl(date_time()) -> {{integer(), integer(), integer()}, {integer(), integer(), integer()}}. to_erl(Dt) -> {{erlang:element(2, Dt), erlang:element(3, Dt), erlang:element(4, Dt)}, {erlang:element(5, Dt), erlang:element(6, Dt), erlang:element(7, Dt)}}. -file("src/calendar/datetime.gleam", 558). ?DOC(" Creates DateTime from Erlang datetime tuple.\n"). -spec from_erl( {{integer(), integer(), integer()}, {integer(), integer(), integer()}}, binary(), binary(), integer(), integer() ) -> {ok, date_time()} | {error, date_time_error()}. from_erl(Erl_datetime, Time_zone, Zone_abbr, Utc_offset, Std_offset) -> {{Year, Month, Day}, {Hour, Minute, Second}} = Erl_datetime, new( Year, Month, Day, Hour, Minute, Second, Time_zone, Zone_abbr, Utc_offset, Std_offset, {0, 0}, <<"Calendar.ISO"/utf8>> ). -file("src/calendar/datetime.gleam", 583). ?DOC(" Returns `true` if the first datetime is strictly earlier than the second.\n"). -spec before(date_time(), date_time()) -> boolean(). before(Dt1, Dt2) -> case compare(Dt1, Dt2) of lt -> true; _ -> false end. -file("src/calendar/datetime.gleam", 591). ?DOC(" Returns `true` if the first datetime is strictly later than the second.\n"). -spec 'after'(date_time(), date_time()) -> boolean(). 'after'(Dt1, Dt2) -> case compare(Dt1, Dt2) of gt -> true; _ -> false end. -file("src/calendar/datetime.gleam", 617). ?DOC(" Adds time to a DateTime using Duration.\n"). -spec shift(date_time(), calendar@duration:duration()) -> {ok, date_time()} | {error, date_time_error()}. shift(Dt, Dur) -> Month_shift = (erlang:element(2, Dur) * 12) + erlang:element(3, Dur), Day_shift = (erlang:element(4, Dur) * 7) + erlang:element(5, Dur), {Us, _} = erlang:element(9, Dur), {Y, M, D, H, Min, S, Microsecond} = calendar@iso:shift_naive_datetime( erlang:element(2, Dt), erlang:element(3, Dt), erlang:element(4, Dt), erlang:element(5, Dt), erlang:element(6, Dt), erlang:element(7, Dt), erlang:element(12, Dt), Month_shift, Day_shift, ((erlang:element(6, Dur) * 3600) + (erlang:element(7, Dur) * 60)) + erlang:element( 8, Dur ), Us ), new( Y, M, D, H, Min, S, erlang:element(8, Dt), erlang:element(9, Dt), erlang:element(10, Dt), erlang:element(11, Dt), Microsecond, erlang:element(13, Dt) ). -file("src/calendar/datetime.gleam", 657). ?DOC(" Returns the given datetime with the microsecond field truncated to the given precision.\n"). -spec truncate(date_time(), integer()) -> date_time(). truncate(Dt, Precision) -> {Ms, _} = erlang:element(12, Dt), Truncated_ms = case Precision of 0 -> 0; 1 -> (Ms div 100000) * 100000; 2 -> (Ms div 10000) * 10000; 3 -> (Ms div 1000) * 1000; 4 -> (Ms div 100) * 100; 5 -> (Ms div 10) * 10; _ -> Ms end, {date_time, erlang:element(2, Dt), erlang:element(3, Dt), erlang:element(4, Dt), erlang:element(5, Dt), erlang:element(6, Dt), erlang:element(7, Dt), erlang:element(8, Dt), erlang:element(9, Dt), erlang:element(10, Dt), erlang:element(11, Dt), {Truncated_ms, Precision}, erlang:element(13, Dt)}. -file("src/calendar/datetime.gleam", 686). ?DOC(" Converts the given `datetime` from its calendar to the given `calendar`.\n"). -spec convert(date_time(), binary()) -> {ok, date_time()} | {error, date_time_error()}. convert(Dt, Target_calendar) -> case erlang:element(13, Dt) =:= Target_calendar of true -> {ok, Dt}; false -> {ok, {date_time, erlang:element(2, Dt), erlang:element(3, Dt), erlang:element(4, Dt), erlang:element(5, Dt), erlang:element(6, Dt), erlang:element(7, Dt), erlang:element(8, Dt), erlang:element(9, Dt), erlang:element(10, Dt), erlang:element(11, Dt), erlang:element(12, Dt), Target_calendar}} end. -file("src/calendar/datetime.gleam", 712). ?DOC(" Creates a DateTime from Gregorian seconds (seconds since 0000-01-01 00:00:00 UTC).\n"). -spec from_gregorian_seconds(integer(), {integer(), integer()}, binary()) -> {ok, date_time()} | {error, date_time_error()}. from_gregorian_seconds(Seconds, Microsecond, Calendar) -> {Ms, Precision} = Microsecond, Iso_days = calendar@iso:gregorian_seconds_to_iso_days(Seconds, Ms), {Year, Month, Day, Hour, Minute, Second, {Us, _}} = calendar@iso:naive_datetime_from_iso_days( Iso_days ), new( Year, Month, Day, Hour, Minute, Second, <<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, 0, 0, {Us, Precision}, Calendar ). -file("src/calendar/datetime.gleam", 739). ?DOC( " Converts a DateTime to Gregorian seconds (seconds since 0000-01-01 00:00:00 UTC).\n" " Returns #(gregorian_seconds, microseconds).\n" ). -spec to_gregorian_seconds(date_time()) -> {integer(), integer()}. to_gregorian_seconds(Dt) -> {Ms, _} = erlang:element(12, Dt), Iso_days = calendar@iso:naive_datetime_to_iso_days( erlang:element(2, Dt), erlang:element(3, Dt), erlang:element(4, Dt), erlang:element(5, Dt), erlang:element(6, Dt), erlang:element(7, Dt), erlang:element(12, Dt) ), {Days, {Day_fraction_us, _}} = Iso_days, Total_offset = erlang:element(10, Dt) + erlang:element(11, Dt), Seconds_in_day = Day_fraction_us div 1000000, Total_seconds = ((Days * 86400) + Seconds_in_day) - Total_offset, {Total_seconds, Ms}. -file("src/calendar/datetime.gleam", 761). -spec convert_to_seconds(integer(), time_unit()) -> integer(). convert_to_seconds(Value, Unit) -> case Unit of second -> Value; millisecond -> Value div 1000; microsecond -> Value div 1000000; nanosecond -> Value div 1000000000; native -> Value div 1000000000 end. -file("src/calendar/datetime.gleam", 427). ?DOC(" Converts a Unix timestamp to a DateTime.\n"). -spec from_unix(integer(), time_unit(), binary()) -> {ok, date_time()} | {error, date_time_error()}. from_unix(Timestamp, Unit, _) -> Seconds = convert_to_seconds(Timestamp, Unit), case calendar@naive_datetime:from_timestamp(Seconds) of {error, _} -> {error, invalid_date_time}; {ok, Ndt} -> {ok, from_naive_datetime( Ndt, <<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, 0, 0 )} end. -file("src/calendar/datetime.gleam", 364). ?DOC(" Returns the current datetime in UTC with specified precision and calendar.\n"). -spec utc_now_with_precision(time_unit(), binary()) -> {ok, date_time()} | {error, date_time_error()}. utc_now_with_precision(Time_unit, Calendar) -> Timestamp = os:system_time(), case from_unix(Timestamp, Time_unit, Calendar) of {ok, Dt} -> {ok, Dt}; {error, _} -> new( 1970, 1, 1, 0, 0, 0, <<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, 0, 0, {0, 0}, Calendar ) end. -file("src/calendar/datetime.gleam", 359). ?DOC(" Returns the current datetime in UTC.\n"). -spec utc_now() -> {ok, date_time()} | {error, date_time_error()}. utc_now() -> utc_now_with_precision(native, <<"Calendar.ISO"/utf8>>). -file("src/calendar/datetime.gleam", 492). ?DOC(" Returns the current datetime in a specific timezone.\n"). -spec now(binary(), binary(), integer(), integer()) -> {ok, date_time()} | {error, date_time_error()}. now(Time_zone, Zone_abbr, Utc_offset, Std_offset) -> case utc_now() of {ok, Utc_dt} -> shift_zone(Utc_dt, Time_zone, Zone_abbr, Utc_offset, Std_offset); {error, E} -> {error, E} end. -file("src/calendar/datetime.gleam", 607). ?DOC(" Adds an amount of time to a DateTime in the given unit.\n"). -spec add(date_time(), integer(), time_unit()) -> {ok, date_time()} | {error, date_time_error()}. add(Dt, Amount, Unit) -> Seconds = convert_to_seconds(Amount, Unit), add_seconds(Dt, Seconds). -file("src/calendar/datetime.gleam", 772). -spec convert_from_seconds(integer(), time_unit()) -> integer(). convert_from_seconds(Seconds, Unit) -> case Unit of second -> Seconds; millisecond -> Seconds * 1000; microsecond -> Seconds * 1000000; nanosecond -> Seconds * 1000000000; native -> Seconds * 1000000000 end. -file("src/calendar/datetime.gleam", 442). ?DOC(" Converts a DateTime to Unix timestamp.\n"). -spec to_unix(date_time(), time_unit()) -> integer(). to_unix(Dt, Unit) -> Utc_seconds = to_utc_timestamp(Dt), convert_from_seconds(Utc_seconds, Unit). -file("src/calendar/datetime.gleam", 599). ?DOC(" Calculates the difference between two datetimes in the specified unit.\n"). -spec diff(date_time(), date_time(), time_unit()) -> integer(). diff(Dt1, Dt2, Unit) -> Timestamp1 = to_utc_timestamp(Dt1), Timestamp2 = to_utc_timestamp(Dt2), Diff_seconds = Timestamp1 - Timestamp2, convert_from_seconds(Diff_seconds, Unit). -file("src/calendar/datetime.gleam", 783). -spec format_offset_basic(integer()) -> binary(). format_offset_basic(Total_offset) -> case Total_offset =:= 0 of true -> <<"+0000"/utf8>>; false -> Sign = case Total_offset >= 0 of true -> <<"+"/utf8>>; false -> <<"-"/utf8>> end, Abs_offset = case Total_offset < 0 of true -> - Total_offset; false -> Total_offset end, Hours = Abs_offset div 3600, Minutes = (Abs_offset rem 3600) div 60, <<<>))/binary>>/binary, (pad_left(erlang:integer_to_binary(Minutes), 2, <<"0"/utf8>>))/binary>> end. -file("src/calendar/datetime.gleam", 527). ?DOC(" Converts DateTime to basic ISO 8601 format.\n"). -spec to_iso8601_basic(date_time()) -> binary(). to_iso8601_basic(Dt) -> Date_part = <<<<(pad_left( erlang:integer_to_binary(erlang:element(2, Dt)), 4, <<"0"/utf8>> ))/binary, (pad_left( erlang:integer_to_binary(erlang:element(3, Dt)), 2, <<"0"/utf8>> ))/binary>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(4, Dt)), 2, <<"0"/utf8>> ))/binary>>, Time_part = <<<<(pad_left( erlang:integer_to_binary(erlang:element(5, Dt)), 2, <<"0"/utf8>> ))/binary, (pad_left( erlang:integer_to_binary(erlang:element(6, Dt)), 2, <<"0"/utf8>> ))/binary>>/binary, (pad_left( erlang:integer_to_binary(erlang:element(7, Dt)), 2, <<"0"/utf8>> ))/binary>>, {Ms, Precision} = erlang:element(12, Dt), Microsecond_part = case (Ms =:= 0) orelse (Precision =:= 0) of true -> <<""/utf8>>; false -> <<"."/utf8, (pad_microseconds(Ms, Precision))/binary>> end, Offset_part = case erlang:element(8, Dt) =:= <<"Etc/UTC"/utf8>> of true -> <<"Z"/utf8>>; false -> format_offset_basic(erlang:element(10, Dt) + erlang:element(11, Dt)) end, <<<<<<<>/binary, Time_part/binary>>/binary, Microsecond_part/binary>>/binary, Offset_part/binary>>. -file("src/calendar/datetime.gleam", 519). ?DOC(" Converts DateTime to ISO 8601 with format option.\n"). -spec to_iso8601_with_format(date_time(), date_time_format()) -> binary(). to_iso8601_with_format(Dt, Format) -> case Format of extended -> to_iso8601(Dt); basic -> to_iso8601_basic(Dt) end. -file("src/calendar/datetime.gleam", 976). -spec parse_offset_hhmm(binary()) -> {ok, integer()} | {error, nil}. parse_offset_hhmm(S) -> case gleam_stdlib:contains_string(S, <<":"/utf8>>) of true -> case gleam@string:split(S, <<":"/utf8>>) of [H_str, M_str] -> case {gleam_stdlib:parse_int(H_str), gleam_stdlib:parse_int(M_str)} of {{ok, H}, {ok, M}} -> {ok, (H * 3600) + (M * 60)}; {_, _} -> {error, nil} end; _ -> {error, nil} end; false -> case string:length(S) of 4 -> case {gleam_stdlib:parse_int(gleam@string:slice(S, 0, 2)), gleam_stdlib:parse_int(gleam@string:slice(S, 2, 2))} of {{ok, H@1}, {ok, M@1}} -> {ok, (H@1 * 3600) + (M@1 * 60)}; {_, _} -> {error, nil} end; 2 -> case gleam_stdlib:parse_int(S) of {ok, H@2} -> {ok, H@2 * 3600}; {error, _} -> {error, nil} end; _ -> {error, nil} end end. -file("src/calendar/datetime.gleam", 904). -spec split_time_at_offset(binary(), binary()) -> {ok, {binary(), integer()}} | {error, nil}. split_time_at_offset(S, Sep) -> case gleam@string:split_once(S, Sep) of {ok, {Time_part, Offset_part}} -> case parse_offset_hhmm(Offset_part) of {ok, Seconds} -> Sign = case Sep of <<"+"/utf8>> -> 1; _ -> -1 end, {ok, {Time_part, Sign * Seconds}}; {error, _} -> {error, nil} end; {error, _} -> {error, nil} end. -file("src/calendar/datetime.gleam", 951). -spec try_5_char_negative_offset(binary(), integer()) -> {ok, {binary(), integer()}} | {error, nil}. try_5_char_negative_offset(S, Len) -> case Len >= 5 of false -> {error, nil}; true -> Maybe = gleam@string:slice(S, Len - 5, 5), case gleam@string:first(Maybe) of {ok, <<"-"/utf8>>} -> Offset_part = gleam@string:drop_start(Maybe, 1), case parse_offset_hhmm(Offset_part) of {ok, Seconds} -> Time_part = gleam@string:slice(S, 0, Len - 5), {ok, {Time_part, - Seconds}}; {error, _} -> {error, nil} end; _ -> {error, nil} end end. -file("src/calendar/datetime.gleam", 922). -spec split_time_at_negative_offset(binary()) -> {ok, {binary(), integer()}} | {error, nil}. split_time_at_negative_offset(S) -> Len = string:length(S), case Len >= 6 of false -> {error, nil}; true -> Maybe = gleam@string:slice(S, Len - 6, 6), case gleam@string:first(Maybe) of {ok, <<"-"/utf8>>} -> Offset_part = gleam@string:drop_start(Maybe, 1), case parse_offset_hhmm(Offset_part) of {ok, Seconds} -> Time_part = gleam@string:slice(S, 0, Len - 6), {ok, {Time_part, - Seconds}}; {error, _} -> try_5_char_negative_offset(S, Len) end; _ -> try_5_char_negative_offset(S, Len) end end. -file("src/calendar/datetime.gleam", 857). -spec parse_time_with_tz(binary(), binary()) -> {ok, {calendar@time:time(), {binary(), binary(), integer(), integer()}}} | {error, date_time_error()}. parse_time_with_tz(Time_string, _) -> case gleam_stdlib:string_ends_with(Time_string, <<"Z"/utf8>>) of true -> Time_part = gleam@string:drop_end(Time_string, 1), case calendar@time:from_iso8601(Time_part) of {error, _} -> {error, invalid_format}; {ok, Parsed_time} -> {ok, {Parsed_time, {<<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, 0, 0}}} end; false -> case split_time_at_offset(Time_string, <<"+"/utf8>>) of {ok, {Time_part@1, Offset_seconds}} -> case calendar@time:from_iso8601(Time_part@1) of {error, _} -> {error, invalid_format}; {ok, Parsed_time@1} -> {ok, {Parsed_time@1, {<<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, Offset_seconds, 0}}} end; {error, _} -> case split_time_at_negative_offset(Time_string) of {ok, {Time_part@2, Offset_seconds@1}} -> case calendar@time:from_iso8601(Time_part@2) of {error, _} -> {error, invalid_format}; {ok, Parsed_time@2} -> {ok, {Parsed_time@2, {<<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, Offset_seconds@1, 0}}} end; {error, _} -> case calendar@time:from_iso8601(Time_string) of {error, _} -> {error, invalid_format}; {ok, Parsed_time@3} -> {ok, {Parsed_time@3, {<<"Etc/UTC"/utf8>>, <<"UTC"/utf8>>, 0, 0}}} end end end end. -file("src/calendar/datetime.gleam", 820). -spec try_parse_datetime_with_separator(binary(), binary(), binary()) -> {ok, date_time()} | {error, date_time_error()}. try_parse_datetime_with_separator(String, Separator, Calendar) -> case gleam@string:split(String, Separator) of [Date_part, Time_part] -> case calendar@date:from_iso8601_with_calendar(Date_part, Calendar) of {error, _} -> {error, invalid_format}; {ok, Parsed_date} -> case parse_time_with_tz(Time_part, Calendar) of {error, _} -> {error, invalid_format}; {ok, {Parsed_time, Tz_info}} -> {Time_zone, Zone_abbr, Utc_offset, Std_offset} = Tz_info, new( erlang:element(2, Parsed_date), erlang:element(3, Parsed_date), erlang:element(4, Parsed_date), erlang:element(2, Parsed_time), erlang:element(3, Parsed_time), erlang:element(4, Parsed_time), Time_zone, Zone_abbr, Utc_offset, Std_offset, erlang:element(5, Parsed_time), Calendar ) end end; _ -> {error, invalid_format} end. -file("src/calendar/datetime.gleam", 805). -spec parse_iso8601_datetime(binary(), binary()) -> {ok, date_time()} | {error, date_time_error()}. parse_iso8601_datetime(String, Calendar) -> case try_parse_datetime_with_separator(String, <<"T"/utf8>>, Calendar) of {ok, Datetime} -> {ok, Datetime}; {error, _} -> case try_parse_datetime_with_separator( String, <<" "/utf8>>, Calendar ) of {ok, Datetime@1} -> {ok, Datetime@1}; {error, _} -> {error, invalid_format} end end. -file("src/calendar/datetime.gleam", 506). ?DOC(" Parses an ISO 8601 datetime string.\n"). -spec from_iso8601(binary()) -> {ok, date_time()} | {error, date_time_error()}. from_iso8601(String) -> parse_iso8601_datetime(String, <<"Calendar.ISO"/utf8>>). -file("src/calendar/datetime.gleam", 511). ?DOC(" Parses an ISO 8601 datetime string with specified calendar.\n"). -spec from_iso8601_with_calendar(binary(), binary()) -> {ok, date_time()} | {error, date_time_error()}. from_iso8601_with_calendar(String, Calendar) -> parse_iso8601_datetime(String, Calendar).