Праздники в календарях или кто больше всех работает
Грядут новогодние каникулы… и самое время поговорить о праздниках. При разработке приложения с поддержкой праздничных дат встает ряд вопросов: каким способом можно получить такие данные и откуда, как их использовать и обрабатывать?
В данной статье я хочу рассказать о ресурсах, связанных с праздниками, и поделиться личным опытом их применения в популярных сервисах и программах. Варианты работы с этими сервисами я буду рассматривать на примере нашего планировщика XtraScheduler. А в конце статьи приведу небольшую статистику по праздникам для различных стран мира.
Онлайн-ресурсыСуществуют информационно-справочные ресурсы с разнообразными календарями — солнечными, лунными, календарями с различного вида праздниками, расписаниями спортивных событий и пр.
В рунете одним из таким ресурсом является "Календарь событий" (http://www.calend.ru/), где можно найти информацию о государственных, профессиональных, религиозных и других праздниках, разбитых по категориям. Все они представлены в виде ics-файлов формата iCalendar, которые можно использовать в своих приложениях.
В качестве других примеров приведу ресурсы, которые представляет Яндекс календарь: Apple.com, Mozilla.org, iCalShare.com. Они также содержат коллекции общедоступных ics-файлов.
Наш планировщик XtraScheduler может импортировать данные из формата iCalendar, поэтому вы можете использовать любые из перечисленных выше ресурсов. Для этого мы используем класс iCalendarImporter из отдельной сборки DevExpress.XtraScheduler.v10.2.iCalendarExchange.dll. В ней реализован весь необходимый функционал загрузки из ics-файла и создания объектов календаря.
Предустановленные праздникиПомимо предложенных ресурсов, Яндекс календарь также содержит предопределённые праздничные даты. На навигаторе дат и на различных видах они отмечены красным цветом и имеют подсказку с описанием. Радует наличие переносов рабочих дней — даже несмотря на то, что не всегда цвет даты в навигаторе соответствует цвету даты в самом календаре.
Так как XtraScheduler является компонентом, то хранить в нём предустановленный набор дат не имеет смыла. Это объясняется тем, что ситуация с праздниками меняется год от года и требования, предъявляемые пользователями, могут отличаться в зависимости от страны или сценария использования. Поэтому вместо того, чтобы вводить фиксированный набор праздников, мы предоставили пользователю свойство-коллекцию для этого набора дат и дали возможность самому определять список рабочих дней, праздников и «рабочих» выходных.
Ниже приведен следующий набор классов-элементов этой коллекции, который «перекрывает» все варианты использования выходных дней.
Праздники как события календаряДанный вариант подразумевает, что для каждого праздника непосредственно создаётся событие в календаре.
Вернёмся к Яндекс календарю. При первом рассмотрении я не нашёл, как добавить праздники в календарь, хотя ожидал увидеть упоминание о праздниках где-то рядом с Афишей и Телепрограммой. Зато нашёл универсальный способ добавления любых событий (включая праздники), используя импорт из ics-файла. Полученный список можно импортировать либо в новый, либо в уже существующий календарь.
Я попробовал выполнить импорт списка «Международных праздников» (http://www.calend.ru/img/export/ical-wholeworld.ics) с описанного выше ресурса. К сожалению, с импортом выбранного календаря Яндекс не смог справиться (хотя, мягко говоря, формат предложенного файла не идеален). Зато импорт с ресурсов, предложенным самим Яндексом, работает отлично.
В Google Календаре дело обстоит несколько иначе. Наряду с импортом календарей из файла, импортом по указанной по ссылке, импортом из другой учётной записи существует и ещё один вариант.
Мы сразу видим список «Другие календари» и открыв пункт меню «Посмотреть интересные календари» (кстати, интересное выбрано название меню) мы попадём в целую коллекцию разнообразных календарных событий, включая спорт, фазы луны и т.д. Одним из них является список предустановленных праздников — примерно по 30 странам.
Достаточно лишь выбрать необходимый и нажать «подписаться» — и список календарных событий будет добавлен как отдельный календарь. При этом будет добавлено событие на день и, как следствие, появится выделение соответствующей даты жирным шрифтом на навигаторе дат.
Кстати, Google с задачей импорта нашего файла «Международных праздников» справился успешно.
XtraScheduler при импорте праздников из ics-файла также создаёт отдельные события на целый день. Как можно это использовать? Достаточно включить опцию, запрещающую иметь пересекающиеся во времени события:
и в этот праздничный день невозможно будет создать любое другое мероприятие.
Праздники в десктопных приложенияхПомимо ics-файлов есть ещё один способ получить список официальных государственных праздников по странам.
Одним из источников, при наличии установленного Microsoft Office, является файл outlook.hol, который расположен в подпапках установленного продукта, например, здесь: C:\Program Files\Microsoft Office\Office12\1049\outlook.hol"
Данные в этом файле разбиты по секциям-странам и содержат фиксированный список строк, представляющих праздники на несколько лет назад и вперёд.
В версии офиса 2010 данные о праздниках представлены с 2009 до 2028 года…
Именно эти данные используются в Outlook Calendar. В параметрах календаря можно добавить праздники для указанной страны. При этом праздники будут также добавлены как физические события календаря.
Остановимся на том, как определяется строка-праздник в этом файле. Строка, хранящая информацию о празднике, состоит из его названия, даты и идентификатора календаря. Заметьте, что для ряда стран, где даты представлены не только в Григорианском календаре, необходимо выполнять преобразования дат.
Такие преобразования дат несложно сделать встроенными средствами, если вы используете .NET.
При реализации функционала праздников в XtraScheduler для того, чтобы облегчить жизнь пользователям, мы предоставили возможность загружать этот файл, хотя сами мы его не используем. Мы создали отдельный класс, загружающий эти данные и делающий необходимые операции с датами. При этом, все необходимые преобразования дат между различными календарями будут выполняться нами и не требуют написания дополнительного кода.
Количество поддерживаемых календарей для выполнения преобразований видно из кода ниже.
Аналогичный функционал праздников получили такие продукты как ASPxScheduler и DXScheduler for WPF. Как это работает в ASPxScheduler, вы можете посмотреть в нашей онлайн-демо.
Помимо загрузки из iCalendar и outlook.hol наш планировщик может загружать и сохранять коллекцию праздников в формате XML.
Где еще может понадобиться поддержка праздников в приложениях? Один из возможных сценариев — фильтрация ненужных дней при показе большого списка временнЫх данных. В качестве примера приведу продукт XtraCharts, который вслед за нашими планировщиками реализовал поддержку выходных дней и праздников для выбрасывания ненужных дат в сериях.
Немного аналитикиВ качестве бонуса приведу немного статистических данных, полученных из файла Outlook-а. Я загрузил файл outlook.hol с праздниками, отфильтровал даты по 2010 году и визуализировал результаты, при этом подсчитав их количество в году для разных стран.
Следующая диаграмма показывает распределение количества государственных праздников по странам в 2010 году:
Полный список количества праздников по странам отражен на легенде ниже:
Если не брать во внимание религиозные праздники, то нетрудно заметить, что лидирующее положение по количеству праздников занимают такие страны как Китай, Канада и Соединенные Штаты Америки.
Минимальное число праздников у Евроcоюза, Ливии, Индии, Малайзии.
Россия занимает среднее положение со значением 12.
Конечно надо понимать, что эти цифры показывают только официальные праздники и никак не отражают реальную картину общего количества выходных. Так что делать какие-либо выводы (например, кто самая «празднующая» страна, а кто — «страна-трудоголик») предоставлю вам… :-)