dcblogdev / dcblogcomments

2 stars 0 forks source link

reading-events-from-an-ical-calendar-using-php #3

Open utterances-bot opened 4 years ago

utterances-bot commented 4 years ago

Reading events from an iCal Calendar using PHP - DC Blog | Development Tutorials

Reading event/calender information from iCal can be very useful this tutorial will show you how t...

https://dcblog.dev/reading-events-from-an-ical-calendar-using-php

philbert99 commented 4 years ago

Thank you for making this. It works well, but I am having trouble getting this to sort by date starting with the next event. I also need to limit the number of events displayed. Any help would be appreciated. Thanks.

dcblogdev commented 4 years ago

Okay since the $events is an array you can use a usort function on the array. This will sort the entries into date order:

$events = iCalDecoder("test.ics");
usort($events, function($a, $b) {
    return $a['DTSTART'] - $b['DTSTART'];
});

To limit the entries you can use a counter $i and break when it reaches a certain number, Like this:

//set value to 0
$i = 0;

//loop over $events
foreach($events as $event){

    //only display the first 5
    if($i >= 5) {
        break;
    }

    $now = date('Y-m-d H:i:s');//current date and time
    $eventdate = date('Y-m-d H:i:s', strtotime($event['DTSTART']));//user friendly date

    if($eventdate > $now){
        echo "
            <div class='eventHolder'>
                <div class='eventDate'>$eventdate</div>
                <div class='eventTitle'>".$event['SUMMARY']."</div>
            </div>";
    }

    //increment $i by 1
    $i++;
}
philbert99 commented 4 years ago

Thank you so much for responding. When I try the first part, it works but gives me errors first. I tried with another calendar, and didn't get the errors, so there may be something weird with my calendar. When I add on the second part, I end up with no results returning regardless of the calendar I use. Here is the calendar that gives me errors: https://my.jalc.edu/ICS/api/ical/b6ad4883-720b-4f4b-ac20-f861b3094252 Here is the code I am using with the calendar that doesn't give errors:

<p><strong>php get events from ical url</strong></p>
<ul>
<?php
ini_set('display_errors', 1);
function iCalDecoder($file) {
        $ical = file_get_contents($file);
        preg_match_all('/(BEGIN:VEVENT.*?END:VEVENT)/si', $ical, $result, PREG_PATTERN_ORDER);
        for ($i = 0; $i < count($result[0]); $i++) {
            $tmpbyline = explode("\r\n", $result[0][$i]);

            foreach ($tmpbyline as $item) {
                $tmpholderarray = explode(":",$item);
                if (count($tmpholderarray) >1) {
                    $majorarray[$tmpholderarray[0]] = $tmpholderarray[1];
                }
            }

            if (preg_match('/DESCRIPTION:(.*)END:VEVENT/si', $result[0][$i], $regs)) {
                $majorarray['DESCRIPTION'] = str_replace("  ", " ", str_replace("\r\n", "", $regs[1]));
            }
            $icalarray[] = $majorarray;
            unset($majorarray);

        }

        return $icalarray;
}

$events = iCalDecoder("https://www.calendarlabs.com/ical-calendar/ics/76/US_Holidays.ics");
/* Sorting by Date */
usort($events, function($a, $b) {
    return $a['DTSTART'] - $b['DTSTART'];
});
/* End Sorting by Date */
//set value to 0
$i = 0;

//loop over $events
foreach($events as $event){

    //only display the first 5
    if($i >= 5) {
        break;
    }
    $date = $event['DTSTART'];//get date from ical
    $date = str_replace('T', '', $date);//remove T
    $date = str_replace('Z', '', $date);//remove Z
    $d    = date('d', strtotime($date));//get date day
    $m    = date('m', strtotime($date));//get date month
    $y    = date('Y', strtotime($date));//get date year
    $now = date('Y-m-d G:i:s');//current date and time
    $eventdate = date('Y-m-d G:i:s', strtotime($date));//user friendly date
    $eventdateb = date('F j, Y', strtotime($date));//user friendly date

    if($eventdate > $now){
        echo "<li><a href='https://my.jalc.edu/ICS/Portal_Homepage.jnz?portlet=Calendar#/event/".$event['UID']."'>".$event['SUMMARY']." - ".$eventdateb."</a></li>";

    }

    //increment $i by 1
    $i++;

}

