Повторяющиеся события с поддержкой перехода на летнее время с использованием ical.net
Каков наилучший способ реализации повторяющихся дат, которые автоматически подстраиваются под летнее время? Например, событие должно повторяться каждый день в 10:00 по восточному поясному времени, даже когда действует летнее время, и не должно прыгать назад или вперед на 1 час.
В настоящее время я храню даты в формате UTC, но у меня также есть доступ к исходному часовому поясу.
1 ответ
В общем случае в программировании даты и времени на самом деле невозможно выразить правила о будущем времени, используя UTC в качестве отправной точки, если ваш целевой часовой пояс также не является UTC. Часовые пояса являются социально-политическими, и правила меняются.
Для этого решение состоит в том, чтобы выразить CalDateTime
с местными часовыми поясами. Как только вы это сделали, GetOccurrences()
будет правильно вычислять повторяемость.
var start = DateTime.Parse("2017-02-01 11:00");
var end = start.AddHours(1);
var dailyUntilSummer = new RecurrencePattern(FrequencyType.Daily, 1)
{
Until = DateTime.Parse("2017-07-01 12:00"),
};
var calendarEvent = new Event
{
Start = new CalDateTime(start, "America/New_York"),
End = new CalDateTime(end, "America/New_York"),
RecurrenceRules = new List<IRecurrencePattern> { dailyUntilSummer },
};
var calendar = new Calendar();
calendar.Events.Add(calendarEvent);
var occurrences = calendar.GetOccurrences(start, start.AddMonths(6))
.Select(o => new {Local = o.Period.StartTime, Utc = o.Period.StartTime.AsUtc})
.OrderBy(o => o.Local)
.ToList();
Если вы установите точку останова после occurrences
и, посмотрев его содержимое, вы увидите, что 12 марта время UTC идет с 16:00 до 15:00, а местное время остается стабильным. 12 марта America/New_York перешла с UTC-5 на UTC-4, когда часы изменились:
(За кулисами ical.net использует NodaTime для преобразования часовых поясов.)