Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- defmodule RFC822 do
- import NimbleParsec
- day =
- choice([
- string("Mon"),
- string("Tue"),
- string("Wed"),
- string("Thu"),
- string("Fri"),
- string("Sat"),
- string("Sun")
- ])
- |> string(",")
- |> string(" ")
- date =
- integer(min: 1, max: 2)
- |> ignore(string(" "))
- |> choice([
- string("Jan"),
- string("Feb"),
- string("Mar"),
- string("Apr"),
- string("May"),
- string("Jun"),
- string("Jul"),
- string("Aug"),
- string("Sep"),
- string("Oct"),
- string("Nov"),
- string("Dec")
- ])
- |> ignore(string(" "))
- |> integer(2)
- time =
- integer(2)
- |> ignore(string(":"))
- |> integer(2)
- |> ignore(string(":"))
- |> optional(integer(2))
- timezone =
- choice([
- string("EST"),
- string("EDT"),
- ])
- defparsec :rfc822,
- optional(ignore(day))
- |> concat(date)
- |> ignore(string(" "))
- |> concat(time)
- |> ignore(string(" "))
- |> concat(timezone)
- def parse(binary) do
- case rfc822(binary) do
- {:ok, result, _, _, _, _} ->
- # FIXME: irreponsible pattern matching.
- [day, month, year, hour, minute, second, zone] = result
- {:ok, naive_datetime} =
- NaiveDateTime.new(year(year), month(month), day, hour, minute, second)
- {
- :ok,
- naive_datetime
- |> NaiveDateTime.add(zone_to_offset(zone), :second)
- |> DateTime.from_naive!("Etc/UTC")
- }
- {:error, _, rest, _, _, _} ->
- {:error, :invalid}
- end
- end
- defp year(year), do: 2000 + year
- defp month("Jan"), do: 1
- defp month("Feb"), do: 2
- defp month("Mar"), do: 3
- defp month("Apr"), do: 4
- defp month("May"), do: 5
- defp month("Jun"), do: 6
- defp month("Jul"), do: 7
- defp month("Aug"), do: 8
- defp month("Sep"), do: 9
- defp month("Oct"), do: 10
- defp month("Nov"), do: 11
- defp month("Dec"), do: 12
- defp zone_to_offset("EDT"), do: -4 * 60 * 60
- defp zone_to_offset("EST"), do: -5 * 60 * 60
- defp zone_to_offset("CST"), do: -6 * 60 * 60
- # More zones to come
- end
- defmodule RFC822Test do
- use ExUnit.Case
- test "parses the string" do
- string = "Wed, 02 Oct 02 08:00:00 EST"
- assert {:ok, datetime} = RFC822.parse(string)
- assert datetime.year == 2002
- assert datetime.month == 10
- assert datetime.day == 2
- assert datetime.hour == 3
- assert datetime.minute == 0
- assert datetime.second == 0
- string = "02 Oct 19 08:00:00 EST"
- assert {:ok, datetime} = RFC822.parse(string)
- assert datetime.year == 2019
- assert datetime.month == 10
- assert datetime.day == 2
- assert datetime.hour == 3
- assert datetime.minute == 0
- assert datetime.second == 0
- string = "Wednesday, 02 Oct 19 08:00:00 EST"
- assert {:error, invalid} = RFC822.parse(string)
- end
- end
Add Comment
Please, Sign In to add comment