0
votes

After generating an ICS file, when I go to import into Outlook/ Google, I find that only one event gets imported when Add by URL. Even with the Import option it gives a message 1 out of 9 events imported

After checking multiple links, the iCalendar specifications, it is clear to me that this is very sparsely documented. Plus, nobody is able to answer these kind of questions till date. There are "similar" questions, though none of them worked for me and many others!

CODE

PHP

function generateICS()
{
require_once(__DIR__."/libs/icalendar/zapcallib.php");
$iCalObj = new ZCiCal();
$ZDateHelper = new ZDateHelper();
$handle = fopen(__DIR__."\\generated\\eventlist.txt", "r");
if($handle){
    while(($line = fgets($handle)) !== false){
        $eventarr = json_decode($line, true);
        $eventObj = new ZCiCalNode("VEVENT", $iCalObj->curnode);
        // add title
        $eventObj->addNode(new ZCiCalDataNode("SUMMARY:" . $eventarr["EventName"]));
        if(isset($eventarr['EventDuration'])){
            // create timestamp
            $start = date_timestamp_get(date_create_from_format("y-M-d H:i", $eventarr['EventStart']));
            // add start date
            $eventObj->addNode(new ZCiCalDataNode("DTSTART:" . $ZDateHelper->fromUnixDateTimetoiCal($start)));
            // add duration
            $eventObj->addNode(new ZCiCalDataNode("DURATION:" . $eventarr['EventDuration']));
        }
        else{
            // create timestamp
            $start = date_timestamp_get(date_create_from_format("y-M-d H:i", $eventarr['EventStart']));
            $end = date_timestamp_get(date_create_from_format("y-M-d H:i", $eventarr['EventEnd']));

            // add start date
            $eventObj->addNode(new ZCiCalDataNode("DTSTART:" . $ZDateHelper->fromUnixDateTimetoiCal($start)));
            // add end date
            $eventObj->addNode(new ZCiCalDataNode("DTEND:" . $ZDateHelper->fromUnixDateTimetoiCal($end)));
        }
        // UID is a required item in VEVENT, create unique string for this event
        // Adding your domain to the end is a good way of creating uniqueness
        $uid = "event".time()."@company.org";
        $eventObj->addNode(new ZCiCalDataNode("UID:" . $uid));
        $eventObj->addNode(new ZCiCalDataNode("Description:" . ZCiCal::formatContent($eventarr['EventDesc'])));
        $eventObj->addNode(new ZCiCalDataNode("METHOD:" . ZCiCal::formatContent("PUBLISH")));
        $eventObj->addNode(new ZCiCalDataNode("X-WR-CALNAME:" . ZCiCal::formatContent("OurCalendar")));
        $eventObj->addNode(new ZCiCalDataNode("X-WR-TIMEZONE:" . ZCiCal::formatContent("(GMT-05:00) Eastern Time (US & Canada)")));

        $eventObj->addNode(new ZCiCalDataNode("SEQUENCE:" . ZCiCal::formatContent("0")));
        $eventObj->addNode(new ZCiCalDataNode("CLASS:" . ZCiCal::formatContent("PUBLIC")));
        $eventObj->addNode(new ZCiCalDataNode("DTSTAMP:".$ZDateHelper->fromUnixDateTimetoiCal(time())));
        $eventObj->addNode(new ZCiCalDataNode("LAST-MODIFIED:".$ZDateHelper->fromUnixDateTimetoiCal(time())));
    }
    fclose($handle);
}
else{
    echo "<div class='alert alert-danger'>Error reading events file!</div>";
}
$ics = $iCalObj->export();
echo $ics;
file_put_contents(__DIR__."\\generated\\company.ics", $ics);
}

Javascript