?>
</ul>
dcblogdev commented 4 years ago

okay, it actually is working but the dates are all passed dates and there is an if statement to only get future dates you can remove that if completely and show all the entries regardless of the date.

I've also updated the example to show up to 50 results, just to show that it can be changed. Also I've simplified the dates sections.

$events = iCalDecoder("https://www.calendarlabs.com/ical-calendar/ics/76/US_Holidays.ics");

/* Sorting by Date */
usort($events, function($a, $b) {
    return $a['DTSTART'] - $b['DTSTART'];
});
/* End Sorting by Date */

//set value to 0
$i = 0;

//loop over $events
foreach($events as $event){

    //only display the first 50
    if($i >= 50) {
        break;
    }

    $eventdate = date('Y-m-d G:i:s', strtotime($event['DTSTART']));//user friendly date
    $eventdateb = date('F j, Y', strtotime($event['DTSTART']));//user friendly date

    echo "<li><a href='https://my.jalc.edu/ICS/Portal_Homepage.jnz?portlet=Calendar#/event/".$event['UID']."'>".$event['SUMMARY']." - ".$eventdateb."</a></li>";

    //increment $i by 1
    $i++;
}
philbert99 commented 4 years ago

It looks like it did some weird stuff with showing my code, so I will try to post that code again. There will be an opening and closing unordered list before and after the php code.

ini_set('display_errors', 1);
function iCalDecoder($file) {
        $ical = file_get_contents($file);
        preg_match_all('/(BEGIN:VEVENT.*?END:VEVENT)/si', $ical, $result, PREG_PATTERN_ORDER);
        for ($i = 0; $i < count($result[0]); $i++) {
            $tmpbyline = explode("\r\n", $result[0][$i]);

            foreach ($tmpbyline as $item) {
                $tmpholderarray = explode(":",$item);
                if (count($tmpholderarray) >1) {
                    $majorarray[$tmpholderarray[0]] = $tmpholderarray[1];
                }
            }

            if (preg_match('/DESCRIPTION:(.*)END:VEVENT/si', $result[0][$i], $regs)) {
                $majorarray['DESCRIPTION'] = str_replace("  ", " ", str_replace("\r\n", "", $regs[1]));
            }
            $icalarray[] = $majorarray;
            unset($majorarray);

        }

        return $icalarray;
}

$events = iCalDecoder("https://www.calendarlabs.com/ical-calendar/ics/76/US_Holidays.ics");
/* Sorting by Date */
usort($events, function($a, $b) {
    return $a['DTSTART'] - $b['DTSTART'];
});
/* End Sorting by Date */
//set value to 0
$i = 0;

//loop over $events
foreach($events as $event){

    //only display the first 5
    if($i >= 5) {
        break;
    }
    $date = $event['DTSTART'];//get date from ical
    $date = str_replace('T', '', $date);//remove T
    $date = str_replace('Z', '', $date);//remove Z
    $d    = date('d', strtotime($date));//get date day
    $m    = date('m', strtotime($date));//get date month
    $y    = date('Y', strtotime($date));//get date year
    $now = date('Y-m-d G:i:s');//current date and time
    $eventdate = date('Y-m-d G:i:s', strtotime($date));//user friendly date
    $eventdateb = date('F j, Y', strtotime($date));//user friendly date

    if($eventdate > $now){
        echo "<li><a href='https://my.jalc.edu/ICS/Portal_Homepage.jnz?portlet=Calendar#/event/".$event['UID']."'>".$event['SUMMARY']." - ".$eventdateb."</a></li>";

    }

    //increment $i by 1
    $i++;

}
dcblogdev commented 4 years ago

your code appears to be fine that I can see, although the latest post is essentially the same as an earlier one.

All you need inside the foreach is:

//only display the first 50
if($i >= 50) {
    break;
}

$eventdate = date('Y-m-d G:i:s', strtotime($event['DTSTART']));//user friendly date
$eventdateb = date('F j, Y', strtotime($event['DTSTART']));//user friendly date

