Packages

Parse ISO8601 date-times! But you should probably use RFC3339 instead

Current section

Files

Jump to
datetime_iso8601 src datetime_iso8601.erl
Raw

src/datetime_iso8601.erl

-module(datetime_iso8601).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/datetime_iso8601.gleam").
-export([parse/1]).
-export_type([date_time/0, time/0, day_of_week/0, timezone/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() :: {calendar_date,
integer(),
gleam@time@calendar:month(),
integer(),
gleam@option:option(time())} |
{calendar_month_date, integer(), gleam@time@calendar:month()} |
{calendar_year_date, integer()} |
{ordinal_date, integer(), integer(), gleam@option:option(time())} |
{week_date,
integer(),
integer(),
day_of_week(),
gleam@option:option(time())} |
{year_week, integer(), integer()}.
-type time() :: {time_second,
integer(),
integer(),
integer(),
gleam@option:option(integer()),
gleam@option:option(timezone())} |
{time_minute,
integer(),
integer(),
gleam@option:option(integer()),
gleam@option:option(timezone())} |
{time_hour,
integer(),
gleam@option:option(integer()),
gleam@option:option(timezone())}.
-type day_of_week() :: monday |
tuesday |
wednesday |
thursday |
friday |
saturday |
sunday.
-type timezone() :: utc | {offset, integer(), integer()}.
-file("src/datetime_iso8601.gleam", 587).
-spec int_to_day_of_week(integer()) -> {ok, day_of_week()} | {error, nil}.
int_to_day_of_week(Day) ->
case Day of
1 ->
{ok, monday};
2 ->
{ok, tuesday};
3 ->
{ok, wednesday};
4 ->
{ok, thursday};
5 ->
{ok, friday};
6 ->
{ok, saturday};
7 ->
{ok, sunday};
_ ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 657).
-spec is_leap_year(integer()) -> boolean().
is_leap_year(Year) ->
((Year rem 4) =:= 0) andalso (((Year rem 100) /= 0) orelse ((Year rem 400)
=:= 0)).
-file("src/datetime_iso8601.gleam", 600).
-spec validate_day(integer(), gleam@time@calendar:month(), integer()) -> {ok,
nil} |
{error, nil}.
validate_day(Year, Month, Day) ->
Max_day = case Month of
january ->
31;
march ->
31;
may ->
31;
july ->
31;
august ->
31;
october ->
31;
december ->
31;
april ->
30;
june ->
30;
september ->
30;
november ->
30;
february ->
case is_leap_year(Year) of
true ->
29;
false ->
28
end
end,
case (Day >= 1) andalso (Day =< Max_day) of
true ->
{ok, nil};
false ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 623).
-spec validate_day_of_year(integer(), integer()) -> {ok, nil} | {error, nil}.
validate_day_of_year(Year, Day) ->
Max_day = case is_leap_year(Year) of
true ->
366;
false ->
365
end,
case (Day >= 1) andalso (Day =< Max_day) of
true ->
{ok, nil};
false ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 642).
-spec weeks_in_year(integer()) -> integer().
weeks_in_year(Year) ->
Y = Year - 1,
Jan1_weekday = ((((1 + Y) + (Y div 4)) - (Y div 100)) + (Y div 400)) rem 7,
Days_in_year = case is_leap_year(Year) of
true ->
366;
false ->
365
end,
Dec31_weekday = ((Jan1_weekday + Days_in_year) - 1) rem 7,
case (Jan1_weekday =:= 4) orelse (Dec31_weekday =:= 4) of
true ->
53;
false ->
52
end.
-file("src/datetime_iso8601.gleam", 634).
-spec validate_week(integer(), integer()) -> {ok, nil} | {error, nil}.
validate_week(Year, Week) ->
Max_week = weeks_in_year(Year),
case (Week >= 1) andalso (Week =< Max_week) of
true ->
{ok, nil};
false ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 661).
-spec validate_hour(integer()) -> {ok, nil} | {error, nil}.
validate_hour(Hour) ->
case (Hour >= 0) andalso (Hour =< 24) of
true ->
{ok, nil};
false ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 668).
-spec validate_midnight(time()) -> {ok, nil} | {error, nil}.
validate_midnight(Time) ->
case Time of
{time_second, 24, Minute, Second, Nanosecond, _} ->
case ((Minute =:= 0) andalso (Second =:= 0)) andalso (Nanosecond =:= none) of
true ->
{ok, nil};
false ->
{error, nil}
end;
{time_minute, 24, Minute@1, Nanosecond@1, _} ->
case (Minute@1 =:= 0) andalso (Nanosecond@1 =:= none) of
true ->
{ok, nil};
false ->
{error, nil}
end;
{time_hour, 24, Nanosecond@2, _} ->
case Nanosecond@2 =:= none of
true ->
{ok, nil};
false ->
{error, nil}
end;
_ ->
{ok, nil}
end.
-file("src/datetime_iso8601.gleam", 689).
-spec validate_minute(integer()) -> {ok, nil} | {error, nil}.
validate_minute(Minute) ->
case (Minute >= 0) andalso (Minute =< 59) of
true ->
{ok, nil};
false ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 696).
-spec validate_second(integer()) -> {ok, nil} | {error, nil}.
validate_second(Second) ->
case (Second >= 0) andalso (Second =< 59) of
true ->
{ok, nil};
false ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 558).
-spec parse_sign(bitstring()) -> {ok, {binary(), bitstring()}} | {error, nil}.
parse_sign(Bytes) ->
case Bytes of
<<Byte, Rest/binary>> when Byte =:= 16#2B ->
{ok, {<<"+"/utf8>>, Rest}};
<<Byte@1, Rest@1/binary>> when Byte@1 =:= 16#2D ->
{ok, {<<"-"/utf8>>, Rest@1}};
_ ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 491).
-spec parse_fraction_as_nanoseconds_loop(bitstring(), integer(), integer()) -> {ok,
{integer(), bitstring()}} |
{error, nil}.
parse_fraction_as_nanoseconds_loop(Bytes, Acc, Power) ->
Power@1 = Power div 10,
case Bytes of
<<Byte, Rest/binary>> when ((Byte >= 16#30) andalso (Byte =< 16#39)) andalso (Power@1 < 1) ->
parse_fraction_as_nanoseconds_loop(Rest, Acc, Power@1);
<<Byte@1, Rest@1/binary>> when (Byte@1 >= 16#30) andalso (Byte@1 =< 16#39) ->
Digit = Byte@1 - 16#30,
parse_fraction_as_nanoseconds_loop(
Rest@1,
Acc + (Digit * Power@1),
Power@1
);
_ ->
{ok, {Acc, Bytes}}
end.
-file("src/datetime_iso8601.gleam", 476).
-spec parse_fraction_as_nanoseconds(bitstring()) -> {ok,
{integer(), bitstring()}} |
{error, nil}.
parse_fraction_as_nanoseconds(Bytes) ->
case Bytes of
<<Byte, Rest/binary>> when (Byte >= 16#30) andalso (Byte =< 16#39) ->
parse_fraction_as_nanoseconds_loop(
<<Byte, Rest/bitstring>>,
0,
1000000000
);
_ ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 464).
-spec parse_optional_fraction_as_nanoseconds(bitstring()) -> {ok,
{gleam@option:option(integer()), bitstring()}} |
{error, nil}.
parse_optional_fraction_as_nanoseconds(Bytes) ->
case Bytes of
<<Byte, Rest/binary>> when Byte =:= 16#2E ->
gleam@result:'try'(
parse_fraction_as_nanoseconds(Rest),
fun(_use0) ->
{Ns, Bytes@1} = _use0,
{ok, {{some, Ns}, Bytes@1}}
end
);
_ ->
{ok, {none, Bytes}}
end.
-file("src/datetime_iso8601.gleam", 573).
-spec parse_digits_loop(bitstring(), integer(), integer(), integer()) -> {ok,
{integer(), bitstring()}} |
{error, nil}.
parse_digits_loop(Bytes, Count, Acc, K) ->
case Bytes of
_ when K >= Count ->
{ok, {Acc, Bytes}};
<<Byte, Rest/binary>> when (Byte >= 16#30) andalso (Byte =< 16#39) ->
parse_digits_loop(Rest, Count, (Acc * 10) + (Byte - 16#30), K + 1);
_ ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 566).
-spec parse_digits(bitstring(), integer()) -> {ok, {integer(), bitstring()}} |
{error, nil}.
parse_digits(Bytes, Count) ->
parse_digits_loop(Bytes, Count, 0, 0).
-file("src/datetime_iso8601.gleam", 523).
-spec parse_timezone_offset(bitstring()) -> {ok,
{gleam@option:option(timezone()), bitstring()}} |
{error, nil}.
parse_timezone_offset(Bytes) ->
gleam@result:'try'(
parse_sign(Bytes),
fun(_use0) ->
{Sign, Bytes@1} = _use0,
gleam@result:'try'(
parse_digits(Bytes@1, 2),
fun(_use0@1) ->
{Hours, Bytes@2} = _use0@1,
case Bytes@2 of
<<Byte, Rest/binary>> when Byte =:= 16#3A ->
gleam@result:'try'(
parse_digits(Rest, 2),
fun(_use0@2) ->
{Minutes, Bytes@3} = _use0@2,
Hours@1 = case Sign of
<<"-"/utf8>> ->
- Hours;
_ ->
Hours
end,
{ok,
{{some, {offset, Hours@1, Minutes}},
Bytes@3}}
end
);
<<Byte@1, _/binary>> when (Byte@1 >= 16#30) andalso (Byte@1 =< 16#39) ->
gleam@result:'try'(
parse_digits(Bytes@2, 2),
fun(_use0@3) ->
{Minutes@1, Bytes@4} = _use0@3,
Hours@2 = case Sign of
<<"-"/utf8>> ->
- Hours;
_ ->
Hours
end,
{ok,
{{some, {offset, Hours@2, Minutes@1}},
Bytes@4}}
end
);
_ ->
Hours@3 = case Sign of
<<"-"/utf8>> ->
- Hours;
_ ->
Hours
end,
{ok, {{some, {offset, Hours@3, 0}}, Bytes@2}}
end
end
)
end
).
-file("src/datetime_iso8601.gleam", 510).
-spec parse_optional_timezone(bitstring()) -> {ok,
{gleam@option:option(timezone()), bitstring()}} |
{error, nil}.
parse_optional_timezone(Bytes) ->
case Bytes of
<<Byte, Rest/binary>> when (Byte =:= 16#5A) orelse (Byte =:= 16#7A) ->
{ok, {{some, utc}, Rest}};
<<Byte@1, _/binary>> when (Byte@1 =:= 16#2B) orelse (Byte@1 =:= 16#2D) ->
parse_timezone_offset(Bytes);
_ ->
{ok, {none, Bytes}}
end.
-file("src/datetime_iso8601.gleam", 402).
-spec parse_time_extended_after_hour(bitstring(), integer()) -> {ok,
{time(), bitstring()}} |
{error, nil}.
parse_time_extended_after_hour(Bytes, Hour) ->
gleam@result:'try'(
parse_digits(Bytes, 2),
fun(_use0) ->
{Minute, Bytes@1} = _use0,
gleam@result:'try'(
validate_minute(Minute),
fun(_) -> case Bytes@1 of
<<Byte, Rest/binary>> when Byte =:= 16#3A ->
gleam@result:'try'(
parse_digits(Rest, 2),
fun(_use0@1) ->
{Second, Bytes@2} = _use0@1,
gleam@result:'try'(
validate_second(Second),
fun(_) ->
gleam@result:'try'(
parse_optional_fraction_as_nanoseconds(
Bytes@2
),
fun(_use0@2) ->
{Nanosecond, Bytes@3} = _use0@2,
gleam@result:'try'(
parse_optional_timezone(
Bytes@3
),
fun(_use0@3) ->
{Timezone, Bytes@4} = _use0@3,
{ok,
{{time_second,
Hour,
Minute,
Second,
Nanosecond,
Timezone},
Bytes@4}}
end
)
end
)
end
)
end
);
<<Byte@1, Rest@1/binary>> when Byte@1 =:= 16#2E ->
gleam@result:'try'(
parse_fraction_as_nanoseconds(Rest@1),
fun(_use0@4) ->
{Nanosecond@1, Bytes@5} = _use0@4,
gleam@result:'try'(
parse_optional_timezone(Bytes@5),
fun(_use0@5) ->
{Timezone@1, Bytes@6} = _use0@5,
{ok,
{{time_minute,
Hour,
Minute,
{some, Nanosecond@1},
Timezone@1},
Bytes@6}}
end
)
end
);
_ ->
gleam@result:'try'(
parse_optional_timezone(Bytes@1),
fun(_use0@6) ->
{Timezone@2, Bytes@7} = _use0@6,
{ok,
{{time_minute,
Hour,
Minute,
none,
Timezone@2},
Bytes@7}}
end
)
end end
)
end
).
-file("src/datetime_iso8601.gleam", 433).
-spec parse_time_basic_after_hour(bitstring(), integer()) -> {ok,
{time(), bitstring()}} |
{error, nil}.
parse_time_basic_after_hour(Bytes, Hour) ->
gleam@result:'try'(
parse_digits(Bytes, 2),
fun(_use0) ->
{Minute, Bytes@1} = _use0,
gleam@result:'try'(
validate_minute(Minute),
fun(_) -> case Bytes@1 of
<<Byte, _/binary>> when (Byte >= 16#30) andalso (Byte =< 16#39) ->
gleam@result:'try'(
parse_digits(Bytes@1, 2),
fun(_use0@1) ->
{Second, Bytes@2} = _use0@1,
gleam@result:'try'(
validate_second(Second),
fun(_) ->
gleam@result:'try'(
parse_optional_fraction_as_nanoseconds(
Bytes@2
),
fun(_use0@2) ->
{Nanosecond, Bytes@3} = _use0@2,
gleam@result:'try'(
parse_optional_timezone(
Bytes@3
),
fun(_use0@3) ->
{Timezone, Bytes@4} = _use0@3,
{ok,
{{time_second,
Hour,
Minute,
Second,
Nanosecond,
Timezone},
Bytes@4}}
end
)
end
)
end
)
end
);
<<Byte@1, Rest/binary>> when Byte@1 =:= 16#2E ->
gleam@result:'try'(
parse_fraction_as_nanoseconds(Rest),
fun(_use0@4) ->
{Nanosecond@1, Bytes@5} = _use0@4,
gleam@result:'try'(
parse_optional_timezone(Bytes@5),
fun(_use0@5) ->
{Timezone@1, Bytes@6} = _use0@5,
{ok,
{{time_minute,
Hour,
Minute,
{some, Nanosecond@1},
Timezone@1},
Bytes@6}}
end
)
end
);
_ ->
gleam@result:'try'(
parse_optional_timezone(Bytes@1),
fun(_use0@6) ->
{Timezone@2, Bytes@7} = _use0@6,
{ok,
{{time_minute,
Hour,
Minute,
none,
Timezone@2},
Bytes@7}}
end
)
end end
)
end
).
-file("src/datetime_iso8601.gleam", 369).
-spec parse_time_after_hour(bitstring(), integer()) -> {ok,
{time(), bitstring()}} |
{error, nil}.
parse_time_after_hour(Bytes, Hour) ->
case Bytes of
<<Byte, Rest/binary>> when Byte =:= 16#3A ->
parse_time_extended_after_hour(Rest, Hour);
<<Byte@1, Rest@1/binary>> when Byte@1 =:= 16#2E ->
gleam@result:'try'(
parse_fraction_as_nanoseconds(Rest@1),
fun(_use0) ->
{Nanosecond, Bytes@1} = _use0,
gleam@result:'try'(
parse_optional_timezone(Bytes@1),
fun(_use0@1) ->
{Timezone, Bytes@2} = _use0@1,
{ok,
{{time_hour, Hour, {some, Nanosecond}, Timezone},
Bytes@2}}
end
)
end
);
<<Byte@2, _/binary>> when (((Byte@2 =:= 16#5A) orelse (Byte@2 =:= 16#7A)) orelse (Byte@2 =:= 16#2B)) orelse (Byte@2 =:= 16#2D) ->
gleam@result:'try'(
parse_optional_timezone(Bytes),
fun(_use0@2) ->
{Timezone@1, Bytes@3} = _use0@2,
{ok, {{time_hour, Hour, none, Timezone@1}, Bytes@3}}
end
);
<<Byte@3, _/binary>> when (Byte@3 >= 16#30) andalso (Byte@3 =< 16#39) ->
parse_time_basic_after_hour(Bytes, Hour);
<<>> ->
{ok, {{time_hour, Hour, none, none}, Bytes}};
_ ->
{error, nil}
end.
-file("src/datetime_iso8601.gleam", 361).
-spec parse_time(bitstring()) -> {ok, {time(), bitstring()}} | {error, nil}.
parse_time(Bytes) ->
gleam@result:'try'(
parse_digits(Bytes, 2),
fun(_use0) ->
{Hour, Bytes@1} = _use0,
gleam@result:'try'(
validate_hour(Hour),
fun(_) ->
gleam@result:'try'(
parse_time_after_hour(Bytes@1, Hour),
fun(_use0@1) ->
{Time, Bytes@2} = _use0@1,
gleam@result:'try'(
validate_midnight(Time),
fun(_) -> {ok, {Time, Bytes@2}} end
)
end
)
end
)
end
).
-file("src/datetime_iso8601.gleam", 345).
-spec parse_optional_time(bitstring()) -> {ok,
{gleam@option:option(time()), bitstring()}} |
{error, nil}.
parse_optional_time(Bytes) ->
case Bytes of
<<Byte, Rest/binary>> when ((Byte =:= 16#54) orelse (Byte =:= 16#74)) orelse (Byte =:= 16#20) ->
gleam@result:'try'(
parse_time(Rest),
fun(_use0) ->
{Time, Bytes@1} = _use0,
{ok, {{some, Time}, Bytes@1}}
end
);
_ ->
{ok, {none, Bytes}}
end.
-file("src/datetime_iso8601.gleam", 228).
-spec parse_extended_calendar_or_ordinal(bitstring(), integer()) -> {ok,
date_time()} |
{error, nil}.
parse_extended_calendar_or_ordinal(Bytes, Year) ->
gleam@result:'try'(
parse_digits(Bytes, 2),
fun(_use0) ->
{First_two, Bytes@1} = _use0,
case Bytes@1 of
<<Byte, Rest/binary>> when Byte =:= 16#2D ->
Month = First_two,
gleam@result:'try'(
gleam@time@calendar:month_from_int(Month),
fun(Month@1) ->
gleam@result:'try'(
parse_digits(Rest, 2),
fun(_use0@1) ->
{Day, Bytes@2} = _use0@1,
gleam@result:'try'(
validate_day(Year, Month@1, Day),
fun(_) ->
gleam@result:'try'(
parse_optional_time(Bytes@2),
fun(_use0@2) ->
{Time, Bytes@3} = _use0@2,
case Bytes@3 of
<<>> ->
{ok,
{calendar_date,
Year,
Month@1,
Day,
Time}};
_ ->
{error, nil}
end
end
)
end
)
end
)
end
);
<<Byte@1, _/binary>> when (Byte@1 >= 16#30) andalso (Byte@1 =< 16#39) ->
gleam@result:'try'(
parse_digits(Bytes@1, 1),
fun(_use0@3) ->
{Third_digit, Bytes@4} = _use0@3,
Day_of_year = (First_two * 10) + Third_digit,
gleam@result:'try'(
validate_day_of_year(Year, Day_of_year),
fun(_) ->
gleam@result:'try'(
parse_optional_time(Bytes@4),
fun(_use0@4) ->
{Time@1, Bytes@5} = _use0@4,
case Bytes@5 of
<<>> ->
{ok,
{ordinal_date,
Year,
Day_of_year,
Time@1}};
_ ->
{error, nil}
end
end
)
end
)
end
);
<<>> ->
Month@2 = First_two,
gleam@result:'try'(
gleam@time@calendar:month_from_int(Month@2),
fun(Month@3) ->
{ok, {calendar_month_date, Year, Month@3}}
end
);
<<Byte@2, _/binary>> when ((Byte@2 =:= 16#54) orelse (Byte@2 =:= 16#74)) orelse (Byte@2 =:= 16#20) ->
{error, nil};
_ ->
{error, nil}
end
end
).
-file("src/datetime_iso8601.gleam", 277).
-spec parse_extended_week(bitstring(), integer()) -> {ok, date_time()} |
{error, nil}.
parse_extended_week(Bytes, Year) ->
gleam@result:'try'(
parse_digits(Bytes, 2),
fun(_use0) ->
{Week, Bytes@1} = _use0,
gleam@result:'try'(
validate_week(Year, Week),
fun(_) -> case Bytes@1 of
<<Byte, Rest/binary>> when Byte =:= 16#2D ->
gleam@result:'try'(
parse_digits(Rest, 1),
fun(_use0@1) ->
{Day_num, Bytes@2} = _use0@1,
gleam@result:'try'(
int_to_day_of_week(Day_num),
fun(Day_of_week) ->
gleam@result:'try'(
parse_optional_time(Bytes@2),
fun(_use0@2) ->
{Time, Bytes@3} = _use0@2,
case Bytes@3 of
<<>> ->
{ok,
{week_date,
Year,
Week,
Day_of_week,
Time}};
_ ->
{error, nil}
end
end
)
end
)
end
);
<<>> ->
{ok, {year_week, Year, Week}};
_ ->
{error, nil}
end end
)
end
).
-file("src/datetime_iso8601.gleam", 219).
-spec parse_extended_format(bitstring(), integer()) -> {ok, date_time()} |
{error, nil}.
parse_extended_format(Bytes, Year) ->
case Bytes of
<<Byte, Rest/binary>> when (Byte =:= 16#57) orelse (Byte =:= 16#77) ->
parse_extended_week(Rest, Year);
_ ->
parse_extended_calendar_or_ordinal(Bytes, Year)
end.
-file("src/datetime_iso8601.gleam", 295).
-spec parse_basic_week(bitstring(), integer()) -> {ok, date_time()} |
{error, nil}.
parse_basic_week(Bytes, Year) ->
gleam@result:'try'(
parse_digits(Bytes, 2),
fun(_use0) ->
{Week, Bytes@1} = _use0,
gleam@result:'try'(
validate_week(Year, Week),
fun(_) -> case Bytes@1 of
<<Byte, Rest/binary>> when (Byte >= 16#30) andalso (Byte =< 16#39) ->
Day_num = Byte - 16#30,
gleam@result:'try'(
int_to_day_of_week(Day_num),
fun(Day_of_week) ->
gleam@result:'try'(
parse_optional_time(Rest),
fun(_use0@1) ->
{Time, Bytes@2} = _use0@1,
case Bytes@2 of
<<>> ->
{ok,
{week_date,
Year,
Week,
Day_of_week,
Time}};
_ ->
{error, nil}
end
end
)
end
);
<<>> ->
{ok, {year_week, Year, Week}};
_ ->
{error, nil}
end end
)
end
).
-file("src/datetime_iso8601.gleam", 313).
-spec parse_basic_format(bitstring(), integer()) -> {ok, date_time()} |
{error, nil}.
parse_basic_format(Bytes, Year) ->
gleam@result:'try'(
parse_digits(Bytes, 1),
fun(_use0) ->
{Digit1, Bytes@1} = _use0,
gleam@result:'try'(
parse_digits(Bytes@1, 1),
fun(_use0@1) ->
{Digit2, Bytes@2} = _use0@1,
gleam@result:'try'(
parse_digits(Bytes@2, 1),
fun(_use0@2) ->
{Digit3, Bytes@3} = _use0@2,
case parse_digits(Bytes@3, 1) of
{ok, {Digit4, Bytes@4}} ->
Month = (Digit1 * 10) + Digit2,
gleam@result:'try'(
gleam@time@calendar:month_from_int(
Month
),
fun(Month@1) ->
Day = (Digit3 * 10) + Digit4,
gleam@result:'try'(
validate_day(Year, Month@1, Day),
fun(_) ->
gleam@result:'try'(
parse_optional_time(
Bytes@4
),
fun(_use0@3) ->
{Time, Bytes@5} = _use0@3,
case Bytes@5 of
<<>> ->
{ok,
{calendar_date,
Year,
Month@1,
Day,
Time}};
_ ->
{error, nil}
end
end
)
end
)
end
);
{error, nil} ->
Day_of_year = ((Digit1 * 100) + (Digit2 * 10))
+ Digit3,
gleam@result:'try'(
validate_day_of_year(Year, Day_of_year),
fun(_) ->
gleam@result:'try'(
parse_optional_time(Bytes@3),
fun(_use0@4) ->
{Time@1, Bytes@6} = _use0@4,
case Bytes@6 of
<<>> ->
{ok,
{ordinal_date,
Year,
Day_of_year,
Time@1}};
_ ->
{error, nil}
end
end
)
end
)
end
end
)
end
)
end
).
-file("src/datetime_iso8601.gleam", 207).
-spec parse_after_year(bitstring(), integer()) -> {ok, date_time()} |
{error, nil}.
parse_after_year(Bytes, Year) ->
case Bytes of
<<>> ->
{ok, {calendar_year_date, Year}};
<<Byte, Rest/binary>> when Byte =:= 16#2D ->
parse_extended_format(Rest, Year);
<<Byte@1, Rest@1/binary>> when (Byte@1 =:= 16#57) orelse (Byte@1 =:= 16#77) ->
parse_basic_week(Rest@1, Year);
_ ->
parse_basic_format(Bytes, Year)
end.
-file("src/datetime_iso8601.gleam", 202).
?DOC(
" Parse an ISO8601 formatted date-time.\n"
"\n"
" The ISO8601 date-time format is complex. Unless you have particular need\n"
" for things like `2024-W11` you are better off using the RFC3339 format,\n"
" which the `gleam_time` package supports.\n"
).
-spec parse(binary()) -> {ok, date_time()} | {error, nil}.
parse(Input) ->
gleam@result:'try'(
parse_digits(<<Input/binary>>, 4),
fun(_use0) ->
{Year, Bytes} = _use0,
parse_after_year(Bytes, Year)
end
).