Last active
January 17, 2025 16:42
-
-
Save James-E-A/539f74d3f9c8c0dea811c745c0aa44ce to your computer and use it in GitHub Desktop.
Elixir parse HTML datetime form input values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule FooWeb.Util do | |
# https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string | |
@spec parse_web_time!(String.t()) :: NaiveDateTime.t() | |
@spec parse_web_time!(String.t(), Calendar.time_zone()) :: DateTime.t() | |
@spec parse_web_time!(String.t(), Calendar.time_zone(), Calendar.time_zone_database()) :: DateTime.t() | |
def parse_web_time!(<<s::binary-size(16)>>) do | |
Timex.parse!(s, "{YYYY}-{0M}-{0D}T{h24}:{m}") | |
end | |
def parse_web_time!(<<s::binary-size(19)>>) do | |
Timex.parse!(s, "{YYYY}-{0M}-{0D}T{h24}:{m}:{s}") | |
end | |
def parse_web_time!(<<s::binary>>) when byte_size(s) in 21..23 do | |
Timex.parse!(s, "{YYYY}-{0M}-{0D}T{h24}:{m}:{s}{ss}") | |
end | |
def parse_web_time!(_), do: (raise ArgumentError, "Expected 16, 19, or 21-23 character long ASCII string.") | |
def parse_web_time!(s, tz), do: parse_web_time!(s) |> DateTime.from_naive!(tz) | |
def parse_web_time!(s, tz, tz_db), do: parse_web_time!(s) |> DateTime.from_naive!(tz, tz_db) | |
@spec parse_web_time(String.t()) :: {:ok, NaiveDateTime.t()} | {:error, term()} | |
#spec parse_web_time(String.t(), "Etc/UTC") :: {:ok, DateTime.t()} | {:error, term()} | |
@spec parse_web_time(String.t(), Calendar.time_zone()) :: {:ok, DateTime.t()} | {:ambiguous, DateTime.t(), DateTime.t()} | {:gap, DateTime.t(), DateTime.t()} | {:error, term()} | |
@spec parse_web_time(String.t(), Calendar.time_zone(), Calendar.time_zone_database()) :: {:ok, DateTime.t()} | {:ambiguous, DateTime.t(), DateTime.t()} | {:gap, DateTime.t(), DateTime.t()} | {:error, term()} | |
def parse_web_time(<<s::binary-size(16)>>) do | |
Timex.parse(s, "{YYYY}-{0M}-{0D}T{h24}:{m}") | |
end | |
def parse_web_time(<<s::binary-size(19)>>) do | |
Timex.parse(s, "{YYYY}-{0M}-{0D}T{h24}:{m}:{s}") | |
end | |
def parse_web_time(<<s::binary>>) when byte_size(s) in 21..23 do | |
Timex.parse(s, "{YYYY}-{0M}-{0D}T{h24}:{m}:{s}{ss}") | |
end | |
def parse_web_time(_), do: {:error, :einval} | |
def parse_web_time(s, tz) do | |
case parse_web_time(s) do | |
{:ok, t} -> DateTime.from_naive(t, tz) | |
other -> other | |
end | |
end | |
def parse_web_time(s, tz, tz_db) do | |
case parse_web_time(s) do | |
{:ok, t} -> DateTime.from_naive(t, tz, tz_db) | |
other -> other | |
end | |
end | |
# https://github.com/erlang/otp/blob/OTP-26.2.5.6/lib/kernel/src/inet_parse.erl#L442 | |
@spec parse_address(String.t()) :: {:ok, :inet.ip_address()} | {:error, :einval} | |
def parse_address(s) do | |
s |> String.to_charlist |> :inet_parse.address | |
end | |
@spec parse_address!(ip_address :: String.t()) :: :inet.ip_address() | |
def parse_address!(s) do | |
case parse_address(s) do | |
{:ok, ip_address} -> ip_address | |
{:error, :einval} -> raise ArgumentError, "invalid IP address" | |
end | |
end | |
@spec unparse_address(:inet.ip_address()) :: String.t() | |
def unparse_address(ip_address) do | |
# infallible for well-typed input | |
ip_address |> :inet_parse.ntoa |> List.to_string | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment