Lecture des fichiers distants de type ICalendar avec .NET


Qu’est-ce qu’un fichier de type ICalendar ?

iCalendar (aussi abrégé iCal) est un format pour les échanges de données de calendrier. Il est notamment utilisé pour le partage de calendrier par abonnement via les protocoles CalDAV et Web Calendar Access Protocol.

Il est implémenté/supporté par un grand nombre de logiciels, tels que : iCal d’Apple, Chandler, Lotus Notes, Zimbra, ScheduleWorld, SOGo, KOrganizer, Mozilla Lightning, Evolution, Windows Calendar via une extension Microsoft Outlook, ou Google Calendar, etc.

Les universités et écoles l’utilisent également pour la mise en place des emplois du temps en ligne appelés souvent Edt. Etant dans l’une de ces écoles, je suis obligé à tout moment d’aller sur le site web de l’école pour consulter mon emploi du temps. L’idée m’est venue de concevoir une application test console .NET Core qui me permettra de lire directement mon emploi sur mon ordinateur à l’aide d’une seule ligne de commande.

A la base je voulais une application mobile mais j’ai vite remarqué qu’il y existe déjà une application disponible permettant de lire les fichiers distants de type ICalendar. J’ai donc laissé mon petit projet d’appli mobile 😅 mais je tiens à partager avec vous mon projet test console .NET Core.

Structure d’un fichier de type ICalendar

Les fichiers ICalendar peuvent avoir comme extensions .ics, .ifb, .iCal, .iFBf, .icalendar.

Dans notre cas, nous essayerons de lire un fichier .ics distant(que j’ai mis sur GitHub) représentant l’emploi du temps d’une école fictive.

Voici la structure d’un fichier .ics:

Chaque évènement(ici un cours) est entouré de deux expressions clés:

  • BEGIN:VEVENT
  • END:VEVENT

Détails de quelques propriétés d’un EVENT:

  • DTSTART: La date début de l’évènement
  • DTEND: La date fin
  • SUMMARY: Le résumé de l’évènement
  • LOCATION; Le lieu où se déroulera l’évènement
  • DESCRIPTION: La description

Les valeurs de ces propriétés sont à bien vérifier afin d’adapter l’algorithme de lecture des données. Nous pouvons faire face à des valeurs qui peuvent nécessiter l’application des expressions régulières par exemple.

Ayant pris connaissance des valeurs possibles des propriétés mon fichier .ics ainsi que ces formats(Image précédente), je m’en vais créer un projet .NET Core Console.

Création du projet .NET Core Console

J’utiliserai dotnet cli pour la création du projet, l’ajout des NuGet Package, le buid ainsi que le run.

Comme vous pouvez le remarquer, j’utilise .NET 5.0 nouvellement sorti.

Ajout du NuGet Package ICal.Net

Ical.Net est une libraire qui nous permettra de lire le contenu des fichiers calendrier.

Ajout d’une classe Cours

using Ical.Net.CalendarComponents;
using System;

namespace ICSFileReader
{
    public class Cours
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public string Location { get; set; }
        public DateTime DateStart { get; set; }
        public DateTime DateEnd { get; set; }

        // Constructor that convert CalendarEvent to Cours
        public Cours(CalendarEvent evt)
        {
            Name = evt.Summary.Trim();
            Description = evt.Description.Trim();
            Location = evt.Location.Trim();
            DateStart =  evt.DtStart.AsSystemLocal;
            DateEnd = evt.DtEnd.AsSystemLocal;
        }

        public override string ToString() =>
            $"Cours: {Name}{Environment.NewLine}" +
            $"Description: {Description}{Environment.NewLine}" +
            $"Location: {Location}{Environment.NewLine}" +
            $"Start Date: {DateStart}{Environment.NewLine}" +
            $"End Date: {DateEnd}";
    }   
}

Les propriétés de ma classe Cours ne feront rien d’autre que récupérer les valeurs des éléments de chaque évènement du fichier Calendrier.

CalendarEvent est une classe de ICal.Net qui représente un EVENT du fichier .ics que j’ai détaillé un peu plus haut.

Vous pouvez remarquer que pour la date début et date fin, j’utilise AsSystemLocal au lieu d’affecter directement la valeur lue depuis CalendarEvent. Ceci permet au développeur de se libérer de la gestion des fuseaux horaires sur chaque machine utilisant notre application. Chaque utilisateur verra alors la date début et fin des cours selon les configurations horaires de sa machine.

L’accès au fichier distant

// Access to the remote .ics file
var olineSchedule = WebRequest.Create("https://gist.githubusercontent.com/egbakou/2f9ea8129fcfb58b80eca78f1a6d1387/raw/a82a9133e2ee5ecce8a6dd19c5d4aad172e5ccbc/cours.ics");
var response = await olineSchedule.GetResponseAsync().ConfigureAwait(false);
var stream = response.GetResponseStream();

Le chargement du fichier

var calendar = Calendar.Load(stream);

// Load the .ics file localy
// var calendar = Calendar.Load(File.OpenRead("cours.ics"));

Récupération des cours et tri par ordre croissant selon la date de début

// Get all events
var events = calendar.Events;

// Order events by Start Date
var events_sorted = events.OrderBy(e => e.DtStart.AsSystemLocal);

Affichage des cours

 foreach (var evt in events_sorted)
{
    // C# Target-typed new expressions
    Cours cours = new(evt);
    Console.WriteLine(cours);
}

Code complet du fichier Main.cs

using Ical.Net;
using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace ICSFileReader
{
    class Program
    {
        static async Task Main()
        {
            // Read Online Calendar 
            var olineSchedule = WebRequest.Create("https://gist.githubusercontent.com/egbakou/2f9ea8129fcfb58b80eca78f1a6d1387/raw/a82a9133e2ee5ecce8a6dd19c5d4aad172e5ccbc/cours.ics");
            var response = await olineSchedule.GetResponseAsync().ConfigureAwait(false);
            var stream = response.GetResponseStream();
            
            var calendar = Calendar.Load(stream);

            // Load the .ics file localy
            // var calendar = Calendar.Load(File.OpenRead("cours.ics"));

            // Get all events
            var events = calendar.Events;

            // Order events by Start Date
            var events_sorted = events.OrderBy(e => e.DtStart.AsSystemLocal);

            foreach (var evt in events_sorted)
            {
                // C# Target-typed new expressions
                Cours cours = new(evt);
                Console.WriteLine(cours);
            }
        }

    }
}

Build du projet

Pas d’erreurs, il ne reste qu’à lancer la commande run.

Run du projet

👉 https://github.com/egbakou/ICSFileReader le lien vers le projet complet sur GitHub.

N’hésitez pas à commenter cet article pour vos questions et remarques.


Commentaires



Mes Badges


Categories

Nouveaux posts