Изнанка электронных календарей: как работает спецификация iCalendar и как создавать .ics-файлы

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Привет, Хабр! Меня зовут Денис Басковский. Я фронтенд-разработчик в билетном сервисе Ticketland.ru (принадлежит МТС Live). В одном из пет-проектов мне понадобилось управлять календарными событиями: ставить время начала и окончания, добавлять комментарии и посылать оповещения. Обычно такая информация хранится и передается в .ics-файлах, описанных в спецификации iCalendar. Благодаря этому формату многие современные календарные приложения могут синхронизировать данные между собой.

В этой статье я расскажу об особенностях этой спецификации, приведу примеры использования .ics-файлов и поделюсь своей библиотекой на TypeScript для их генерации. Все подробности — под катом.


Что может iCalendar

Унификация работы с календарями прошла несколько этапов:

  • Первый шаг сделала в 1996 году компания Versit Consortium, которая разработала стандарт vCalendar. 

  • В 1998 году IETF опубликовал стандарт RFC 2445, основанный на опыте использования vCalendar.

  • В 2009 году на замену RFC 2445 появились RFC 5545 и его расширение iCalendar протоколом iTIP, описанным в RFC 5546.

  • В 2012 году RFC 6638 добавил поддержку планирования (scheduling) в CalDAV на основе протокола iTIP.

Из достоинств этого формата можно отметить:

  • Универсальность. Сейчас iCalendar используется всеми современными календарными приложениями и сервисами: Microsoft Outlook, Google Calendar, Apple Calendar и так далее. Он обеспечивает им совместимость и позволяет синхронизироваться. 

  • Легкость обмена данными. Синхронизация между разными приложениями происходит с помощью экспорта и импорта .ics-файлов.

  • Гибкость. iCalendar поддерживает сложные сценарии использования: повторяющиеся события, задачи с приоритетами, уведомления. 

  • Поддержка протокола CalDAV. Позволяет организовать работу с календарными данными в распределенных системах, обеспечивая синхронизацию и управление событиями между разными устройствами и приложениями через HTTP-запросы к серверу, поддерживающему CalDAV. Подробно об этом расскажу ниже. 

Нужно учитывать, что при создании сложных повторяющихся событий с большим числом исключений структура ics-файла будет усложняться, а размер файла увеличиваться.

Что входит в файл календаря

Пример .ics-файла:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//id//NONSGML v1.0//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
BEGIN:VEVENT
UID:12345678-1234-1234-1234-123456789012
DTSTART:20240816T150000Z
SUMMARY:title
DESCRIPTION:description
END:VEVENT
END:VCALENDAR

Файлы .ics используют текстовые данные и включают компоненты, каждый из которых служит для своей цели. Вот они:

  • VJOURNAL хранит записи в журнале. С его помощью можно вести личные заметки, записывать события в течение дня. 

  • VEVENT описывает события или встречи и включает дату и время начала и окончания, местоположение, информации об организаторе и участниках, он также может содержать информацию о повторениях (RRULE), статус события, категорию и пр. Применяется для создания событий в календаре, отправки и получения откликов.

  • VTODO описывает параметры задачи: срок выполнения, приоритет, текущий статус и прогресс.

  • VALARM настраивает оповещения, связанные с VEVENT или VTODO. С его помощью можно завести оповещение, настроить тип, время и регулярность уведомления.

  • VFREEBUSY используется для описания периодов свободного или занятого времени.

Пример использования

В распределенных системах клиентские приложения — например, календари на мобильных устройствах или десктопах — работают с событиями на серверах через протокол CalDAV и сохраняют полную совместимость с форматом iCalendar.

Google Calendar использует CalDAV для синхронизации с внешними клиентами, поддерживающими этот протокол. А Google Calendar API, хоть и использует собственную структуру данных для работы с событиями, поддерживает стандарт iCalendar. Так появляется возможность синхронизироваться с клиентами, которые работают только c iCalendar.

Microsoft Outlook поддерживает импорт и экспорт .ics-файлов, а это позволяет обмениваться событиями с другими календарными системами. Microsoft Exchange Server использует .ics-файлы для обмена событиями и задачами между Outlook и другими клиентами.

Как работать с .ics-файлами

У .ics-файла текстовый тип и mime-type text/calendar. В самом простом варианте его можно создать вручную в текстовом редакторе и проверить на ошибки с помощью любого стороннего валидатора, поддерживающего RFC 5545.