function genBtns() {
var _html = "";
var subIcal = "<a class='m-1 btn bg-lightdark text-dark' href='" + encodeURI("webcal://outwebsite.net/generated/ourcal.ics") + "'>Subscribe to iCalendar</a>";
var subGcal = "<a class='m-1 btn bg-lightdark text-dark' href='http://www.google.com/calendar/render?cid=" + encodeURI("webcal://ourwebsite.net/generated/ourcal.ics") + "'>Subscribe with Google Calendar</a>";
var subMcal = "<a class='m-1 btn bg-lightdark text-dark' href='http://calendar.live.com/calendar/calendar.asp?rru=addsubscription&url=" + encodeURI("https://ourwebsite.net/generated/ourcal.ics") + "&name=" + encodeURI("OurCalendar") + "'>Subscribe with Microsoft Calendar</a>";
_html = subIcal + "<br/>" + subGcal + "<br/>" + subMcal;
return _html;
}

Of which, the first button links directly to the file itself, the second one works and links to google, and the last one, doesn't work, but link to outlook.

Goal

The goal is to read a user's calender from our banking website backend and then parse the events, and make them available across multiple popular calendars so that the user can synchronize his payment dates and other such events seamlessly.

NOTE: Such a calendar is not in the iCal format, but to simulate this, I have written the php script and assumed an event list arrives in this format inside a text file.

{"EventName":"Car loan Payment","EventDesc":"","EventStart":"18-Nov-22 09:00","EventDuration":"PT24H"}
{"EventName":"Bernie's Anniversary ","EventDesc":"A small gathering to celebrate Bernie's 10 successful years at the company!","EventStart":"18-Nov-17 16:00","EventEnd":"18-Nov-17 18:00"}
{"EventName":"Snow day","EventDesc":"Snow all day!","EventStart":"18-Nov-15 05:00","EventDuration":"PT24H"}
.
.
.

The generated ICS (iCalendar) file is shown below:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//ZContent.net//ZapCalLib 1.0//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
BEGIN:VEVENT
SUMMARY:Car loan Payment
DTSTART:20181122T090000
DURATION:PT24H
UID:[email protected]
Description:
METHOD:PUBLISH
X-WR-CALNAME:CompanyCalendar
X-WR-TIMEZONE:(GMT-05:00) Eastern Time (US & Canada)
SEQUENCE:0
CLASS:PUBLIC
DTSTAMP:20181119T134138
LAST-MODIFIED:20181119T134138
END:VEVENT
BEGIN:VEVENT
SUMMARY:Bernie's Anniversary 
DTSTART:20181117T160000
DTEND:20181117T180000
UID:[email protected]
Description:A small gathering to celebrate Bernie's 10 successful years at 
the company!
METHOD:PUBLISH
X-WR-CALNAME:CompanyCalendar
X-WR-TIMEZONE:(GMT-05:00) Eastern Time (US & Canada)
SEQUENCE:0
CLASS:PUBLIC
DTSTAMP:20181119T134138
LAST-MODIFIED:20181119T134138
END:VEVENT
BEGIN:VEVENT
SUMMARY:Snow day
DTSTART:20181115T050000
DURATION:PT24H
UID:[email protected]
Description:Snow all day!
METHOD:PUBLISH
X-WR-CALNAME:CompanyCalendar
X-WR-TIMEZONE:(GMT-05:00) Eastern Time (US & Canada)
SEQUENCE:0
CLASS:PUBLIC
DTSTAMP:20181119T134138
LAST-MODIFIED:20181119T134138
END:VEVENT
BEGIN:VEVENT
SUMMARY:Gary's Bday
DTSTART:20181127T170000
DTEND:20181127T190000
UID:[email protected]
Description:A small celebration for Gary's Birthday 
METHOD:PUBLISH
X-WR-CALNAME:CompanyCalendar
X-WR-TIMEZONE:(GMT-05:00) Eastern Time (US & Canada)
SEQUENCE:0
CLASS:PUBLIC
DTSTAMP:20181119T134138
LAST-MODIFIED:20181119T134138
END:VEVENT
BEGIN:VEVENT
SUMMARY:Avengers Movie night
DTSTART:20181115T180000
DURATION:PT24H
UID:[email protected]
Description:Watch avengers movie for free tonight!
METHOD:PUBLISH
X-WR-CALNAME:CompanyCalendar
X-WR-TIMEZONE:(GMT-05:00) Eastern Time (US & Canada)
SEQUENCE:0
CLASS:PUBLIC
DTSTAMP:20181119T134138
LAST-MODIFIED:20181119T134138
END:VEVENT
BEGIN:VEVENT
SUMMARY:Electric Bill Payment
DTSTART:20181118T070000
DURATION:PT24H
UID:[email protected]
Description:Please make a payment of $50 towards this month's bill!
METHOD:PUBLISH
X-WR-CALNAME:CompanyCalendar
X-WR-TIMEZONE:(GMT-05:00) Eastern Time (US & Canada)
SEQUENCE:0
CLASS:PUBLIC
DTSTAMP:20181119T134138
LAST-MODIFIED:20181119T134138
END:VEVENT
BEGIN:VEVENT
SUMMARY:Gas Bill Payment
DTSTART:20181118T080000
DURATION:PT24H
UID:[email protected]
Description:Please make a payment of $150 towards the current gas bill!
METHOD:PUBLISH
X-WR-CALNAME:CompanyCalendar
X-WR-TIMEZONE:(GMT-05:00) Eastern Time (US & Canada)
SEQUENCE:0
CLASS:PUBLIC
DTSTAMP:20181119T134138
LAST-MODIFIED:20181119T134138
END:VEVENT
BEGIN:VEVENT
SUMMARY:Snow day
DTSTART:20181128T060000
DURATION:PT24H
UID:[email protected]
Description:A winter storm warning is in effect and DG will remain closed f
or the day
METHOD:PUBLISH
X-WR-CALNAME:CompanyCalendar
X-WR-TIMEZONE:(GMT-05:00) Eastern Time (US & Canada)
SEQUENCE:0
CLASS:PUBLIC
DTSTAMP:20181119T134138
LAST-MODIFIED:20181119T134138
END:VEVENT
BEGIN:VEVENT
SUMMARY:Thanksgiving Lunch
DTSTART:20181123T120000
DTEND:20181123T140000
UID:[email protected]
Description:Please gather for free food friday\, where you can enjoy turkey
  and salad!
