Повторяющиеся события с поддержкой перехода на летнее время с использованием 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 для преобразования часовых поясов.)

Другие вопросы по тегам