lpil / icalendar

🗓️ A small library for reading and writing ICalendar files.
MIT License
103 stars 56 forks source link

TZID provided by VTIMEZONE component is ignored and `from_ics` crashes if TZID is non-IANA #71

Open SergeyMosin opened 1 month ago

SergeyMosin commented 1 month ago

Example with TZID:Fictitious:

    """
    BEGIN:VCALENDAR
    VERSION:2.0
    BEGIN:VTIMEZONE
    TZID:Fictitious
    LAST-MODIFIED:19870101T000000Z
    BEGIN:STANDARD
    DTSTART:19671029T020000
    RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
    TZOFFSETFROM:-0400
    TZOFFSETTO:-0500
    TZNAME:EST
    END:STANDARD
    BEGIN:DAYLIGHT
    DTSTART:19870405T020000
    RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=19980404T070000Z
    TZOFFSETFROM:-0500
    TZOFFSETTO:-0400
    TZNAME:EDT
    END:DAYLIGHT
    BEGIN:DAYLIGHT
    DTSTART:19990424T020000
    RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=4
    TZOFFSETFROM:-0500
    TZOFFSETTO:-0400
    TZNAME:EDT
    END:DAYLIGHT
    END:VTIMEZONE
    BEGIN:VEVENT
    DTSTAMP:19980309T231000Z
    UID:guid-1.host1.com
    ORGANIZER;ROLE=CHAIR:MAILTO:mrbig@host.com
    ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:employee-A@host.com
    DESCRIPTION:Project XYZ Review Meeting
    CREATED:19980309T130000Z
    SUMMARY:XYZ Project Review
    DTSTART;TZID=Fictitious:19980312T083000
    DTEND;TZID=Fictitious:19980312T093000
    LOCATION:1CP Conference Room 4350
    END:VEVENT
    END:VCALENDAR
    """
    |> ICalendar.Deserialize.from_ics()
    |> IO.inspect()

errors out with the following:

 ** (ArgumentError) construction of binary failed: segment 2 of type 'binary': expected a binary but got: nil
     code: |> ICalendar.Deserialize.from_ics()
     stacktrace:
       (icalendar 1.1.2) lib/icalendar/util/deserialize.ex:252: ICalendar.Util.Deserialize.to_date/2
       (icalendar 1.1.2) lib/icalendar/util/deserialize.ex:82: ICalendar.Util.Deserialize.parse_attr/2
       (elixir 1.15.7) lib/enum.ex:2510: Enum."-reduce/3-lists^foldl/2-0-"/3
       (icalendar 1.1.2) lib/icalendar/deserialize.ex:37: ICalendar.Deserialize.BitString.get_events/3

The VTIMEZONE component/example is taken directly from RFC 5545 [Page 70]

Expected Behavior

  1. No crash
  2. Calculate Offset from UTC using the VTIMEZONE component and use the offset for DTSTART, DTEND, etc...

LibIcal has the icaltimezone_get_utc_offset function ( https://github.com/libical/libical/blob/fbdbc621fe1858aa4203a3bd7a859231aeec47bb/src/libical/icaltimezone.c#L808 ) but I am not sure if it would easy to port it from C to Elixir

P.S. I know that this library is in maintenance mode, but this report could be useful to future maintainers. Thank you for you work on this project.