METHOD:PUBLISH
X-WR-CALNAME:CompanyCalendar
X-WR-TIMEZONE:(GMT-05:00) Eastern Time (US & Canada)
SEQUENCE:0
CLASS:PUBLIC
DTSTAMP:20181119T134138
LAST-MODIFIED:20181119T134138
END:VEVENT
END:VCALENDAR

Challenges

  1. All day events are not properly parsed.
  2. Importing into other calendars is not working correctly.
  3. Documentation is too broad with too few examples.
  4. Library support for this is very limited.
  5. This same ics file in windows 10 calendar works fine (all events are loaded) when just opened by clicking and all the events show up. However, the timing is still off, and all day events end at 12am next day regardless of PT24H Duration, as mentioned by multiple posts previously.
  6. Popular websites like Stanza.co create their own calendar and then allow users to subscribe to it from all other calendars. This is not open source.

What I have researched is the same exact thing you can find when you use any search bar. I have visited at least 100 or more articles on multiple websites around the whole topic. This is my second attempt at getting an answer.

1

1 Answers

2
votes

There are errors. Put your ics files through the various ics validators. I do as many as I can as they don't all say the same thing. Google does not tell you what is wrong but will just reject the invalid events. Using one validator (this https://icalendar.org/validator.html) with your ics content I got:

Problem! Found 5 errors Errors

UID value is not unique, duplicate found near line # 6Reference: RFC 5545 3.8.4.7. Unique Identifier
UID value is not unique, duplicate found near line # 20Reference: RFC 5545 3.8.4.7. Unique Identifier
Missing DTSTAMP property near line # 35Reference: RFC 5545 3.6.1. Event Component
Missing UID property near line # 35Reference: RFC 5545 3.6.1. Event Component
Missing DTSTART property in VEVENT near line # 35Reference: RFC 5545 3.6.1. Event Component