echo "<li><a href='https://my.jalc.edu/ICS/Portal_Homepage.jnz?portlet=Calendar#/event/".$event['UID']."'>".$event['SUMMARY']." - ".$eventdateb."</a></li>";

//increment $i by 1
$i++;
philbert99 commented 4 years ago

Sorry for the confusion, I was only using that calendar because it didn't give errors, but I see now that it was giving past dates, which is why it came up blank. I still need the other values and the if statement for what I am wanting to accomplish. It is working now with my calendar, I just don't know why those errors come up. Here is my code with the calendar if you want to try it. If not that is fine too. Thank you for all your help.

ini_set('display_errors', 1);
function iCalDecoder($file) {
        $ical = file_get_contents($file);
        preg_match_all('/(BEGIN:VEVENT.*?END:VEVENT)/si', $ical, $result, PREG_PATTERN_ORDER);
        for ($i = 0; $i < count($result[0]); $i++) {
            $tmpbyline = explode("\r\n", $result[0][$i]);

            foreach ($tmpbyline as $item) {
                $tmpholderarray = explode(":",$item);
                if (count($tmpholderarray) >1) {
                    $majorarray[$tmpholderarray[0]] = $tmpholderarray[1];
                }
            }

            if (preg_match('/DESCRIPTION:(.*)END:VEVENT/si', $result[0][$i], $regs)) {
                $majorarray['DESCRIPTION'] = str_replace("  ", " ", str_replace("\r\n", "", $regs[1]));
            }
            $icalarray[] = $majorarray;
            unset($majorarray);

        }

        return $icalarray;
}

$events = iCalDecoder("https://my.jalc.edu/ICS/api/ical/b6ad4883-720b-4f4b-ac20-f861b3094252");
/* Sorting by Date */
usort($events, function($a, $b) {
    return $a['DTSTART'] - $b['DTSTART'];
});
/* End Sorting by Date */
//set value to 0
$i = 0;

//loop over $events
foreach($events as $event){

 //only display the first 50
if($i >= 3) {
    break;
}
    $date = $event['DTSTART'];//get date from ical
    $date = str_replace('T', '', $date);//remove T
    $date = str_replace('Z', '', $date);//remove Z
    $d    = date('d', strtotime($date));//get date day
    $m    = date('m', strtotime($date));//get date month
    $y    = date('Y', strtotime($date));//get date year
    $now = date('Y-m-d G:i:s');//current date and time
    $eventdate = date('Y-m-d G:i:s', strtotime($event['DTSTART']));//user friendly date
    $eventdateb = date('F j, Y', strtotime($event['DTSTART']));//user friendly date

    if($eventdate > $now){
echo "<li><a href='https://my.jalc.edu/ICS/Portal_Homepage.jnz?portlet=Calendar#/event/".$event['UID']."'>".$event['SUMMARY']." - ".$eventdateb."</a></li>";

//increment $i by 1
$i++;

    }
}
dcblogdev commented 4 years ago

it's the data it appears to have some malformed entried like [DTSTART;VALUE=DATE] => 20201207 instead of [DTSTART] => 20201207

