Packages

Parse and manipulate iCalendar (RFC5545) and vCard objects (RFC6350)

Current section

Files

Jump to
vobject lib icalendar value.ex
Raw

lib/icalendar/value.ex

defprotocol ICalendar.Value do
@fallback_to_any true
def to_ics(data)
end
alias ICalendar.Value
alias ICalendar.Util.RRULE, as: Util
defimpl Value, for: ICalendar.RRULE do
@doc """
This function converts RRULE structs into an RRULE string
"""
def to_ics(rrule = %ICalendar.RRULE{}) do
rrule
|> Map.from_struct
|> Map.keys
|> order_conventionally
|> Enum.map(&(Util.serialize(rrule, &1)))
|> Enum.reject(&(&1 == nil))
|> Enum.join(";")
end
# some clients rely on FREQ coming first, COUNT or UNTIL next, then others
# even though against spec (http://www.kanzaki.com/docs/ical/recur.html#descr)
# Apple Calendar, I'm looking at you
defp order_conventionally(keys) do
first_keys = [:frequency, :count, :until, :interval]
last_keys = keys -- first_keys
first_keys ++ last_keys
end
end
defimpl Value, for: BitString do
def to_ics(x) do
x
|> String.replace(~S"\n", ~S"\\n")
|> String.replace("\n", ~S"\n")
end
end
defimpl Value, for: Tuple do
defmacro elem2(x, i1, i2) do
quote do
unquote(x) |> elem(unquote(i1)) |> elem(unquote(i2))
end
end
@doc """
This macro is used to establish whether a tuple is in the Erlang Timestamp
format (`{{year, month, day}, {hour, minute, second}}`).
"""
defmacro is_datetime_tuple(x) do
quote do
# Year
( unquote(x) |> elem2(0, 0) |> is_integer) and
# Month
( unquote(x) |> elem2(0, 1) |> is_integer) and
((unquote(x) |> elem2(0, 1)) <= 12) and
((unquote(x) |> elem2(0, 1)) >= 1) and
# Day
( unquote(x) |> elem2(0, 2) |> is_integer) and
((unquote(x) |> elem2(0, 2)) <= 31) and
((unquote(x) |> elem2(0, 2)) >= 1) and
# Hour
( unquote(x) |> elem2(1, 0) |> is_integer) and
((unquote(x) |> elem2(1, 0)) <= 23) and
((unquote(x) |> elem2(1, 0)) >= 0) and
# Minute
( unquote(x) |> elem2(1, 1) |> is_integer) and
((unquote(x) |> elem2(1, 1)) <= 59) and
((unquote(x) |> elem2(1, 1)) >= 0) and
# Second
( unquote(x) |> elem2(1, 2) |> is_integer) and
((unquote(x) |> elem2(1, 2)) <= 60) and
((unquote(x) |> elem2(1, 2)) >= 0)
end
end
@doc """
This function converts Erlang timestamp tuples into DateTimes.
"""
def to_ics(timestamp) when is_datetime_tuple(timestamp) do
timestamp
|> Timex.to_datetime
|> Value.to_ics
end
def to_ics(x), do: x
end
defimpl Value, for: DateTime do
use Timex
@doc """
This function converts DateTimes to UTC timezone and then into Strings in the
iCal format
"""
def to_ics(%DateTime{} = timestamp) do
format_string = "{YYYY}{0M}{0D}T{h24}{m}{s}"
{:ok, result} =
timestamp
|> Timex.format(format_string)
result
end
end
defimpl Value, for: Date do
use Timex
@doc """
This function converts DateTimes to UTC timezone and then into Strings in the
iCal format
"""
def to_ics(%Date{} = timestamp) do
format_string = "{YYYY}{0M}{0D}"
{:ok, result} =
timestamp
|> Timex.format(format_string)
result
end
end
defimpl Value, for: Any do
def to_ics(x), do: x
end