Как стать автором
Обновить
0

Праздники в календарях или кто больше всех работает

Время на прочтение6 мин
Количество просмотров19K

Грядут новогодние каникулы… и самое время поговорить о праздниках. При разработке приложения с поддержкой праздничных дат встает ряд вопросов: каким способом можно получить такие данные и откуда, как их использовать и обрабатывать?


В данной статье я хочу рассказать о ресурсах, связанных с праздниками, и поделиться личным опытом их применения в популярных сервисах и программах. Варианты работы с этими сервисами я буду рассматривать на примере нашего планировщика 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 является компонентом, то хранить в нём предустановленный набор дат не имеет смыла. Это объясняется тем, что ситуация с праздниками меняется год от года и требования, предъявляемые пользователями, могут отличаться в зависимости от страны или сценария использования. Поэтому вместо того, чтобы вводить фиксированный набор праздников, мы предоставили пользователю свойство-коллекцию для этого набора дат и дали возможность самому определять список рабочих дней, праздников и «рабочих» выходных.
public WorkDaysCollection WorkDays { get {... } }

Ниже приведен следующий набор классов-элементов этой коллекции, который «перекрывает» все варианты использования выходных дней.
public abstract class WorkDay : ICloneable {
    public abstract bool IsWorkDay(DateTime date);
}
public class WeekDaysWorkDay : WorkDay {
    public WeekDays WeekDays {get { ...} }
}
public abstract class KnownDateDay : WorkDay {
    public string DisplayName { get { ... } set { ... } }
    public DateTime Date { get { ... } }
}
public class Holiday : KnownDateDay {
    public string Location { get { ...} set { ... } }
}
public class ExactWorkDay : KnownDateDay { 
}

Праздники как события календаря


Данный вариант подразумевает, что для каждого праздника непосредственно создаётся событие в календаре.

Вернёмся к Яндекс календарю. При первом рассмотрении я не нашёл, как добавить праздники в календарь, хотя ожидал увидеть упоминание о праздниках где-то рядом с Афишей и Телепрограммой. Зато нашёл универсальный способ добавления любых событий (включая праздники), используя импорт из ics-файла. Полученный список можно импортировать либо в новый, либо в уже существующий календарь.