Другой вариант создания .ics-файлов — использовать готовые библиотеки. Для JavaScript я нашел две:

  • icalendar.js — заброшенный проект, последняя правка была десять лет назад. Функционирует только в Nodejs, требует полифилы для работы в браузере.

  • rrule.js — более живой проект, специализирующийся на генерации и управлении повторяющимися событиями (RRULE). Эта библиотека предназначена для использования как в Node.js, так и в браузерах, однако для создания полных .ics-файлов могут потребоваться дополнительные библиотеки. Размер библиотеки 687 Кб, есть зависимость пакета tslib.

В своем пет-проекте я использую стандарт RFC 5545. Так как готовые варианты библиотек меня не устроили, я реализовал создание ics-файлов в собственной библиотеке ical-browser на TypeScript. В отличие от rrule.js и icalendar.js библиотека работает в том числе и в браузерах без создания тяжелых зависимостей. У меня много планов по ее доработке — пишите в личку, если хотите помочь или нужна какая-то дополнительная функциональность.

Пример работы с ical-browser

Сначала установим пакет:

npm install ical-browser

Подключим библиотеку к своему проекту, поддерживающему ESM-модули. Работать будем с типами Event, Todo, Journal и Alarm:

import { todo as createTodo,
  event as createEvent,
  journal as createJournal,
  alarm as createAlarm,
  default as icalendar, } from 'ical-browser'

// Раньше можно было использовать любое значение, но для повышения безопасности требуется уникальное значение идентификатора, например uuidv1
const uid = 'c7614cff-3560-4a00-9152-d25cc1fe077d',

const event = createEvent({
    uid,
    location: 'Online',
    geo: [37.5739497,-85.7399606],
    summary: 'Event summary',
    description: 'Event description',
    stamp: new Date(),
    start: new Date('2024-01-01T10:10:00.611Z'),
    end: new Date('2024-01-02T10:12:00.611Z'),
    // Прикладываем документ в формате base64. В данном случае это будет пиксель в формате gif
    attach: [
      'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQEAAAAACwAAAAAAQABAAACAkQBADs=',
    ],
    organizer: 'Jane Doe',
    attendee: 'CN=John Smith:mailto:john.smith@example.com',
    url: new URL('https://example.com#event'),
})

const todo = createTodo({
    uid,
    stamp: new Date(),
    due: new Date(),
    summary: 'Task summary',
    description: 'Task description',
    priority: 1,
    status: 'CONFIRMED',
})

const journal = createJournal({
    uid,
    stamp: new Date(),
    due: new Date(),
    summary: 'Journal summary',
    description: 'Journal description',
})

const alarm = createAlarm({
    uid,
    trigger: '-PT5M',
    description: 'Reminder',
    action: 'DISPLAY',
})

// Cклеиваем данные и генерируем файл
const str = icalendar('ID’, { event, todo, journal, alarm })
const file = new File([new TextEncoder().encode(str)], 'example.ics', {
  type: 'text/calendar',
})

После запуска пробуем открыть созданный файл:

В Apple Calendar мы увидим новое событие
В Apple Calendar мы увидим новое событие

Важно учитывать, что время берется с указанием таймзоны. Поэтому в моем примере значением new Date('2024-01-01T10:10:00.611Z') для Москвы станет 13:10.

Итог

iCalendar — это гибкий и мощный стандарт для работы с календарными данными, который поддерживается большинством современных приложений и сервисов. Файлы .ics легко создаются и импортируются во все самые популярные приложения для управления временем. 

Надеюсь, моя статья помогла вам лучше понять стандарт iCalendar и то, как интегрировать его в свои проекты. Если у вас возникли вопросы или есть чем дополнить статью — пишите в комментариях.

Источник: https://habr.com/ru/companies/ru_mts/articles/837964/


Интересные статьи

Интересные статьи

Привет, Хабр! Меня зовут Анна Назаренко. Я ведущий инженер продукта МТС Маркетолог, а еще у меня много хобби. Одно из них — вязать игрушки, в том числе под заказ. Сегодня расскажу об этом подробно. За...
Команда Notion представила Sites — набор инструментов для создания полноценных веб-сайтов. Добавили функции для работы с SEO, аналитику от Google, настройку тем и шаблонов.
Игра с нуля — интересный челлендж для разработчика. Но если хотите пройти его на сложности Nightmare, можно еще и сделать собственный игровой движок, заточенный специально под проект. Подводных камней...
В том, что цены ПК, ноутбуков и других электронных устройств постепенно будут расти, сомневаться особенно не приходилось — негативных факторов слишком уж много. И цены стали постепенно увеличиваться...
Привет Хабр. Наверное многие, приобретающие часы или метеостанцию, видели на упаковке логотип Radio Controlled Clock или даже Atomic Clock. Это весьма удобно, ведь достаточно поставить часы на...