they can be ignored by check for if (isset($event["DTSTART"])) {

then your code becomes:

ini_set('display_errors', 1);
function iCalDecoder($file) {
        $ical = file_get_contents($file);
        preg_match_all('/(BEGIN:VEVENT.*?END:VEVENT)/si', $ical, $result, PREG_PATTERN_ORDER);
        for ($i = 0; $i < count($result[0]); $i++) {
            $tmpbyline = explode("\r\n", $result[0][$i]);

            foreach ($tmpbyline as $item) {
                $tmpholderarray = explode(":",$item);
                if (count($tmpholderarray) >1) {
                    $majorarray[$tmpholderarray[0]] = $tmpholderarray[1];
                }
            }

            if (preg_match('/DESCRIPTION:(.*)END:VEVENT/si', $result[0][$i], $regs)) {
                $majorarray['DESCRIPTION'] = str_replace("  ", " ", str_replace("\r\n", "", $regs[1]));
            }
            $icalarray[] = $majorarray;
            unset($majorarray);
        }

        return $icalarray;
}

$events = iCalDecoder("https://my.jalc.edu/ICS/api/ical/b6ad4883-720b-4f4b-ac20-f861b3094252");

/* Sorting by Date */
usort($events, function($a, $b) {

    if (isset($a["DTSTART"]) && isset($b["DTSTART"])) {
        return strtotime($a["DTSTART"]) - strtotime($b["DTSTART"]);
    }
});
/* End Sorting by Date */
//set value to 0
$i = 0;

//loop over $events
foreach($events as $event) {

    //only display the first 50
    if ($i >= 3) {
        break;
    }

    if (isset($event["DTSTART"])) {

        $date = $event['DTSTART'];//get date from ical
        $date = str_replace('T', '', $date);//remove T
        $date = str_replace('Z', '', $date);//remove Z
        $d    = date('d', strtotime($date));//get date day
        $m    = date('m', strtotime($date));//get date month
        $y    = date('Y', strtotime($date));//get date year
        $now = date('Y-m-d G:i:s');//current date and time
        $eventdate = date('Y-m-d G:i:s', strtotime($event['DTSTART']));//user friendly date
        $eventdateb = date('F j, Y', strtotime($event['DTSTART']));//user friendly date

        if ($eventdate > $now) {
            echo "<li><a href='https://my.jalc.edu/ICS/Portal_Homepage.jnz?portlet=Calendar#/event/".$event['UID']."'>".$event['SUMMARY']." - ".$eventdateb."</a></li>";

            //increment $i by 1
            $i++;
        }
    }
}
philbert99 commented 4 years ago

Okay, thanks again for this great script, and your help with it.

philbert99 commented 4 years ago

Two more things I noticed after testing the latest version out. The ordering by date seems to not be working now, you can see it if you set it to a higher number such as

if ($i >= 10)

It also won't show events marked as "All day". I think this was always the case and not just with the latest version. If you don't have time to work on this, I understand.

philbert99 commented 4 years ago

I figured out why my ordering wasn't working and how to include "All day" events in the results. Thanks again for this script.

monza258 commented 4 years ago

Hi @all,

My Calendar Doesn't Show. Can anyone help me pls.

https://calendar.google.com/calendar/ical/rfo9ptv4dnjvld8sgls7lk6fgo%40group.calendar.google.com/public/basic.ics

dcblogdev commented 4 years ago

I've work it working using this code:

//read events
$events = iCalDecoder("basic.ics");

//sort events into date order
usort($events, function ($a, $b) {

    if (isset($a["DTSTAMP"]) && isset($b["DTSTAMP"])) {
        return strtotime($a["DTSTAMP"]) - strtotime($b["DTSTAMP"]);
    }

});

foreach ($events as $event) {

    $eventdate = date('Y-m-d H:i:s', strtotime($event['DTSTAMP']));

    echo "
        <div class='eventHolder'>
            <div class='eventDate'>$eventdate</div>
            <div class='eventTitle'>" . $event['SUMMARY'] . "</div>
        </div>
    ";

}
monza258 commented 4 years ago

Hi @dcblogdev, I have tried and changed that shows the upcoming events for next 2 events but it doesn't show. I want that I can see the upcoming events in next two days. This ical is my Recycle Cal for this year.

$events = iCalDecoder("https://calendar.google.com/calendar/ical/rfo9ptv4dnjvld8sgls7lk6fgo%40group.calendar.google.com/public/basic.ics");

//* Sorting by Date */
usort($events, function ($a, $b) {

    if (isset($a["DTSTAMP"]) && isset($b["DTSTAMP"])) {
        return strtotime($a["DTSTAMP"]) - strtotime($b["DTSTAMP"]);
    }

});
/* End Sorting by Date */
//set value to 0
$i = 0;

//loop over $events
foreach($events as $event){

    //only display the first 5
    if($i >= 2) {
        break;
    }
    $date = $event['DTSTAMP'];//get date from ical
    $date = str_replace('T', '', $date);//remove T
    $date = str_replace('Z', '', $date);//remove Z
    $d    = date('d', strtotime($date));//get date day
    $m    = date('m', strtotime($date));//get date month
    $y   = date('Y', strtotime($date));//get date year
    $now = date("Y-m-d H:i:s");//current date and time
    $eventdate = date('Y-m-d H:i:s', strtotime($event['DTSTAMP']));

       if($eventdate > $now){ 
echo "<div class='wrapper-item'>";            
echo "<div class='message-title message-img'>$eventdate</div>";
echo "<div class='message-text'>".$event['SUMMARY']."</div>";
echo "</div>";

            //increment $i by 1
            $i++;
        }
    }

I hope you will help pls.

dcblogdev commented 4 years ago

give this a try:

$events = iCalDecoder("https://calendar.google.com/calendar/ical/rfo9ptv4dnjvld8sgls7lk6fgo%40group.calendar.google.com/public/basic.ics");

//* Sorting by Date */
usort($events, function ($a, $b) {

    if (isset($a["DTSTART;VALUE=DATE"]) && isset($b["DTSTART;VALUE=DATE"])) {
        return strtotime($a["DTSTART;VALUE=DATE"]) - strtotime($b["DTSTART;VALUE=DATE"]);
    }
});
/* End Sorting by Date */

//set value to 0
$i = 0;

//loop over $events
foreach ($events as $event) {

    //only display the first 5
    if ($i >= 2) {
        break;
    }

    $now = date("Y-m-d H:i:s"); //current date and time
    $eventdate = date('Y-m-d H:i:s', strtotime($event['DTSTART;VALUE=DATE']));

    if ($eventdate > $now) {
        echo "<div class='wrapper-item'>";
        echo "<div class='message-title message-img'>$eventdate</div>";
        echo "<div class='message-text'>" . $event['SUMMARY'] . "</div>";
        echo "</div>";

        //increment $i by 1
        $i++;
    }
}
monza258 commented 4 years ago

Thank you so much @dcblogdev

Now that works fine. Is it possible to show the Weekdays in German? This is really the last thing i ask. :-)

