kewisch / ical.js

Javascript parser for ics (rfc5545) and vcard (rfc6350) data
https://kewisch.github.io/ical.js/
Mozilla Public License 2.0
991 stars 137 forks source link

Timezone not set correctly when iterating occurrences #257

Open roberthartung opened 8 years ago

roberthartung commented 8 years ago

ics file:

BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
BEGIN:VEVENT
CREATED:20160728T114557Z
LAST-MODIFIED:20160728T122120Z
DTSTAMP:20160728T122120Z
UID:9fda684c-373b-4f58-9fc7-6db9f06218b5
SUMMARY:Test-Event
RRULE:FREQ=WEEKLY;UNTIL=20160912T080000Z
EXDATE:20160808T080000Z
DTSTART;TZID=Europe/Berlin:20160725T100000
DTEND;TZID=Europe/Berlin:20160725T110000
TRANSP:OPAQUE
SEQUENCE:3
X-MOZ-GENERATION:4
END:VEVENT
BEGIN:VEVENT
CREATED:20160728T115039Z
LAST-MODIFIED:20160728T115048Z
DTSTAMP:20160728T115048Z
UID:9fda684c-373b-4f58-9fc7-6db9f06218b5
SUMMARY:Test-Event - Reccurence #2
RECURRENCE-ID;TZID=Europe/Berlin:20160801T100000
DTSTART;TZID=Europe/Berlin:20160801T100000
DTEND;TZID=Europe/Berlin:20160801T110000
TRANSP:OPAQUE
SEQUENCE:2
X-MOZ-GENERATION:3
END:VEVENT
BEGIN:VEVENT
CREATED:20160728T114921Z
LAST-MODIFIED:20160728T122231Z
DTSTAMP:20160728T122231Z
UID:9fda684c-373b-4f58-9fc7-6db9f06218b5
SUMMARY:Test-Event
TRANSP:OPAQUE
CLASS:PUBLIC
RECURRENCE-ID;TZID=Europe/Berlin:20160725T100000
DTSTART;TZID=Europe/Berlin:20160725T100000
DTEND;TZID=Europe/Berlin:20160725T113000
END:VEVENT
PRODID:-//Inf-IT//InfCloud 0.12.1//EN
END:VCALENDAR

Code:

const ICAL = require("ical.js");
const fs = require('fs');

var buffer = fs.readFileSync("/file.ics", "utf8");
var jcal = ICAL.parse(buffer);
var vcalendar = new ICAL.Component(jcal);
var vevents = vcalendar.getAllSubcomponents('vevent');
var event;
var exceptions = [];
vevents.forEach((vevent, i) => {
  let _event = new ICAL.Event(vevent);
  if ( _event.isRecurring() ) {
    event = _event;
  } else if( _event.isRecurrenceException() ) {
    exceptions.push(_event);
  }
});

if(event) {
  exceptions.forEach((ex) => {
    event.relateException(ex);
  });

  var exdates = [];
  event.component.getAllProperties('exdate').forEach((exdate) => {
    exdates.push(exdate.getFirstValue().toJSDate());
  });

  let it = event.iterator();

  // console.log(it);

  var occ;
  while((occ = it.next())) {
    var details = event.getOccurrenceDetails(occ);
    var jsDate = details.startDate.toJSDate();
    // console.log(jsDate, exdates.indexOf(jsDate));
    /// Does not work due to different objects
    // Another problem is the timezone
    if(exdates.indexOf(jsDate) != -1) {
      console.log("    ", jsDate, 'IGNORED'); // THIS NEVER GETS CALLED
    } else {
      console.log("    ", jsDate, details.item.summary, event.findRangeException(details.startDate), it.exDate);
    }
  }
}

it.exDate is undefined after the date that should be excluded, but I still see it through the iterator.

In lib/ical/recur_expansion.js:267 you compare the EXDATE to "last". Last points at the end of the event (10am), but the EXDATE points to the start (8am).

roberthartung commented 8 years ago

Addition: It looks like a problem with the timezone. The exDate is correctly in timezone 'Z' with utcOffset 0. In contrast, the startDate I get from the iterator for the occurence details object is 10:00:00 with utcOffset 0 and tz 'floating' which is obviously wrong!

kewisch commented 7 years ago

Does it work correctly when using UTC as the timezone? I won't have immediate time to look into this. Can you create a minimal testcase I can paste into http://jsfiddle.net/kewisch/227efboL/ ?

mifi commented 7 years ago

I made a wrapper for ical.js that solves this problem: https://github.com/mifi/ical-expander

marcoancona commented 6 years ago

@mifi Nice thank you. The problem is not easily solved within ical.js since it does not know standard timezones.

PavelPolyakov commented 6 years ago

It seems that EXDATE is not considered in ical.js at all, I was not even able to find this information in the event properties.

I had to use https://github.com/mifi/ical-expander at the end and it worked like a charm.