1defmodule Calendar.ParseUtil do 2 @moduledoc false 3 4 def month_number_for_month_name(string) do 5 string 6 |> String.downcase 7 |> cap_month_number_for_month_name 8 end 9 defp cap_month_number_for_month_name("jan"), do: 1 10 defp cap_month_number_for_month_name("feb"), do: 2 11 defp cap_month_number_for_month_name("mar"), do: 3 12 defp cap_month_number_for_month_name("apr"), do: 4 13 defp cap_month_number_for_month_name("may"), do: 5 14 defp cap_month_number_for_month_name("jun"), do: 6 15 defp cap_month_number_for_month_name("jul"), do: 7 16 defp cap_month_number_for_month_name("aug"), do: 8 17 defp cap_month_number_for_month_name("sep"), do: 9 18 defp cap_month_number_for_month_name("oct"), do: 10 19 defp cap_month_number_for_month_name("nov"), do: 11 20 defp cap_month_number_for_month_name("dec"), do: 12 21 # By returning 0 for invalid month names, we have a valid int to pass to 22 # DateTime.from_erl that will return a nice error. This way we avoid an 23 # exception when parsing an httpdate with an invalid month name. 24 defp cap_month_number_for_month_name(_), do: 0 25 26 def to_int(string) do 27 {int, _} = Integer.parse(string) 28 int 29 end 30 31 def capture_rfc2822_string(string) do 32 ~r/(?<day>[\d]{1,2})[\s]+(?<month>[^\d]{3})[\s]+(?<year>[\d]{4})[\s]+(?<hour>[\d]{2})[^\d]?(?<min>[\d]{2})[^\d]?(?<sec>[\d]{2})[^\d]?(((?<offset_sign>[+-])(?<offset_hours>[\d]{2})(?<offset_mins>[\d]{2})|(?<offset_letters>[A-Z]{1,3})))?/ 33 |> Regex.named_captures(string) 34 end 35 36 # Takes strings of hours and mins and return secs 37 def hours_mins_to_secs!(hours, mins) do 38 hours_int = hours |> to_int 39 mins_int = mins |> to_int 40 hours_int*3600+mins_int*60 41 end 42 43 def two_to_four_digit_year(year, year_guessing_base) when year < 100 do 44 closest_year(year, year_guessing_base) 45 end 46 def two_to_four_digit_year(year, _), do: year 47 48 defp closest_year(two_digit_year, year_guessing_base) do 49 two_digit_year 50 |> possible_years(year_guessing_base) 51 |> Enum.map(fn year -> {year, abs(year_guessing_base-year)} end) 52 |> Enum.min_by(fn {_year, diff} -> diff end) 53 |> elem(0) 54 end 55 defp possible_years(two_digit_year, year_guessing_base) do 56 centuries_for_guessing_base(year_guessing_base) 57 |> Enum.map(&(&1+two_digit_year)) 58 end 59 # The three centuries closest to the guessing base 60 # if you provide e.g. 2015 it should return [1900, 2000, 2100] 61 defp centuries_for_guessing_base(year_guessing_base) do 62 base_century = year_guessing_base-rem(year_guessing_base, 100) 63 [base_century-100, base_century, base_century+100] 64 end 65end 66