dcblogdev commented 4 years ago

I'm not sure what you mean, can you show me an example?

monza258 commented 4 years ago

When I change the eventdate to following:

$eventdate = date('l-d-m-Y', strtotime($event3['DTSTART;VALUE=DATE']));

I have add the l to show the Day of the event. But that shows in englisch. My Question is: Is it possible to show German format for Days.

dcblogdev commented 4 years ago

I see, you could try and set the locale:

setlocale(LC_TIME, 'de_DE', 'deu_deu');

https://www.php.net/manual/de/function.setlocale.php#refsect1-function.setlocale-examples

monza258 commented 4 years ago

I see, you could try and set the locale:

setlocale(LC_TIME, 'de_DE', 'deu_deu');

https://www.php.net/manual/de/function.setlocale.php#refsect1-function.setlocale-examples

@dcblogdev Unfortunately that does not work. Or I'm too stupid.

akanshutambi811 commented 3 years ago

Hi !

akanshutambi811 commented 3 years ago

I want to get last modified calendar date from google calendar ical address: (For Ex: https://calendar.google.com/calendar/ical/doirgjbngql1cims5k5su1q1uo%40group.calendar.google.com/public/basic.ics)

Is it possible in PHP by file url?

NH-Networks commented 3 years ago

you can use the following for (Multipule day events) DTSTART;VALUE=DATE events and for (Single day events with time windows) DTSTART events

//sort events into date order
usort($events, function($a, $b) {

    if (isset($a["DTSTART"]) && isset($b["DTSTART"])) {
        return strtotime($a["DTSTART"]) - strtotime($b["DTSTART"]);

    } elseif (isset($a["DTSTART;VALUE=DATE"]) && isset($b["DTSTART;VALUE=DATE"])) {
        return strtotime($a["DTSTART;VALUE=DATE"]) - strtotime($b["DTSTART;VALUE=DATE"]);

    }
});

foreach($events as $event){
    $now = date('Y-m-d');//current date and time
    if (isset($event["DTSTART"])) {
        $eventdate = date('Y-m-d', strtotime($event['DTSTART']));

    } elseif (isset($event["DTSTART;VALUE=DATE"])) {
        $eventdate = date('Y-m-d', strtotime($event['DTSTART;VALUE=DATE']));
    }
alinakis commented 1 year ago

Can you please modify the above code to show a day by day event and not just start and end? thank you.