public static void Main(string[] args) { // Название нашей таблицы с расписанием. string filePath = filename + @".xlsx"; // Парсим xlsx-таблицу List <WorkDay> week = ParseExcelSchedule.Parse(filePath); // Задаем дату начала семестра. iCalDateTime startStudy = new iCalDateTime(2016, 9, 1); // Создаём календарь, в который будем сохранять матчи. iCalendar CalForSchedule = new iCalendar { Method = "PUBLISH", Version = "2.0", }; // Эти настройки нужны для календаря Mac, чтобы он был неотличим от // оригинального календаря (т.е. созданного внутри Mac Calendar) CalForSchedule.AddProperty("CALSCALE", "GREGORIAN"); CalForSchedule.AddProperty("X-WR-CALNAME", "Расписание"); CalForSchedule.AddProperty("X-WR-TIMEZONE", "Europe/Moscow"); CalForSchedule.AddLocalTimeZone(); // Сохраняем дату начала первой учебной недели. //TODO тут какое-то говно с преобразованием iCalDateTime в IDateTime int numberOfFirstDayOfFirstStudyWeek = startStudy.DayOfYear - ParseExcelSchedule.GetIntNumberFromDayWeek(startStudy.DayOfWeek.ToString()); iCalDateTime firstDayOfFirstStudyWeek = new iCalDateTime(startStudy.FirstDayOfYear.AddDays(numberOfFirstDayOfFirstStudyWeek)); // Пробегаемся по всем учебным дням в неделе. foreach (WorkDay workDay in week) { // Информация для отладки. Console.WriteLine(workDay); // Плюсуем к понедельнику первой учебной недели номер нашего обрабатываемого дня iCalDateTime tmpDate = new iCalDateTime(firstDayOfFirstStudyWeek.AddDays(workDay.dayNumber - 1)); // Плюсуем к временной дате (номер недели - 1, т.к. чтобы перейти // к первой неделе не нужно плюсовать неделю) * 7 дней) и // приводим к локальной временной зоне. // // FIXME // Для второго семестра приходится минусовать 24 недели //iCalDateTime StartClass = new iCalDateTime(tmpDate.AddDays((number - 1 - 23) * 7).Local); iCalDateTime StartClass = new iCalDateTime(tmpDate.AddDays((workDay.repeatAt[0] - 1) * 7).Local); // Если неделя первая (подразумевается, что она не полная) // и день занятий раньше для начала учебы, тогда не записываем его. //if ((1 == 1 // && StartClass.LessThan(startStudy)) // || // (StartClass.GreaterThanOrEqual(new iCalDateTime(startStudy.FirstDayOfYear.AddDays(363))) // && !(isLeapYear(StartClass.Year))) // || // (StartClass.GreaterThanOrEqual(new iCalDateTime(startStudy.FirstDayOfYear.AddDays(364))) // && isLeapYear(StartClass.Year))) // continue; Event newClass = CalForSchedule.Create <Event>(); newClass.DTStart = StartClass; // OLD: StartClass newClass.DTStart = newClass.DTStart.Add(workDay.timeClassStart); newClass.Duration = workDay.timeClassEnd - workDay.timeClassStart; if (workDay.typeClass == "Семинар") { newClass.Summary = Emojione.Emojione.ShortnameToUnicode(":closed_book:"); } else { newClass.Summary = Emojione.Emojione.ShortnameToUnicode(":green_book:"); } newClass.Summary += string.Format("{0}", workDay.nameSubject); newClass.Description = string.Format("Преподаватель: {0}", workDay.nameLecturer); newClass.Location = string.Format("{0}, {1}", workDay.typeClass, workDay.place); newClass.IsAllDay = false; RecurrencePattern rp = new RecurrencePattern("RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=" + (workDay.repeatAt.Max() - workDay.repeatAt.Min() + 1)); newClass.RecurrenceRules.Add(rp); //event.RecurrenceRules.Add(rp); //newClass.AddProperty("RRULE", @"FREQ = WEEKLY; INTERVAL = 1; COUNT = " + (); // Добавим напоминание к парам, чтобы не забыть о них. Alarm alarm = new Alarm(); alarm.Trigger = new Trigger(TimeSpan.FromMinutes(-5)); alarm.Description = "Напоминание о событии"; alarm.AddProperty("ACTION", "DISPLAY"); newClass.Alarms.Add(alarm); // Если это первая пара за день, напоминаем о ней за 2,5 часа. //if (workDay.isFirstClassesOfADay) //{ // Alarm alarm2 = new Alarm(); // alarm2.Trigger = new Trigger(TimeSpan.FromMinutes(-150)); // alarm2.Description = "Напоминание о событии"; // alarm2.AddProperty("ACTION", "DISPLAY"); // newClass.Alarms.Add(alarm2); //} } // Сериализуем наш календарь. iCalendarSerializer serializer = new iCalendarSerializer(); serializer.Serialize(CalForSchedule, fileCalcName + @".ics"); Console.WriteLine("Календарь расписания сохранён успешно" + Environment.NewLine); }
/// <summary> /// Creates the iCalendar object and populates it with events /// </summary> /// <param name="calendarProps">The calendar props.</param> /// <returns></returns> private iCalendar CreateICalendar(CalendarProps calendarProps) { // Get a list of Rock Calendar Events filtered by calendarProps List <EventItem> eventItems = GetEventItems(calendarProps); // Create the iCalendar iCalendar icalendar = new iCalendar(); icalendar.AddLocalTimeZone(); // Create each of the events for the calendar(s) foreach (EventItem eventItem in eventItems) { foreach (EventItemOccurrence occurrence in eventItem.EventItemOccurrences) { iCalendarSerializer serializer = new iCalendarSerializer(); iCalendarCollection ical = ( iCalendarCollection )serializer.Deserialize(occurrence.Schedule.iCalendarContent.ToStreamReader()); foreach (var icalEvent in ical[0].Events) { // We get all of the schedule info from Schedule.iCalendarContent Event ievent = icalEvent.Copy <Event>(); ievent.Summary = !string.IsNullOrEmpty(eventItem.Name) ? eventItem.Name : string.Empty; ievent.Location = !string.IsNullOrEmpty(occurrence.Location) ? occurrence.Location : string.Empty; ievent.DTStart.SetTimeZone(icalendar.TimeZones[0]); ievent.DTEnd.SetTimeZone(icalendar.TimeZones[0]); // Rock has more descriptions than iCal so lets concatenate them string description = CreateEventDescription(eventItem, occurrence); // Don't set the description prop for outlook to force it to use the X-ALT-DESC property which can have markup. if (interactionDeviceType != "Outlook") { ievent.Description = description.ConvertBrToCrLf().SanitizeHtml(); } // HTML version of the description for outlook ievent.AddProperty("X-ALT-DESC;FMTTYPE=text/html", "<html>" + description + "</html>"); // classification: "PUBLIC", "PRIVATE", "CONFIDENTIAL" ievent.Class = "PUBLIC"; if (!string.IsNullOrEmpty(eventItem.DetailsUrl)) { ievent.Url = new Uri(eventItem.DetailsUrl); } // add contact info if it exists if (occurrence.ContactPersonAlias != null) { ievent.Organizer = new Organizer(string.Format("MAILTO:{0}", occurrence.ContactPersonAlias.Person.Email)); ievent.Organizer.CommonName = occurrence.ContactPersonAlias.Person.FullName; // Outlook doesn't seems to use Contacts or Comments string contactName = !string.IsNullOrEmpty(occurrence.ContactPersonAlias.Person.FullName) ? "Name: " + occurrence.ContactPersonAlias.Person.FullName : string.Empty; string contactEmail = !string.IsNullOrEmpty(occurrence.ContactEmail) ? ", Email: " + occurrence.ContactEmail : string.Empty; string contactPhone = !string.IsNullOrEmpty(occurrence.ContactPhone) ? ", Phone: " + occurrence.ContactPhone : string.Empty; string contactInfo = contactName + contactEmail + contactPhone; ievent.Contacts.Add(contactInfo); ievent.Comments.Add(contactInfo); } // TODO: categories - comma delimited list of whatever, might use audience foreach (var a in eventItem.EventItemAudiences) { ievent.Categories.Add(a.DefinedValue.Value); } //// No attachments for now. ////if ( eventItem.PhotoId != null ) ////{ //// // The DDay Attachment obj doesn't allow you to name the attachment. Nice huh? So just add prop manually... //// ievent.AddProperty( "ATTACH;VALUE=BINARY;ENCODING=BASE64;X-FILENAME=\"" + eventItem.Photo.FileName + "\"", Convert.ToBase64String( eventItem.Photo.ContentStream.ReadBytesToEnd().ToArray() ) ); ////} icalendar.Events.Add(ievent); } } } return(icalendar); }
public static void Main(string[] args) { // Адрес сайта, откуда будем парсить данные. string WebAddress = @"http://www.sports.ru/barcelona/calendar/"; // Создаём экземляры классов веб-страницы и веб-документа HtmlWeb WebGet = new HtmlWeb(); // Загружаем html-документ с указанного сайта. HtmlDocument htmlDoc = WebGet.Load(WebAddress); // Сюда будем сохранять матчи Matches MatchesFC = new Matches(); // Парсим название клуба (удаляя символ возрата каретки) MatchesFC.NameFC = htmlDoc.DocumentNode. SelectSingleNode(".//*[@class='titleH1']"). FirstChild.InnerText.Replace("\r\n", ""); // Находим в этом документе таблицу с датами матчей с помощью XPath-выражений. HtmlNode Table = htmlDoc.DocumentNode.SelectSingleNode(".//*[@class='stat-table']/tbody"); // Из полученной таблицы выделяем все элементы-строки с тегом "tr". IEnumerable <HtmlNode> rows = Table.Descendants().Where(x => x.Name == "tr"); foreach (var row in rows) { // Создаём коллекцию из ячеек каждой строки. HtmlNodeCollection cells = row.ChildNodes; // Создаём экземпляр класса SingleMatch, чтобы затем добавить его в лист. SingleMatch match = new SingleMatch(); // Парсим дату, предварительно убирая из строки символ черточки "|", // иначе наш метод TryParse не сможет правильно обработать. DateTime time; DateTime.TryParse(cells[1].InnerText.Replace("|", " "), out time); match.StartTime = time; // Остальные поля просто заполняем, зная нужный нам индекс. match.Tournament = cells[3].InnerText; // В ячейке "Соперник" нужно удалить символ неразрывного пробела (" ") match.Rival = cells[5].InnerText.Replace(" ", ""); match.Place = cells[6].InnerText; // Добавляем одиночный матч в лист матчей. MatchesFC.ListMatches.Add(match); } // Создаём календарь, в который будем сохранять матчи. iCalendar CalForMatches = new iCalendar { Method = "PUBLISH", Version = "2.0" }; // Эти настройки нужны для календаря Mac, чтобы он был неотличим от // оригинального календаря (т.е. созданного внутри Mac Calendar) CalForMatches.AddProperty("CALSCALE", "GREGORIAN"); CalForMatches.AddProperty("X-WR-CALNAME", "Mатчи ФК " + MatchesFC.NameFC); CalForMatches.AddProperty("X-WR-TIMEZONE", "Europe/Moscow"); CalForMatches.AddLocalTimeZone(); // Сохраняем полученный результат. foreach (SingleMatch match in MatchesFC.ListMatches) { Event newMatch = CalForMatches.Create <Event>(); newMatch.DTStart = new iCalDateTime(match.StartTime); newMatch.Duration = new TimeSpan(2, 30, 0); newMatch.Summary = string.Format("{0} : {1}", MatchesFC.NameFC, match.Rival); newMatch.Description = string.Format("{0}. {1} : {2}, {3}", match.Tournament, MatchesFC.NameFC, match.Rival, match.Place); // Добавим напоминание к матчам, чтобы не забыть о них Alarm alarm = new Alarm(); alarm.Trigger = new Trigger(TimeSpan.FromMinutes(-10)); alarm.Description = "Напоминание о событии"; alarm.AddProperty("ACTION", "DISPLAY"); newMatch.Alarms.Add(alarm); } // Сериализуем наш календарь. iCalendarSerializer serializer = new iCalendarSerializer(); serializer.Serialize(CalForMatches, MatchesFC.NameFC + ".ics"); Console.WriteLine("Календарь матчей сохранён успешно" + Environment.NewLine); return; }