Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iCal format for Google Calendar / Yahoo calendar not working

I've created calendar file (.ics) output from my application for the purpose of consumption within a Calendar app such as Google Calendar. I've ran the below file through a validator, but it appears that neither Google nor Yahoo Calendars want to play ball. My Local Mac Calendar client works 100%. Can anyone see anything obvious about the file below that would potentially choke within Google Calendar? Or any additional fields they need? I get a 500 error back from Yahoo calendar too. Tearing hair out at this point.

I've tried with and without timezone information, and it doesn't seem to make much difference.

Header output

        header('Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); 
        header('Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); 
        header('Cache-Control: no-store, no-cache, must-revalidate' );
        header('Cache-Control: post-check=0, pre-check=0', false );
        header('Pragma: no-cache' );
        header('Content-type: text/calendar;');
        header('Content-Disposition: inline; filename="calendar.ics"');
        header("Content-Description: File Transfer");
        header("Content-Transfer-Encoding: binary");
        header("Content-Length: " . strlen($generated));

UTC times or TZID I've experimented with and doesn't seem to make a difference. If anyone has a really simple example of a URL of .ics events that seems to work "cross calendar" would love to see it. Alternatively if someone can provide some decent libraries for this purpose that aren't a pain to integrate into a CakePHP project, that would suffice.

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//MS//NONSGML//EN
X-WR-CALNAME:Holidays
CALSCALE:GREGORIAN
METHOD:PUBLISH
BEGIN:VEVENT
UID:1075
DTSTART;TZID=Europe/London:20150114T080000
DTEND;TZID=Europe/London:20150114T170000
DTSTAMP:20150114T080000Z
CREATED:20151019T211433Z
DESCRIPTION:Stat Holiday (1.0 days)
LAST-MODIFIED:20150114T080000Z
LOCATION:
SUMMARY: Statutory Day
SEQUENCE:0
STATUS:CONFIRMED
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
UID:1076
DTSTART;TZID=Europe/London:20150116T080000
DTEND;TZID=Europe/London:20150116T170000
DTSTAMP:20150116T080000Z
CREATED:20151019T211433Z
DESCRIPTION:Stat Holiday (1.0 days)
LAST-MODIFIED:20150116T080000Z
LOCATION:
SUMMARY: Statutory Day
SEQUENCE:0
STATUS:CONFIRMED
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
UID:1079
DTSTART;TZID=Europe/London:20151020T123000
DTEND;TZID=Europe/London:20151020T170000
DTSTAMP:20151020T123000Z
CREATED:20151019T211433Z
DESCRIPTION:Holiday Request (3.0 days) test
LAST-MODIFIED:20151020T123000Z
LOCATION:
SUMMARY:admin Leave
SEQUENCE:0
STATUS:CONFIRMED
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
UID:1080
DTSTART;TZID=Europe/London:20151021T080000
DTEND;TZID=Europe/London:20151021T123000
DTSTAMP:20151021T080000Z
CREATED:20151019T211433Z
DESCRIPTION:Holiday (3.0 days) test
LAST-MODIFIED:20151021T080000Z
LOCATION:
SUMMARY:admin Leave
SEQUENCE:0
STATUS:CONFIRMED
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
UID:1081
DTSTART;TZID=Europe/London:20151022T080000
DTEND;TZID=Europe/London:20151022T170000
DTSTAMP:20151022T080000Z
CREATED:20151019T211433Z
DESCRIPTION:Holiday Request (3.0 days) test
LAST-MODIFIED:20151022T080000Z
LOCATION:
SUMMARY:admin Leave
SEQUENCE:0
STATUS:CONFIRMED
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
UID:1082
DTSTART;TZID=Europe/London:20151023T080000
DTEND;TZID=Europe/London:20151023T170000
DTSTAMP:20151023T080000Z
CREATED:20151019T211433Z
DESCRIPTION:Holiday Request (3.0 days) test
LAST-MODIFIED:20151023T080000Z
LOCATION:
SUMMARY:admin Leave
SEQUENCE:0
STATUS:CONFIRMED
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
like image 924
Squiggs. Avatar asked Oct 19 '15 20:10

Squiggs.


People also ask

Does Yahoo work with Google Calendar?

It is not possible to directly add your Yahoo calendar to the Calendar app. Instead you can sync your Yahoo calendar with your Google calendar, then sync your Google calendar with the Calendar app.

Why isn't my iCal syncing with Google Calendar?

Ensure You're Properly Adding Events To sync with Google account, you need to set up the account in iCal by visiting the "Calendar" menu, selecting "Preferences" and then "Accounts." If you don't see your Google account listed in the box, it isn't set up to sync.

How do I get my Yahoo calendar on iCal?

Go to your Yahoo calendars, select the down-arrow next to your calendar's name, and choose Edit Calendar. Select Get shareable link and copy the URL under the To view in a browser (HTML) section to share a web link. Copy the URL under the To import into a Calendar app (ICS) section to share a link to an ICS file.

How do I sync my Yahoo calendar with my Google Calendar?

Sign in to the Google Calendar website. Click the drop-down arrow next to "Other Calendars," and then click "Add by URL." Click in the "URL" field, press "Ctrl-V" to paste your Yahoo iCal address, and then click the "Add Calendar" button. It may take a few minutes to import your calendar.


2 Answers

Using a combination of answers at SO (Google Calendar errors on importing .ics file) and some source code from https://gist.github.com/jakebellacera/635416

My working code tested in several tools is:

<?php

//test
//
$summary = "test";
$datestart=time();
$dateend = $datestart + 3600;
$address = "Amsterdam";
$description = "testing ical format";
$filename = "test.ics";

// Variables used in this script:
//   $summary     - text title of the event
//   $datestart   - the starting date (in seconds since unix epoch)
//   $dateend     - the ending date (in seconds since unix epoch)
//   $address     - the event's address
//   $uri         - the URL of the event (add http://)
//   $description - text description of the event
//   $filename    - the name of this file for saving (e.g. my-event-name.ics)
//
// Notes:
//  - the UID should be unique to the event, so in this case I'm just using
//    uniqid to create a uid, but you could do whatever you'd like.
//
//  - iCal requires a date format of "yyyymmddThhiissZ". The "T" and "Z"
//    characters are not placeholders, just plain ol' characters. The "T"
//    character acts as a delimeter between the date (yyyymmdd) and the time
//    (hhiiss), and the "Z" states that the date is in UTC time. Note that if
//    you don't want to use UTC time, you must prepend your date-time values
//    with a TZID property. See RFC 5545 section 3.3.5
//
//  - The Content-Disposition: attachment; header tells the browser to save/open
//    the file. The filename param sets the name of the file, so you could set
//    it as "my-event-name.ics" or something similar.
//
//  - Read up on RFC 5545, the iCalendar specification. There is a lot of helpful
//    info in there, such as formatting rules. There are also many more options
//    to set, including alarms, invitees, busy status, etc.
//
//      https://www.ietf.org/rfc/rfc5545.txt
// 1. Set the correct headers for this file
header('Content-type: text/calendar; charset=utf-8');
header("Content-Disposition:inline;filename=".$filename);
// 2. Define helper functions
// Converts a unix timestamp to an ics-friendly format
// NOTE: "Z" means that this timestamp is a UTC timestamp. If you need
// to set a locale, remove the "\Z" and modify DTEND, DTSTAMP and DTSTART
// with TZID properties (see RFC 5545 section 3.3.5 for info)
//
// Also note that we are using "H" instead of "g" because iCalendar's Time format
// requires 24-hour time (see RFC 5545 section 3.3.12 for info).
function dateToCal($timestamp) {
  return date('Ymd\THis\Z', $timestamp);
}
// Escapes a string of characters
function escapeString($string) {
  return preg_replace('/([\,;])/','\\\$1', $string);
}
// 3. Echo out the ics file's contents
$iCal="BEGIN:VCALENDAR\r
VERSION:2.0\r
PRODID:-//hacksw/handcal//NONSGML v1.0//EN\r
CALSCALE:GREGORIAN\r
BEGIN:VEVENT\r
DTSTAMP:".dateToCal(time())."\r
DTSTART:".dateToCal($datestart)."\r
DTEND:".dateToCal($dateend)."\r
UID:".uniqid()."\r
LOCATION:".escapeString($address)."\r
DESCRIPTION:".escapeString($description)."\r
SUMMARY:".escapeString($summary)."\r
END:VEVENT\r
END:VCALENDAR";
file_put_contents($filename,$iCal);
print file_get_contents($filename);
unlink($filename);
exit;
?>

It seems important that the line endings are correct (so \r\n).

like image 61
Bas van Stein Avatar answered Oct 22 '22 00:10

Bas van Stein


Your file is correct, I have uploaded it to google calendars myself, so it should work, however if you aren't stopping the script after the file echo, for example:

    //somewhere else in the script
    echo "this will break the file";
    header('Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); 
    header('Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); 
    header('Cache-Control: no-store, no-cache, must-revalidate' );
    header('Cache-Control: post-check=0, pre-check=0', false );
    header('Pragma: no-cache' );
    header('Content-type: text/calendar;');
    header('Content-Disposition: inline; filename="calendar.ics"');
    header("Content-Description: File Transfer");
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: " . strlen($generated));
    echo $generated;
    exit;//or return 200 or whatever
    echo "this could break the file except there is an exit;";//for example.

You could be in essence sending a malformed file.

like image 22
Paul Stanley Avatar answered Oct 21 '22 23:10

Paul Stanley