Packages

A comprehensive calendar library for Gleam — date, time, datetime, naive datetime, duration, ISO 8601 parsing and formatting, timezone support. Port of Elixir's Calendar modules.

Current section

Files

Jump to
sidereal src calendar@iso.erl
Raw

src/calendar@iso.erl

-module(calendar@iso).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/calendar/iso.gleam").
-export([leap_year/1, days_in_month/2, months_in_year/1, parse_date_with_format/2, parse_date/1, parse_time_with_format/2, parse_time/1, parse_naive_datetime_with_format/2, parse_naive_datetime/1, day_of_year/3, valid_date/3, valid_time/4, time_to_microseconds/4, microseconds_to_time/1, quarter_of_year/3, year_of_era/1, year_of_era_from_date/3, time_unit_to_precision/1, add_day_fraction_to_iso_days/3, parse_utc_datetime_with_format/2, parse_utc_datetime/1, parse_duration/1, date_to_string/4, time_to_string/5, naive_datetime_to_string/8, datetime_to_string/12, date_to_iso_days/3, naive_datetime_to_iso_days/7, date_from_iso_days/1, naive_datetime_from_iso_days/1, day_of_week/4, shift_date/5, day_of_era/3, time_to_day_fraction/4, iso_days_to_beginning_of_day/1, iso_days_to_end_of_day/1, shift_naive_datetime/11, shift_time/6, gregorian_seconds_to_iso_days/2, time_from_day_fraction/1, iso_days_to_unit/2]).
-export_type([parse_error/0, time_unit/0, parse_result/1, format/0, starting_day/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 parse_error() :: invalid_format |
invalid_date |
invalid_time |
invalid_duration.
-type time_unit() :: second | millisecond | microsecond | nanosecond.
-type parse_result(EAS) :: {parse_ok, EAS} | {parse_error, parse_error()}.
-type format() :: basic | extended.
-type starting_day() :: monday | sunday.
-file("src/calendar/iso.gleam", 147).
?DOC(" Check if a year is a leap year.\n").
-spec leap_year(integer()) -> boolean().
leap_year(Year) ->
case (Year rem 4) =:= 0 of
true ->
case (Year rem 100) =:= 0 of
true ->
(Year rem 400) =:= 0;
false ->
true
end;
false ->
false
end.
-file("src/calendar/iso.gleam", 159).
?DOC(" Get the number of days in a month for a given year.\n").
-spec days_in_month(integer(), integer()) -> integer().
days_in_month(Year, Month) ->
case Month of
1 ->
31;
3 ->
31;
5 ->
31;
7 ->
31;
8 ->
31;
10 ->
31;
12 ->
31;
4 ->
30;
6 ->
30;
9 ->
30;
11 ->
30;
2 ->
case leap_year(Year) of
true ->
29;
false ->
28
end;
_ ->
0
end.
-file("src/calendar/iso.gleam", 173).
?DOC(" Get the number of months in a year (always 12 for ISO calendar).\n").
-spec months_in_year(integer()) -> integer().
months_in_year(_) ->
12.
-file("src/calendar/iso.gleam", 242).
?DOC(" Helper functions\n").
-spec parse_date_parts(binary(), binary(), binary()) -> parse_result({integer(),
integer(),
integer()}).
parse_date_parts(Year_str, Month_str, Day_str) ->
case {gleam_stdlib:parse_int(Year_str),
gleam_stdlib:parse_int(Month_str),
gleam_stdlib:parse_int(Day_str)} of
{{ok, Year}, {ok, Month}, {ok, Day}} ->
{parse_ok, {Year, Month, Day}};
{_, _, _} ->
{parse_error, invalid_format}
end.
-file("src/calendar/iso.gleam", 253).
-spec is_valid_date_parts(integer(), integer(), integer()) -> boolean().
is_valid_date_parts(Year, Month, Day) ->
(((Month >= 1) andalso (Month =< 12)) andalso (Day >= 1)) andalso (Day =< days_in_month(
Year,
Month
)).
-file("src/calendar/iso.gleam", 52).
?DOC(
" Parse an ISO 8601 date string with specified format.\n"
" Extended: YYYY-MM-DD, Basic: YYYYMMDD\n"
).
-spec parse_date_with_format(binary(), format()) -> parse_result({integer(),
integer(),
integer()}).
parse_date_with_format(Date_string, Format) ->
case Format of
extended ->
case gleam@string:split(Date_string, <<"-"/utf8>>) of
[Year_str, Month_str, Day_str] ->
case parse_date_parts(Year_str, Month_str, Day_str) of
{parse_ok, {Year, Month, Day}} ->
case is_valid_date_parts(Year, Month, Day) of
true ->
{parse_ok, {Year, Month, Day}};
false ->
{parse_error, invalid_date}
end;
{parse_error, Err} ->
{parse_error, Err}
end;
_ ->
{parse_error, invalid_format}
end;
basic ->
Len = string:length(Date_string),
case Len >= 8 of
false ->
{parse_error, invalid_format};
true ->
Year_str@1 = gleam@string:slice(Date_string, 0, 4),
Month_str@1 = gleam@string:slice(Date_string, 4, 2),
Day_str@1 = gleam@string:slice(Date_string, 6, 2),
case parse_date_parts(Year_str@1, Month_str@1, Day_str@1) of
{parse_ok, {Year@1, Month@1, Day@1}} ->
case is_valid_date_parts(Year@1, Month@1, Day@1) of
true ->
{parse_ok, {Year@1, Month@1, Day@1}};
false ->
{parse_error, invalid_date}
end;
{parse_error, Err@1} ->
{parse_error, Err@1}
end
end
end.
-file("src/calendar/iso.gleam", 46).
?DOC(" Parse an ISO 8601 date string in extended format (YYYY-MM-DD).\n").
-spec parse_date(binary()) -> parse_result({integer(), integer(), integer()}).
parse_date(Date_string) ->
parse_date_with_format(Date_string, extended).
-file("src/calendar/iso.gleam", 257).
-spec is_valid_time_parts(integer(), integer(), integer(), integer(), integer()) -> boolean().
is_valid_time_parts(Hour, Minute, Second, Microsecond, Precision) ->
(((((((((Hour >= 0) andalso (Hour =< 23)) andalso (Minute >= 0)) andalso (Minute
=< 59))
andalso (Second >= 0))
andalso (Second =< 59))
andalso (Microsecond >= 0))
andalso (Microsecond < 1000000))
andalso (Precision >= 0))
andalso (Precision =< 6).
-file("src/calendar/iso.gleam", 276).
-spec pad_microsecond_string(binary()) -> binary().
pad_microsecond_string(Ms_str) ->
Len = string:length(Ms_str),
case Len of
N when N >= 6 ->
gleam@string:slice(Ms_str, 0, 6);
N@1 ->
<<Ms_str/binary,
(gleam@string:repeat(<<"0"/utf8>>, 6 - N@1))/binary>>
end.
-file("src/calendar/iso.gleam", 313).
-spec parse_second_part(integer(), integer(), binary()) -> parse_result({integer(),
integer(),
integer(),
{integer(), integer()}}).
parse_second_part(Hour, Minute, Second_part) ->
case gleam@string:split(Second_part, <<"."/utf8>>) of
[Second_str] ->
case gleam_stdlib:parse_int(Second_str) of
{ok, Second} ->
case is_valid_time_parts(Hour, Minute, Second, 0, 0) of
true ->
{parse_ok, {Hour, Minute, Second, {0, 0}}};
false ->
{parse_error, invalid_time}
end;
{error, _} ->
{parse_error, invalid_format}
end;
[Second_str@1, Microsecond_str] ->
case gleam_stdlib:parse_int(Second_str@1) of
{ok, Second@1} ->
Padded_ms = pad_microsecond_string(Microsecond_str),
case gleam_stdlib:parse_int(Padded_ms) of
{ok, Microsecond} ->
Precision = string:length(Microsecond_str),
case is_valid_time_parts(
Hour,
Minute,
Second@1,
Microsecond,
Precision
) of
true ->
{parse_ok,
{Hour,
Minute,
Second@1,
{Microsecond, Precision}}};
false ->
{parse_error, invalid_time}
end;
{error, _} ->
{parse_error, invalid_format}
end;
{error, _} ->
{parse_error, invalid_format}
end;
_ ->
{parse_error, invalid_format}
end.
-file("src/calendar/iso.gleam", 284).
-spec parse_time_extended(binary()) -> parse_result({integer(),
integer(),
integer(),
{integer(), integer()}}).
parse_time_extended(S) ->
case gleam@string:split(S, <<":"/utf8>>) of
[Hour_str, Minute_str, Second_part] ->
case {gleam_stdlib:parse_int(Hour_str),
gleam_stdlib:parse_int(Minute_str)} of
{{ok, Hour}, {ok, Minute}} ->
parse_second_part(Hour, Minute, Second_part);
{_, _} ->
{parse_error, invalid_format}
end;
_ ->
{parse_error, invalid_format}
end.
-file("src/calendar/iso.gleam", 296).
-spec parse_time_basic(binary()) -> parse_result({integer(),
integer(),
integer(),
{integer(), integer()}}).
parse_time_basic(S) ->
Len = string:length(S),
case Len >= 6 of
false ->
{parse_error, invalid_format};
true ->
Hour_str = gleam@string:slice(S, 0, 2),
Minute_str = gleam@string:slice(S, 2, 2),
Second_part = gleam@string:drop_start(S, 4),
case {gleam_stdlib:parse_int(Hour_str),
gleam_stdlib:parse_int(Minute_str)} of
{{ok, Hour}, {ok, Minute}} ->
parse_second_part(Hour, Minute, Second_part);
{_, _} ->
{parse_error, invalid_format}
end
end.
-file("src/calendar/iso.gleam", 105).
?DOC(
" Parse an ISO 8601 time string with specified format.\n"
" Extended: HH:MM:SS[.ffffff], Basic: HHMMSS[.ffffff]\n"
" Also accepts a leading 'T' prefix which is stripped.\n"
).
-spec parse_time_with_format(binary(), format()) -> parse_result({integer(),
integer(),
integer(),
{integer(), integer()}}).
parse_time_with_format(Time_string, Format) ->
S = case gleam@string:first(Time_string) of
{ok, <<"T"/utf8>>} ->
gleam@string:drop_start(Time_string, 1);
_ ->
Time_string
end,
case Format of
extended ->
parse_time_extended(S);
basic ->
parse_time_basic(S)
end.
-file("src/calendar/iso.gleam", 96).
?DOC(" Parse an ISO 8601 time string in extended format (HH:MM:SS or HH:MM:SS.ffffff).\n").
-spec parse_time(binary()) -> parse_result({integer(),
integer(),
integer(),
{integer(), integer()}}).
parse_time(Time_string) ->
parse_time_with_format(Time_string, extended).
-file("src/calendar/iso.gleam", 360).
-spec try_parse_ndt_with_separator(binary(), binary(), format()) -> parse_result({integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()}}).
try_parse_ndt_with_separator(Datetime_string, Separator, Format) ->
case gleam@string:split_once(Datetime_string, Separator) of
{ok, {Date_part, Time_part}} ->
case {parse_date_with_format(Date_part, Format),
parse_time_with_format(Time_part, Format)} of
{{parse_ok, {Year, Month, Day}},
{parse_ok, {Hour, Minute, Second, Microsecond}}} ->
{parse_ok,
{Year, Month, Day, Hour, Minute, Second, Microsecond}};
{{parse_error, Err}, _} ->
{parse_error, Err};
{_, {parse_error, Err@1}} ->
{parse_error, Err@1}
end;
{error, _} ->
{parse_error, invalid_format}
end.
-file("src/calendar/iso.gleam", 130).
?DOC(
" Parse an ISO 8601 naive datetime string with specified format.\n"
" Extended: YYYY-MM-DDTHH:MM:SS, Basic: YYYYMMDDTHHMMSS\n"
" Also accepts space separator.\n"
).
-spec parse_naive_datetime_with_format(binary(), format()) -> parse_result({integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()}}).
parse_naive_datetime_with_format(Datetime_string, Format) ->
case try_parse_ndt_with_separator(Datetime_string, <<"T"/utf8>>, Format) of
{parse_ok, Result} ->
{parse_ok, Result};
{parse_error, _} ->
case try_parse_ndt_with_separator(
Datetime_string,
<<" "/utf8>>,
Format
) of
{parse_ok, Result@1} ->
{parse_ok, Result@1};
{parse_error, Err} ->
{parse_error, Err}
end
end.
-file("src/calendar/iso.gleam", 121).
?DOC(" Parse an ISO 8601 naive datetime string in extended format (YYYY-MM-DDTHH:MM:SS).\n").
-spec parse_naive_datetime(binary()) -> parse_result({integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()}}).
parse_naive_datetime(Datetime_string) ->
parse_naive_datetime_with_format(Datetime_string, extended).
-file("src/calendar/iso.gleam", 484).
-spec days_before_month(integer()) -> integer().
days_before_month(Month) ->
case Month of
1 ->
0;
2 ->
31;
3 ->
59;
4 ->
90;
5 ->
120;
6 ->
151;
7 ->
181;
8 ->
212;
9 ->
243;
10 ->
273;
11 ->
304;
12 ->
334;
_ ->
0
end.
-file("src/calendar/iso.gleam", 502).
-spec leap_day_offset_for_month(integer(), integer()) -> integer().
leap_day_offset_for_month(Year, Month) ->
case Month < 3 of
true ->
0;
false ->
case leap_year(Year) of
true ->
1;
false ->
0
end
end.
-file("src/calendar/iso.gleam", 514).
-spec year_day_to_year_date(integer(), integer()) -> {integer(), integer()}.
year_day_to_year_date(Extra_day, Day_of_year) ->
case Day_of_year < 31 of
true ->
{1, Day_of_year};
false ->
case Day_of_year < (59 + Extra_day) of
true ->
{2, Day_of_year - 31};
false ->
case Day_of_year < (90 + Extra_day) of
true ->
{3, (Day_of_year - 59) - Extra_day};
false ->
case Day_of_year < (120 + Extra_day) of
true ->
{4, (Day_of_year - 90) - Extra_day};
false ->
case Day_of_year < (151 + Extra_day) of
true ->
{5, (Day_of_year - 120) - Extra_day};
false ->
case Day_of_year < (181 + Extra_day) of
true ->
{6,
(Day_of_year - 151) - Extra_day};
false ->
case Day_of_year < (212 + Extra_day) of
true ->
{7,
(Day_of_year - 181)
- Extra_day};
false ->
case Day_of_year < (243
+ Extra_day) of
true ->
{8,
(Day_of_year
- 212)
- Extra_day};
false ->
case Day_of_year
< (273 + Extra_day) of
true ->
{9,
(Day_of_year
- 243)
- Extra_day};
false ->
case Day_of_year
< (304
+ Extra_day) of
true ->
{10,
(Day_of_year
- 273)
- Extra_day};
false ->
case Day_of_year
< (334
+ Extra_day) of
true ->
{11,
(Day_of_year
- 304)
- Extra_day};
false ->
{12,
(Day_of_year
- 334)
- Extra_day}
end
end
end
end
end
end
end
end
end
end
end.
-file("src/calendar/iso.gleam", 625).
?DOC(" Calculate day of year (1-366)\n").
-spec day_of_year(integer(), integer(), integer()) -> integer().
day_of_year(Year, Month, Day) ->
(days_before_month(Month) + leap_day_offset_for_month(Year, Month)) + Day.
-file("src/calendar/iso.gleam", 639).
?DOC(" Check if a date is valid\n").
-spec valid_date(integer(), integer(), integer()) -> boolean().
valid_date(Year, Month, Day) ->
(((Month >= 1) andalso (Month =< 12)) andalso (Day >= 1)) andalso (Day =< days_in_month(
Year,
Month
)).
-file("src/calendar/iso.gleam", 644).
?DOC(" Check if a time is valid\n").
-spec valid_time(integer(), integer(), integer(), integer()) -> boolean().
valid_time(Hour, Minute, Second, Microsecond) ->
(((((((Hour >= 0) andalso (Hour =< 23)) andalso (Minute >= 0)) andalso (Minute
=< 59))
andalso (Second >= 0))
andalso (Second =< 59))
andalso (Microsecond >= 0))
andalso (Microsecond < 1000000).
-file("src/calendar/iso.gleam", 656).
?DOC(" Convert time to microseconds since midnight\n").
-spec time_to_microseconds(integer(), integer(), integer(), integer()) -> integer().
time_to_microseconds(Hour, Minute, Second, Microsecond) ->
((((Hour * 3600) * 1000000) + ((Minute * 60) * 1000000)) + (Second * 1000000))
+ Microsecond.
-file("src/calendar/iso.gleam", 674).
?DOC(" Convert microseconds since midnight to time components\n").
-spec microseconds_to_time(integer()) -> {integer(),
integer(),
integer(),
integer()}.
microseconds_to_time(Total_microseconds) ->
Total_seconds = Total_microseconds div 1000000,
Microseconds = Total_microseconds rem 1000000,
Hours = Total_seconds div 3600,
Remaining = Total_seconds rem 3600,
Minutes = Remaining div 60,
Seconds = Remaining rem 60,
{Hours, Minutes, Seconds, Microseconds}.
-file("src/calendar/iso.gleam", 785).
?DOC(" Calculate quarter of year (1-4).\n").
-spec quarter_of_year(integer(), integer(), integer()) -> integer().
quarter_of_year(_, Month, _) ->
((Month - 1) div 3) + 1.
-file("src/calendar/iso.gleam", 790).
?DOC(" Calculate year of era from a year.\n").
-spec year_of_era(integer()) -> {integer(), integer()}.
year_of_era(Year) ->
case Year >= 1 of
true ->
{Year, 1};
false ->
{gleam@int:absolute_value(Year) + 1, 0}
end.
-file("src/calendar/iso.gleam", 798).
?DOC(" Calculate year of era from a date.\n").
-spec year_of_era_from_date(integer(), integer(), integer()) -> {integer(),
integer()}.
year_of_era_from_date(Year, _, _) ->
year_of_era(Year).
-file("src/calendar/iso.gleam", 901).
?DOC(" Get the precision for a time unit.\n").
-spec time_unit_to_precision(time_unit()) -> integer().
time_unit_to_precision(Unit) ->
case Unit of
nanosecond ->
6;
microsecond ->
6;
millisecond ->
3;
second ->
0
end.
-file("src/calendar/iso.gleam", 1096).
-spec div_rem(integer(), integer()) -> {integer(), integer()}.
div_rem(A, B) ->
D = case B of
0 -> 0;
Gleam@denominator -> A div Gleam@denominator
end,
R = A - (D * B),
case R >= 0 of
true ->
{D, R};
false ->
{D - 1, R + B}
end.
-file("src/calendar/iso.gleam", 1124).
-spec modulo(integer(), integer()) -> integer().
modulo(A, B) ->
R = case B of
0 -> 0;
Gleam@denominator -> A rem Gleam@denominator
end,
case R < 0 of
true ->
R + B;
false ->
R
end.
-file("src/calendar/iso.gleam", 1105).
-spec normalize_iso_days(integer(), integer(), integer()) -> {integer(),
{integer(), integer()}}.
normalize_iso_days(Days, Parts, Ppd) ->
case Parts < 0 of
true ->
New_days = (Days - 1) + (case Ppd of
0 -> 0;
Gleam@denominator -> Parts div Gleam@denominator
end),
New_parts = modulo(Parts, Ppd),
{New_days, {New_parts, Ppd}};
false ->
case Parts >= Ppd of
true ->
New_days@1 = Days + (case Ppd of
0 -> 0;
Gleam@denominator@1 -> Parts div Gleam@denominator@1
end),
New_parts@1 = case Ppd of
0 -> 0;
Gleam@denominator@2 -> Parts rem Gleam@denominator@2
end,
{New_days@1, {New_parts@1, Ppd}};
false ->
{Days, {Parts, Ppd}}
end
end.
-file("src/calendar/iso.gleam", 1138).
-spec gcd_helper(integer(), integer()) -> integer().
gcd_helper(A, B) ->
case B of
0 ->
A;
_ ->
gcd_helper(B, case B of
0 -> 0;
Gleam@denominator -> A rem Gleam@denominator
end)
end.
-file("src/calendar/iso.gleam", 1132).
-spec gcd(integer(), integer()) -> integer().
gcd(A, B) ->
Abs_a = gleam@int:absolute_value(A),
Abs_b = gleam@int:absolute_value(B),
gcd_helper(Abs_a, Abs_b).
-file("src/calendar/iso.gleam", 925).
?DOC(" Add a day fraction value to ISO days.\n").
-spec add_day_fraction_to_iso_days(
{integer(), {integer(), integer()}},
integer(),
integer()
) -> {integer(), {integer(), integer()}}.
add_day_fraction_to_iso_days(Iso_days, Add, Add_ppd) ->
{Days, {Parts, Ppd}} = Iso_days,
case Ppd =:= Add_ppd of
true ->
normalize_iso_days(Days, Parts + Add, Ppd);
false ->
New_parts = (Parts * Add_ppd) + (Add * Ppd),
Gcd_val = gcd(Ppd, Add_ppd),
Result_parts = case Gcd_val of
0 -> 0;
Gleam@denominator -> New_parts div Gleam@denominator
end,
Result_ppd = case Gcd_val of
0 -> 0;
Gleam@denominator@1 -> Ppd * Add_ppd div Gleam@denominator@1
end,
normalize_iso_days(Days, Result_parts, Result_ppd)
end.
-file("src/calendar/iso.gleam", 1145).
-spec shift_months({integer(), integer(), integer()}, integer()) -> {integer(),
integer(),
integer()}.
shift_months(Date, Months) ->
{Year, Month, Day} = Date,
Total_months = (((Year * 12) + Month) - 1) + Months,
{New_year, New_month_zero} = div_rem(Total_months, 12),
New_month = New_month_zero + 1,
Max_day = days_in_month(New_year, New_month),
New_day = case Day > Max_day of
true ->
Max_day;
false ->
Day
end,
{New_year, New_month, New_day}.
-file("src/calendar/iso.gleam", 1221).
-spec parse_offset_value(binary(), integer()) -> {ok, integer()} | {error, nil}.
parse_offset_value(Value, Sign) ->
case gleam_stdlib:contains_string(Value, <<":"/utf8>>) of
true ->
case gleam@string:split(Value, <<":"/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, Sign * ((H * 3600) + (M * 60))};
{_, _} ->
{error, nil}
end;
_ ->
{error, nil}
end;
false ->
case string:length(Value) of
4 ->
H_str@1 = gleam@string:slice(Value, 0, 2),
M_str@1 = gleam@string:slice(Value, 2, 2),
case {gleam_stdlib:parse_int(H_str@1),
gleam_stdlib:parse_int(M_str@1)} of
{{ok, H@1}, {ok, M@1}} ->
{ok, Sign * ((H@1 * 3600) + (M@1 * 60))};
{_, _} ->
{error, nil}
end;
2 ->
case gleam_stdlib:parse_int(Value) of
{ok, H@2} ->
{ok, (Sign * H@2) * 3600};
{error, _} ->
{error, nil}
end;
_ ->
{error, nil}
end
end.
-file("src/calendar/iso.gleam", 1213).
-spec parse_offset_string(binary()) -> {ok, integer()} | {error, nil}.
parse_offset_string(Offset) ->
case gleam@string:first(Offset) of
{ok, <<"+"/utf8>>} ->
parse_offset_value(gleam@string:drop_start(Offset, 1), 1);
{ok, <<"-"/utf8>>} ->
parse_offset_value(gleam@string:drop_start(Offset, 1), -1);
_ ->
{error, nil}
end.
-file("src/calendar/iso.gleam", 1164).
-spec split_at_offset(binary()) -> {ok, {binary(), integer()}} | {error, nil}.
split_at_offset(S) ->
case gleam@string:last(S) of
{error, _} ->
{error, nil};
{ok, _} ->
Len = string:length(S),
case Len >= 6 of
false ->
{error, nil};
true ->
Maybe_offset = gleam@string:slice(S, Len - 6, 6),
case gleam@string:first(Maybe_offset) of
{ok, <<"+"/utf8>>} ->
Dt_part = gleam@string:slice(S, 0, Len - 6),
case parse_offset_string(Maybe_offset) of
{ok, Offset} ->
{ok, {Dt_part, Offset}};
{error, _} ->
Maybe_offset5 = gleam@string:slice(
S,
Len - 5,
5
),
Dt_part5 = gleam@string:slice(S, 0, Len - 5),
case parse_offset_string(Maybe_offset5) of
{ok, Offset@1} ->
{ok, {Dt_part5, Offset@1}};
{error, _} ->
{error, nil}
end
end;
{ok, <<"-"/utf8>>} ->
Dt_part = gleam@string:slice(S, 0, Len - 6),
case parse_offset_string(Maybe_offset) of
{ok, Offset} ->
{ok, {Dt_part, Offset}};
{error, _} ->
Maybe_offset5 = gleam@string:slice(
S,
Len - 5,
5
),
Dt_part5 = gleam@string:slice(S, 0, Len - 5),
case parse_offset_string(Maybe_offset5) of
{ok, Offset@1} ->
{ok, {Dt_part5, Offset@1}};
{error, _} ->
{error, nil}
end
end;
_ ->
Maybe_offset5@1 = gleam@string:slice(S, Len - 5, 5),
case gleam@string:first(Maybe_offset5@1) of
{ok, <<"+"/utf8>>} ->
Dt_part5@1 = gleam@string:slice(
S,
0,
Len - 5
),
case parse_offset_string(Maybe_offset5@1) of
{ok, Offset@2} ->
{ok, {Dt_part5@1, Offset@2}};
{error, _} ->
{error, nil}
end;
{ok, <<"-"/utf8>>} ->
Dt_part5@1 = gleam@string:slice(
S,
0,
Len - 5
),
case parse_offset_string(Maybe_offset5@1) of
{ok, Offset@2} ->
{ok, {Dt_part5@1, Offset@2}};
{error, _} ->
{error, nil}
end;
_ ->
{error, nil}
end
end
end
end.
-file("src/calendar/iso.gleam", 695).
?DOC(" Parse an ISO 8601 UTC datetime string with specified format.\n").
-spec parse_utc_datetime_with_format(binary(), format()) -> parse_result({{integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()}},
integer()}).
parse_utc_datetime_with_format(Datetime_string, Format) ->
case gleam_stdlib:string_ends_with(Datetime_string, <<"Z"/utf8>>) of
true ->
Without_z = gleam@string:drop_end(Datetime_string, 1),
case parse_naive_datetime_with_format(Without_z, Format) of
{parse_ok,
{Year, Month, Day, Hour, Minute, Second, Microsecond}} ->
{parse_ok,
{{Year, Month, Day, Hour, Minute, Second, Microsecond},
0}};
{parse_error, Err} ->
{parse_error, Err}
end;
false ->
case split_at_offset(Datetime_string) of
{ok, {Dt_part, Offset_seconds}} ->
case parse_naive_datetime_with_format(Dt_part, Format) of
{parse_ok,
{Year@1,
Month@1,
Day@1,
Hour@1,
Minute@1,
Second@1,
Microsecond@1}} ->
{parse_ok,
{{Year@1,
Month@1,
Day@1,
Hour@1,
Minute@1,
Second@1,
Microsecond@1},
Offset_seconds}};
{parse_error, Err@1} ->
{parse_error, Err@1}
end;
{error, _} ->
{parse_error, invalid_format}
end
end.
-file("src/calendar/iso.gleam", 688).
?DOC(
" Parse an ISO 8601 UTC datetime string with offset.\n"
" Returns the datetime components and the UTC offset in seconds.\n"
).
-spec parse_utc_datetime(binary()) -> parse_result({{integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()}},
integer()}).
parse_utc_datetime(Datetime_string) ->
parse_utc_datetime_with_format(Datetime_string, extended).
-file("src/calendar/iso.gleam", 1282).
-spec zone_to_string(integer(), integer(), binary(), binary()) -> binary().
zone_to_string(Utc_offset, Std_offset, Zone_abbr, Time_zone) ->
case ((Time_zone =:= <<"Etc/UTC"/utf8>>) andalso (Utc_offset =:= 0)) andalso (Std_offset
=:= 0) of
true ->
<<""/utf8>>;
false ->
<<" "/utf8, Zone_abbr/binary>>
end.
-file("src/calendar/iso.gleam", 1294).
-spec pad_microsecond_value(integer(), integer()) -> binary().
pad_microsecond_value(Ms, Precision) ->
Ms_str = erlang:integer_to_binary(Ms),
Padded = case string:length(Ms_str) < 6 of
true ->
<<(gleam@string:repeat(<<"0"/utf8>>, 6 - string:length(Ms_str)))/binary,
Ms_str/binary>>;
false ->
Ms_str
end,
gleam@string:slice(Padded, 0, Precision).
-file("src/calendar/iso.gleam", 1386).
-spec is_digit(binary()) -> boolean().
is_digit(C) ->
case C of
<<"0"/utf8>> ->
true;
<<"1"/utf8>> ->
true;
<<"2"/utf8>> ->
true;
<<"3"/utf8>> ->
true;
<<"4"/utf8>> ->
true;
<<"5"/utf8>> ->
true;
<<"6"/utf8>> ->
true;
<<"7"/utf8>> ->
true;
<<"8"/utf8>> ->
true;
<<"9"/utf8>> ->
true;
_ ->
false
end.
-file("src/calendar/iso.gleam", 1361).
-spec extract_digits(list(binary()), binary()) -> {ok,
{integer(), binary(), binary()}} |
{error, nil}.
extract_digits(Chars, Acc) ->
case Chars of
[] ->
{error, nil};
[C | Rest] ->
case is_digit(C) of
true ->
extract_digits(Rest, <<Acc/binary, C/binary>>);
false ->
case Acc of
<<""/utf8>> ->
{error, nil};
_ ->
case gleam_stdlib:parse_int(Acc) of
{ok, Num} ->
{ok,
{Num,
C,
gleam@string:join(Rest, <<""/utf8>>)}};
{error, _} ->
{error, nil}
end
end
end
end.
-file("src/calendar/iso.gleam", 1356).
-spec extract_number_and_unit(binary()) -> {ok, {integer(), binary(), binary()}} |
{error, nil}.
extract_number_and_unit(S) ->
Chars = gleam@string:to_graphemes(S),
extract_digits(Chars, <<""/utf8>>).
-file("src/calendar/iso.gleam", 1303).
-spec do_parse_duration_date(binary(), list({binary(), integer()})) -> parse_result(list({binary(),
integer()})).
do_parse_duration_date(S, Acc) ->
case S of
<<""/utf8>> ->
{parse_ok, Acc};
_ ->
case extract_number_and_unit(S) of
{ok, {Value, Unit, Rest}} ->
Pair = case Unit of
<<"Y"/utf8>> ->
{ok, {<<"year"/utf8>>, Value}};
<<"M"/utf8>> ->
{ok, {<<"month"/utf8>>, Value}};
<<"W"/utf8>> ->
{ok, {<<"week"/utf8>>, Value}};
<<"D"/utf8>> ->
{ok, {<<"day"/utf8>>, Value}};
_ ->
{error, nil}
end,
case Pair of
{ok, P} ->
do_parse_duration_date(Rest, [P | Acc]);
{error, _} ->
{parse_error, invalid_duration}
end;
{error, _} ->
{parse_error, invalid_duration}
end
end.
-file("src/calendar/iso.gleam", 1330).
-spec do_parse_duration_time(binary(), list({binary(), integer()})) -> parse_result(list({binary(),
integer()})).
do_parse_duration_time(S, Acc) ->
case S of
<<""/utf8>> ->
{parse_ok, Acc};
_ ->
case extract_number_and_unit(S) of
{ok, {Value, Unit, Rest}} ->
Pair = case Unit of
<<"H"/utf8>> ->
{ok, {<<"hour"/utf8>>, Value}};
<<"M"/utf8>> ->
{ok, {<<"minute"/utf8>>, Value}};
<<"S"/utf8>> ->
{ok, {<<"second"/utf8>>, Value}};
_ ->
{error, nil}
end,
case Pair of
{ok, P} ->
do_parse_duration_time(Rest, [P | Acc]);
{error, _} ->
{parse_error, invalid_duration}
end;
{error, _} ->
{parse_error, invalid_duration}
end
end.
-file("src/calendar/iso.gleam", 1014).
?DOC(" Parse an ISO 8601 duration string.\n").
-spec parse_duration(binary()) -> parse_result(list({binary(), integer()})).
parse_duration(Duration_string) ->
case gleam@string:first(Duration_string) of
{ok, <<"P"/utf8>>} ->
Content = gleam@string:drop_start(Duration_string, 1),
case gleam@string:split_once(Content, <<"T"/utf8>>) of
{ok, {Date_part, Time_part}} ->
case {do_parse_duration_date(Date_part, []),
do_parse_duration_time(Time_part, [])} of
{{parse_ok, Date_pairs}, {parse_ok, Time_pairs}} ->
Pairs = lists:append(
lists:reverse(Date_pairs),
lists:reverse(Time_pairs)
),
{parse_ok, Pairs};
{{parse_error, Err}, _} ->
{parse_error, Err};
{_, {parse_error, Err@1}} ->
{parse_error, Err@1}
end;
{error, _} ->
case do_parse_duration_date(Content, []) of
{parse_ok, Pairs@1} ->
{parse_ok, lists:reverse(Pairs@1)};
{parse_error, Err@2} ->
{parse_error, Err@2}
end
end;
{ok, <<"+"/utf8>>} ->
case gleam@string:drop_start(Duration_string, 1) of
<<"P"/utf8, Rest/binary>> ->
parse_duration(<<"P"/utf8, Rest/binary>>);
_ ->
{parse_error, invalid_duration}
end;
{ok, <<"-"/utf8>>} ->
case gleam@string:drop_start(Duration_string, 1) of
<<"P"/utf8, Rest@1/binary>> ->
case parse_duration(<<"P"/utf8, Rest@1/binary>>) of
{parse_ok, Pairs@2} ->
{parse_ok,
gleam@list:map(
Pairs@2,
fun(Pair) ->
{erlang:element(1, Pair),
- erlang:element(2, Pair)}
end
)};
{parse_error, Err@3} ->
{parse_error, Err@3}
end;
_ ->
{parse_error, invalid_duration}
end;
_ ->
{parse_error, invalid_duration}
end.
-file("src/calendar/iso.gleam", 1394).
-spec zero_pad(integer(), integer()) -> binary().
zero_pad(Value, Width) ->
case Value >= 0 of
true ->
S = erlang:integer_to_binary(Value),
Len = string:length(S),
case Width - Len of
N when N =< 0 ->
S;
1 ->
<<"0"/utf8, S/binary>>;
2 ->
<<"00"/utf8, S/binary>>;
3 ->
<<"000"/utf8, S/binary>>;
4 ->
<<"0000"/utf8, S/binary>>;
5 ->
<<"00000"/utf8, S/binary>>;
6 ->
<<"000000"/utf8, S/binary>>;
_ ->
S
end;
false ->
<<"-"/utf8, (zero_pad(- Value, Width))/binary>>
end.
-file("src/calendar/iso.gleam", 574).
?DOC(" Convert date to string representation\n").
-spec date_to_string(integer(), integer(), integer(), format()) -> binary().
date_to_string(Year, Month, Day, Format) ->
case Format of
extended ->
<<<<<<<<(zero_pad(Year, 4))/binary, "-"/utf8>>/binary,
(zero_pad(Month, 2))/binary>>/binary,
"-"/utf8>>/binary,
(zero_pad(Day, 2))/binary>>;
basic ->
<<<<(zero_pad(Year, 4))/binary, (zero_pad(Month, 2))/binary>>/binary,
(zero_pad(Day, 2))/binary>>
end.
-file("src/calendar/iso.gleam", 586).
?DOC(" Convert time to string representation\n").
-spec time_to_string(integer(), integer(), integer(), integer(), format()) -> binary().
time_to_string(Hour, Minute, Second, Microsecond, Format) ->
Time_part = case Format of
extended ->
<<<<<<<<(zero_pad(Hour, 2))/binary, ":"/utf8>>/binary,
(zero_pad(Minute, 2))/binary>>/binary,
":"/utf8>>/binary,
(zero_pad(Second, 2))/binary>>;
basic ->
<<<<(zero_pad(Hour, 2))/binary, (zero_pad(Minute, 2))/binary>>/binary,
(zero_pad(Second, 2))/binary>>
end,
case Microsecond of
0 ->
Time_part;
_ ->
<<<<Time_part/binary, "."/utf8>>/binary,
(zero_pad(Microsecond, 6))/binary>>
end.
-file("src/calendar/iso.gleam", 944).
?DOC(" Convert naive datetime to string representation.\n").
-spec naive_datetime_to_string(
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()},
format()
) -> binary().
naive_datetime_to_string(
Year,
Month,
Day,
Hour,
Minute,
Second,
Microsecond,
Format
) ->
{Ms, Precision} = Microsecond,
Ms_part = case (Ms =:= 0) orelse (Precision =:= 0) of
true ->
<<""/utf8>>;
false ->
<<"."/utf8, (pad_microsecond_value(Ms, Precision))/binary>>
end,
case Format of
extended ->
<<<<<<(date_to_string(Year, Month, Day, extended))/binary,
" "/utf8>>/binary,
(time_to_string(Hour, Minute, Second, 0, extended))/binary>>/binary,
Ms_part/binary>>;
basic ->
<<<<<<(date_to_string(Year, Month, Day, basic))/binary, " "/utf8>>/binary,
(time_to_string(Hour, Minute, Second, 0, basic))/binary>>/binary,
Ms_part/binary>>
end.
-file("src/calendar/iso.gleam", 1257).
-spec offset_to_string(integer(), integer(), binary(), format()) -> binary().
offset_to_string(Utc_offset, Std_offset, Time_zone, Format) ->
case ((Time_zone =:= <<"Etc/UTC"/utf8>>) andalso (Utc_offset =:= 0)) andalso (Std_offset
=:= 0) of
true ->
<<"Z"/utf8>>;
false ->
Total = Utc_offset + Std_offset,
Sign = case Total >= 0 of
true ->
<<"+"/utf8>>;
false ->
<<"-"/utf8>>
end,
Abs_total = gleam@int:absolute_value(Total),
Hours = Abs_total div 3600,
Minutes = (Abs_total rem 3600) div 60,
case Format of
extended ->
<<<<<<Sign/binary, (zero_pad(Hours, 2))/binary>>/binary,
":"/utf8>>/binary,
(zero_pad(Minutes, 2))/binary>>;
basic ->
<<<<Sign/binary, (zero_pad(Hours, 2))/binary>>/binary,
(zero_pad(Minutes, 2))/binary>>
end
end.
-file("src/calendar/iso.gleam", 974).
?DOC(" Convert datetime to string representation with timezone.\n").
-spec datetime_to_string(
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()},
binary(),
binary(),
integer(),
integer(),
format()
) -> binary().
datetime_to_string(
Year,
Month,
Day,
Hour,
Minute,
Second,
Microsecond,
Time_zone,
Zone_abbr,
Utc_offset,
Std_offset,
Format
) ->
{Ms, Precision} = Microsecond,
Ms_part = case (Ms =:= 0) orelse (Precision =:= 0) of
true ->
<<""/utf8>>;
false ->
<<"."/utf8, (pad_microsecond_value(Ms, Precision))/binary>>
end,
Offset_part = offset_to_string(Utc_offset, Std_offset, Time_zone, Format),
Zone_part = zone_to_string(Utc_offset, Std_offset, Zone_abbr, Time_zone),
case Format of
extended ->
<<<<<<<<<<(date_to_string(Year, Month, Day, extended))/binary,
" "/utf8>>/binary,
(time_to_string(Hour, Minute, Second, 0, extended))/binary>>/binary,
Ms_part/binary>>/binary,
Offset_part/binary>>/binary,
Zone_part/binary>>;
basic ->
<<<<<<<<<<(date_to_string(Year, Month, Day, basic))/binary,
" "/utf8>>/binary,
(time_to_string(Hour, Minute, Second, 0, basic))/binary>>/binary,
Ms_part/binary>>/binary,
Offset_part/binary>>/binary,
Zone_part/binary>>
end.
-file("src/calendar/iso.gleam", 436).
-spec days_to_end_of_epoch(integer()) -> integer().
days_to_end_of_epoch(Year) ->
case Year < 0 of
true ->
Previous_year = Year + 1,
(((Previous_year div 4) - (Previous_year div 100)) + (Previous_year
div 400))
+ (Previous_year * 365);
false ->
0
end.
-file("src/calendar/iso.gleam", 453).
-spec days_in_previous_years(integer()) -> integer().
days_in_previous_years(Year) ->
case Year > 0 of
true ->
Previous_year = Year - 1,
((((Previous_year div 4) - (Previous_year div 100)) + (Previous_year
div 400))
+ (Previous_year * 365))
+ 366;
false ->
Previous_year@1 = Year - 1,
(((((Year div 4) - (Year div 100)) + (Year div 400)) - 1) + (Previous_year@1
* 365))
+ 366
end.
-file("src/calendar/iso.gleam", 178).
?DOC(" Convert date to days since the ISO epoch.\n").
-spec date_to_iso_days(integer(), integer(), integer()) -> integer().
date_to_iso_days(Year, Month, Day) ->
case ((Year =:= 0) andalso (Month =:= 1)) andalso (Day =:= 1) of
true ->
0;
false ->
case ((Year =:= 1970) andalso (Month =:= 1)) andalso (Day =:= 1) of
true ->
719528;
false ->
(((days_in_previous_years(Year) + days_before_month(Month))
+ leap_day_offset_for_month(Year, Month))
+ Day)
- 1
end
end.
-file("src/calendar/iso.gleam", 207).
?DOC(" Convert naive datetime to ISO days representation.\n").
-spec naive_datetime_to_iso_days(
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()}
) -> {integer(), {integer(), integer()}}.
naive_datetime_to_iso_days(Year, Month, Day, Hour, Minute, Second, Microsecond) ->
Days = date_to_iso_days(Year, Month, Day),
{Ms, Precision} = Microsecond,
Day_fraction_ms = ((((Hour * 3600) * 1000000) + ((Minute * 60) * 1000000)) + (Second
* 1000000))
+ Ms,
{Days, {Day_fraction_ms, Precision}}.
-file("src/calendar/iso.gleam", 422).
-spec days_to_year_helper(integer(), integer(), integer()) -> {integer(),
integer()}.
days_to_year_helper(Year, Days1, Days2) ->
case {Year < 0, Days1 >= Days2} of
{true, true} ->
days_to_year_helper(Year + 1, Days1, days_to_end_of_epoch(Year + 1));
{false, false} ->
case Days1 < Days2 of
true ->
days_to_year_helper(
Year - 1,
Days1,
days_in_previous_years(Year - 1)
);
false ->
{Year, Days2}
end;
{_, _} ->
{Year, Days2}
end.
-file("src/calendar/iso.gleam", 395).
-spec days_to_year_negative(integer()) -> {integer(), integer()}.
days_to_year_negative(Days) ->
Negative_days = 0 - Days,
Year_estimate = (0 - (case 365 of
0 -> 0;
Gleam@denominator -> Negative_days div Gleam@denominator
end)) - 1,
{Year, Days_before_year} = days_to_year_helper(
Year_estimate,
Days,
days_to_end_of_epoch(Year_estimate)
),
Leap_year_pad = case leap_year(Year) of
true ->
1;
false ->
0
end,
{Year, ((Leap_year_pad + 365) + Days) - Days_before_year}.
-file("src/calendar/iso.gleam", 411).
-spec days_to_year_positive(integer()) -> {integer(), integer()}.
days_to_year_positive(Days) ->
Year_estimate = case 365 of
0 -> 0;
Gleam@denominator -> Days div Gleam@denominator
end,
{Year, Days_before_year} = days_to_year_helper(
Year_estimate,
Days,
days_in_previous_years(Year_estimate)
),
{Year, Days - Days_before_year}.
-file("src/calendar/iso.gleam", 388).
-spec days_to_year(integer()) -> {integer(), integer()}.
days_to_year(Days) ->
case Days < 0 of
true ->
days_to_year_negative(Days);
false ->
days_to_year_positive(Days)
end.
-file("src/calendar/iso.gleam", 196).
?DOC(" Convert days since ISO epoch back to date.\n").
-spec date_from_iso_days(integer()) -> {integer(), integer(), integer()}.
date_from_iso_days(Iso_days) ->
{Year, Day_of_year} = days_to_year(Iso_days),
Extra_day = case leap_year(Year) of
true ->
1;
false ->
0
end,
{Month, Day_in_month} = year_day_to_year_date(Extra_day, Day_of_year),
{Year, Month, Day_in_month + 1}.
-file("src/calendar/iso.gleam", 224).
?DOC(" Convert ISO days representation back to naive datetime.\n").
-spec naive_datetime_from_iso_days({integer(), {integer(), integer()}}) -> {integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()}}.
naive_datetime_from_iso_days(Iso_days) ->
{Days, {Day_fraction_ms, Precision}} = Iso_days,
{Year, Month, Day} = date_from_iso_days(Days),
Total_seconds = Day_fraction_ms div 1000000,
Microseconds = Day_fraction_ms rem 1000000,
Hours = Total_seconds div 3600,
Remaining = Total_seconds rem 3600,
Minutes = Remaining div 60,
Seconds = Remaining rem 60,
{Year, Month, Day, Hours, Minutes, Seconds, {Microseconds, Precision}}.
-file("src/calendar/iso.gleam", 610).
?DOC(" Calculate day of week (1-7, where 1 is the starting day)\n").
-spec day_of_week(integer(), integer(), integer(), starting_day()) -> integer().
day_of_week(Year, Month, Day, Starting_day) ->
Iso_days = date_to_iso_days(Year, Month, Day),
Offset = case Starting_day of
monday ->
5;
sunday ->
6
end,
((Iso_days + Offset) rem 7) + 1.
-file("src/calendar/iso.gleam", 1158).
-spec shift_days({integer(), integer(), integer()}, integer()) -> {integer(),
integer(),
integer()}.
shift_days(Date, Days) ->
{Year, Month, Day} = Date,
Iso_days = date_to_iso_days(Year, Month, Day) + Days,
date_from_iso_days(Iso_days).
-file("src/calendar/iso.gleam", 804).
?DOC(
" Shift a date by a duration.\n"
" Duration is given as #(months, days) where months includes year*12.\n"
).
-spec shift_date(integer(), integer(), integer(), integer(), integer()) -> {integer(),
integer(),
integer()}.
shift_date(Year, Month, Day, Month_shift, Day_shift) ->
{New_year, New_month, New_day} = case Month_shift of
0 ->
{Year, Month, Day};
_ ->
shift_months({Year, Month, Day}, Month_shift)
end,
case Day_shift of
0 ->
{New_year, New_month, New_day};
_ ->
shift_days({New_year, New_month, New_day}, Day_shift)
end.
-file("src/calendar/iso.gleam", 630).
?DOC(" Calculate day of era\n").
-spec day_of_era(integer(), integer(), integer()) -> {integer(), integer()}.
day_of_era(Year, Month, Day) ->
Days = date_to_iso_days(Year, Month, Day),
case Year >= 1 of
true ->
{(Days - 366) + 1, 1};
false ->
{gleam@int:absolute_value(Days - 366), 0}
end.
-file("src/calendar/iso.gleam", 730).
?DOC(
" Convert time to day fraction representation.\n"
" Day fraction is {microseconds_in_day, parts_per_day}.\n"
).
-spec time_to_day_fraction(
integer(),
integer(),
integer(),
{integer(), integer()}
) -> {integer(), integer()}.
time_to_day_fraction(Hour, Minute, Second, Microsecond) ->
{Ms, _} = Microsecond,
case (((Hour =:= 0) andalso (Minute =:= 0)) andalso (Second =:= 0)) andalso (Ms
=:= 0) of
true ->
{0, 86400000000};
false ->
Combined = ((((Hour * 3600) + (Minute * 60)) + Second) * 1000000) + Ms,
{Combined, 86400000000}
end.
-file("src/calendar/iso.gleam", 769).
?DOC(" Get ISO days for the beginning of a day.\n").
-spec iso_days_to_beginning_of_day({integer(), {integer(), integer()}}) -> {integer(),
{integer(), integer()}}.
iso_days_to_beginning_of_day(Iso_days) ->
{Days, _} = Iso_days,
{Days, {0, 86400000000}}.
-file("src/calendar/iso.gleam", 777).
?DOC(" Get ISO days for the end of a day.\n").
-spec iso_days_to_end_of_day({integer(), {integer(), integer()}}) -> {integer(),
{integer(), integer()}}.
iso_days_to_end_of_day(Iso_days) ->
{Days, _} = Iso_days,
{Days, {86400000000 - 1, 86400000000}}.
-file("src/calendar/iso.gleam", 824).
?DOC(" Shift a naive datetime by duration components.\n").
-spec shift_naive_datetime(
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()},
integer(),
integer(),
integer(),
integer()
) -> {integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
{integer(), integer()}}.
shift_naive_datetime(
Year,
Month,
Day,
Hour,
Minute,
Second,
Microsecond,
Month_shift,
Day_shift,
Second_shift,
Microsecond_shift
) ->
{Y, M, D} = case Month_shift of
0 ->
{Year, Month, Day};
_ ->
shift_months({Year, Month, Day}, Month_shift)
end,
{Y2, M2, D2} = case Day_shift of
0 ->
{Y, M, D};
_ ->
shift_days({Y, M, D}, Day_shift)
end,
Total_time_shift = (Second_shift * 1000000) + Microsecond_shift,
case Total_time_shift of
0 ->
{Y2, M2, D2, Hour, Minute, Second, Microsecond};
_ ->
{Ms, Precision} = Microsecond,
Current_us = ((((Hour * 3600) + (Minute * 60)) + Second) * 1000000)
+ Ms,
New_us = Current_us + Total_time_shift,
{Day_overflow, Day_us} = div_rem(New_us, 86400000000),
{Y3, M3, D3} = case Day_overflow of
0 ->
{Y2, M2, D2};
_ ->
shift_days({Y2, M2, D2}, Day_overflow)
end,
{H, Min, Sec, Us} = microseconds_to_time(Day_us),
{Y3, M3, D3, H, Min, Sec, {Us, Precision}}
end.
-file("src/calendar/iso.gleam", 874).
?DOC(" Shift time by duration components.\n").
-spec shift_time(
integer(),
integer(),
integer(),
{integer(), integer()},
integer(),
integer()
) -> {integer(), integer(), integer(), {integer(), integer()}}.
shift_time(Hour, Minute, Second, Microsecond, Second_shift, Microsecond_shift) ->
{Ms, Precision} = Microsecond,
Total_shift = (Second_shift * 1000000) + Microsecond_shift,
case Total_shift of
0 ->
{Hour, Minute, Second, Microsecond};
_ ->
Current_us = ((((Hour * 3600) + (Minute * 60)) + Second) * 1000000)
+ Ms,
New_us = Current_us + Total_shift,
Wrapped = modulo(New_us, 86400000000),
{H, Min, Sec, Us} = microseconds_to_time(Wrapped),
{H, Min, Sec, {Us, Precision}}
end.
-file("src/calendar/iso.gleam", 1067).
?DOC(" Convert a gregorian seconds value to ISO days representation.\n").
-spec gregorian_seconds_to_iso_days(integer(), integer()) -> {integer(),
{integer(), integer()}}.
gregorian_seconds_to_iso_days(Seconds, Microsecond) ->
{Days, Rest_seconds} = div_rem(Seconds, 86400),
Microseconds_in_day = (Rest_seconds * 1000000) + Microsecond,
{Days, {Microseconds_in_day, 86400000000}}.
-file("src/calendar/iso.gleam", 1089).
-spec divide_by_parts_per_day(integer(), integer()) -> integer().
divide_by_parts_per_day(Parts, Ppd) ->
case Ppd =:= 86400000000 of
true ->
Parts;
false ->
case Ppd of
0 -> 0;
Gleam@denominator -> Parts * 86400000000 div Gleam@denominator
end
end.
-file("src/calendar/iso.gleam", 750).
?DOC(" Convert day fraction back to time components.\n").
-spec time_from_day_fraction({integer(), integer()}) -> {integer(),
integer(),
integer(),
{integer(), integer()}}.
time_from_day_fraction(Day_fraction) ->
{Parts_in_day, Ppd} = Day_fraction,
case Parts_in_day =:= 0 of
true ->
{0, 0, 0, {0, 6}};
false ->
Total_microseconds = divide_by_parts_per_day(Parts_in_day, Ppd),
{Hours, Rest1} = div_rem(Total_microseconds, 3600 * 1000000),
{Minutes, Rest2} = div_rem(Rest1, 60 * 1000000),
{Seconds, Microseconds} = div_rem(Rest2, 1000000),
{Hours, Minutes, Seconds, {Microseconds, 6}}
end.
-file("src/calendar/iso.gleam", 911).
?DOC(" Convert ISO days to a time unit value.\n").
-spec iso_days_to_unit({integer(), {integer(), integer()}}, time_unit()) -> integer().
iso_days_to_unit(Iso_days, Unit) ->
{Days, {Parts, Ppd}} = Iso_days,
Day_microseconds = Days * 86400000000,
Microseconds = divide_by_parts_per_day(Parts, Ppd),
Total_us = Day_microseconds + Microseconds,
case Unit of
second ->
case 1000000 of
0 -> 0;
Gleam@denominator -> Total_us div Gleam@denominator
end;
millisecond ->
Total_us div 1000;
microsecond ->
Total_us;
nanosecond ->
Total_us * 1000
end.