var ical = require('./ical') , request = require('request') , fs = require('fs') exports.fromURL = function(url, opts, cb){ if (!cb) return; request(url, opts, function(err, r, data){ if (err) { return cb(err, null); } else if (r.statusCode != 200) { return cb(r.statusCode + ": " + r.statusMessage, null); } cb(undefined, ical.parseICS(data)); }) } exports.parseFile = function(filename){ return ical.parseICS(fs.readFileSync(filename, 'utf8')) } var rrule = require('rrule').RRule function getLocaleISOString(date) { var year = date.getFullYear().toString(10).padStart(4,'0'); var month = date.getMonth().toString(10).padStart(2,'0'); var day = date.getDate().toString(10).padStart(2,'0'); var hour = date.getHours().toString(10).padStart(2,'0'); var minute = date.getMinutes().toString(10).padStart(2,'0'); var second = date.getSeconds().toString(10).padStart(2,'0'); return `${year}${month}${day}T${hour}${minute}${second}Z`; } ical.objectHandlers['RRULE'] = function(val, params, curr, stack, line){ curr.rrule = line; return curr } var originalEnd = ical.objectHandlers['END']; ical.objectHandlers['END'] = function (val, params, curr, stack) { // Recurrence rules are only valid for VEVENT, VTODO, and VJOURNAL. // More specifically, we need to filter the VCALENDAR type because we might end up with a defined rrule // due to the subtypes. if ((val === "VEVENT") || (val === "VTODO") || (val === "VJOURNAL")) { if (curr.rrule) { var rule = curr.rrule.replace('RRULE:', ''); if (rule.indexOf('DTSTART') === -1) { if (curr.start.length === 8) { var comps = /^(\d{4})(\d{2})(\d{2})$/.exec(curr.start); if (comps) { curr.start = new Date(comps[1], comps[2] - 1, comps[3]); } } if (typeof curr.start.toISOString === 'function') { try { // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time rule += ';DTSTART=' + getLocaleISOString(curr.start); } catch (error) { console.error("ERROR when trying to convert to ISOString", error); } } else { console.error("No toISOString function in curr.start", curr.start); } } curr.rrule = rrule.fromString(rule); } } return originalEnd.call(this, val, params, curr, stack); }