Я попробовал выполнить импорт списка «Международных праздников» (http://www.calend.ru/img/export/ical-wholeworld.ics) с описанного выше ресурса.
К сожалению, с импортом выбранного календаря Яндекс не смог справиться (хотя, мягко говоря, формат предложенного файла не идеален). Зато импорт с ресурсов, предложенным самим Яндексом, работает отлично.

В Google Календаре дело обстоит несколько иначе. Наряду с импортом календарей из файла, импортом по указанной по ссылке, импортом из другой учётной записи существует и ещё один вариант.



Мы сразу видим список «Другие календари» и открыв пункт меню «Посмотреть интересные календари» (кстати, интересное выбрано название меню) мы попадём в целую коллекцию разнообразных календарных событий, включая спорт, фазы луны и т.д. Одним из них является список предустановленных праздников — примерно по 30 странам.



Достаточно лишь выбрать необходимый и нажать «подписаться» — и список календарных событий будет добавлен как отдельный календарь. При этом будет добавлено событие на день и, как следствие, появится выделение соответствующей даты жирным шрифтом на навигаторе дат.

Кстати, Google с задачей импорта нашего файла «Международных праздников» справился успешно.

XtraScheduler при импорте праздников из ics-файла также создаёт отдельные события на целый день. Как можно это использовать? Достаточно включить опцию, запрещающую иметь пересекающиеся во времени события:
schedulerControl1.OptionsCustomization.AllowAppointmentConflicts = AppointmentConflictsMode.Forbidden;

и в этот праздничный день невозможно будет создать любое другое мероприятие.

Праздники в десктопных приложениях


Помимо ics-файлов есть ещё один способ получить список официальных государственных праздников по странам.

Одним из источников, при наличии установленного Microsoft Office, является файл outlook.hol, который расположен в подпапках установленного продукта, например, здесь: C:\Program Files\Microsoft Office\Office12\1049\outlook.hol"

Данные в этом файле разбиты по секциям-странам и содержат фиксированный список строк, представляющих праздники на несколько лет назад и вперёд.

...
[Россия] 84
Новогодние каникулы,2006/1/1
Новогодние каникулы,2007/1/1
Новогодние каникулы,2008/1/1
Новогодние каникулы,2009/1/1
Новогодние каникулы,2010/1/1
Новогодние каникулы,2011/1/1
Новогодние каникулы,2012/1/1
...

В версии офиса 2010 данные о праздниках представлены с 2009 до 2028 года…

Именно эти данные используются в Outlook Calendar. В параметрах календаря можно добавить праздники для указанной страны. При этом праздники будут также добавлены как физические события календаря.



Остановимся на том, как определяется строка-праздник в этом файле. Строка, хранящая информацию о празднике, состоит из его названия, даты и идентификатора календаря. Заметьте, что для ряда стран, где даты представлены не только в Григорианском календаре, необходимо выполнять преобразования дат.
...
[Алжир] 42
...
День рождения пророка Магомета,1424/3/12,6
...


Такие преобразования дат несложно сделать встроенными средствами, если вы используете .NET.

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

Количество поддерживаемых календарей для выполнения преобразований видно из кода ниже.
public class OutlookHolidaysLoader {
    #region CalendarTypes consts
    internal const int CAL_GREGORIAN = 1;
    internal const int CAL_GREGORIAN_ARABIC = 10;
    internal const int CAL_GREGORIAN_ME_FRENCH = 9;
    internal const int CAL_GREGORIAN_US = 2;
    internal const int CAL_GREGORIAN_XLIT_ENGLISH = 11;
    internal const int CAL_GREGORIAN_XLIT_FRENCH = 12;
    internal const int CAL_HEBREW = 8;
    internal const int CAL_HIJRI = 6;
    internal const int CAL_JAPAN = 3;
    internal const int CAL_JULIAN = 13;
    internal const int CAL_KOREA = 5;
    internal const int CAL_TAIWAN = 4;
    internal const int CAL_THAI = 7;
    #endregion

    internal const int DefaultCalendarType = CAL_GREGORIAN;

    public string[] ExtractLocations(string fileName) { }
    public string[] ExtractLocations(Stream stream) { }
    public HolidayBaseCollection FromFile(string fileName) {  }
    public HolidayBaseCollection FromFile(string fileName, string[] locations) { }
    public HolidayBaseCollection FromFile(string fileName, Encoding encoding, string[] locations) { }
    public HolidayBaseCollection FromStream(Stream stream) { }
    public HolidayBaseCollection FromStream(Stream stream, string[] locations) { }
    public HolidayBaseCollection FromStream(Stream stream, Encoding encoding, string[]) { }
}

Аналогичный функционал праздников получили такие продукты как ASPxScheduler и DXScheduler for WPF.
Как это работает в ASPxScheduler, вы можете посмотреть в нашей онлайн-демо.

Помимо загрузки из iCalendar и outlook.hol наш планировщик может загружать и сохранять коллекцию праздников в формате XML.
    //...
    HolidayBaseCollection holidays = HolidayCollectionXmlPersistenceHelper.ObjectFromXml(string xml);
    //....
    new HolidayCollectionXmlPersistenceHelper(holidays).ToXml();


Где еще может понадобиться поддержка праздников в приложениях? Один из возможных сценариев — фильтрация ненужных дней при показе большого списка временнЫх данных. В качестве примера приведу продукт XtraCharts, который вслед за нашими планировщиками реализовал поддержку выходных дней и праздников для выбрасывания ненужных дат в сериях.

Немного аналитики


В качестве бонуса приведу немного статистических данных, полученных из файла Outlook-а. Я загрузил файл outlook.hol с праздниками, отфильтровал даты по 2010 году и визуализировал результаты, при этом подсчитав их количество в году для разных стран.

Следующая диаграмма показывает распределение количества государственных праздников по странам в 2010 году:


Полный список количества праздников по странам отражен на легенде ниже:


Если не брать во внимание религиозные праздники, то нетрудно заметить, что лидирующее положение по количеству праздников занимают такие страны как
Китай, Канада и Соединенные Штаты Америки.

Минимальное число праздников у Евроcоюза, Ливии, Индии, Малайзии.

Россия занимает среднее положение со значением 12.

Конечно надо понимать, что эти цифры показывают только официальные праздники и никак не отражают реальную картину общего количества выходных. Так что делать какие-либо выводы (например, кто самая «празднующая» страна, а кто — «страна-трудоголик») предоставлю вам… :-)

ВСЕХ С НАСТУПАЮЩИМ НОВЫМ ГОДОМ!!!
Теги:
Хабы:
Всего голосов 40: ↑29 и ↓11+18
Комментарии24

Публикации

Информация

Сайт
www.developersoft.ru
Дата регистрации
Дата основания
1998
Численность
201–500 человек
Местоположение
Россия

Истории