Повторяющиеся события теряют автоматическое преобразование часового пояса
Я настраиваю календарь приглашений, используя ical.net. Отправка неповторяющегося события, кажется, работает отлично: я установил дату начала и окончания следующим образом
iCalEvent.DtStart = new CalDateTime(DateTime.SpecifyKind(model.EventTime.Value, DateTimeKind.Utc));
iCalEvent.DtEnd = new CalDateTime(DateTime.SpecifyKind(model.EventTime.Value.AddMinutes(model.DurationMins.Value), DateTimeKind.Utc));
Когда приходит электронное письмо, часовой пояс конвертируется в часовой пояс получателя (часовой пояс -7, eventTime - 4 вечера и продолжительность - 3 часа)
Тем не менее, когда я беру этот самый точный код и добавляю эту строку к нему
IRecurrencePattern recurrence = new RecurrencePattern(FrequencyType.Daily, 1)
{
Until = DateTime.SpecifyKind(model.endDate.Value.AddDays(1), DateTimeKind.Utc)
};
iCalEvent.RecurrenceRules = new List<IRecurrencePattern> { recurrence };
Внезапно мой часовой пояс больше не преобразуется при получении электронного письма (часовой пояс -7, eventTime 4 часа и продолжительность 3 часа. EndDate 28-го числа)
Мне нужно, чтобы DateTime отображался пользователю в его собственном часовом поясе, и мне нужно отображать повторяющиеся события от eventTime до endDate.
Также может быть полезно отметить, что у меня нет свойства часового пояса, указанного в Календаре, поскольку оно заставляло отправленное электронное письмо отображать "не поддерживаемое сообщение календаря" в Outlook. До того как я его снял, это выглядело так
iCal.AddTimeZone(new VTimeZone("UTC"));
когда я открывал ical-файлы с указанным часовым поясом, они, похоже, работали корректно для многодневных событий, но, поскольку мне нужно, чтобы они отображались в outlook с помощью кнопок принять / отклонить / ориентировочные, нет смысла добавлять его обратно
Я также пытался указать дату и время, как это
iCalEvent.DtStart = new CalDateTime(leEvent.EventTime.Value, "UTC");
но ничего не изменилось
РЕДАКТИРОВАТЬ: Теперь я понимаю, что проблема связана с повторяющимся событием, нуждающимся в часовом поясе, как указано здесь, но я не совсем уверен, где часовой пояс должен быть указан. Я вернулся к добавлению vTimeZone и проверке его через этот сайт, и кажется, что в файле iCal отсутствует раздел стандартного / дневного света внутри блока часового пояса.
Я также попытался указать часовой пояс как GMT и указать часовой пояс как "\"America/Phoenix\"", чтобы tzid получился как TZID:"America/Phoenix" (с кавычками в файле ical.
Это мой код на данный момент, который вызывает проблему.
iCalEvent.DtStart = new CalDateTime(DateTime.SpecifyKind(model.EventTime.Value, DateTimeKind.Utc));
iCalEvent.DtEnd = new CalDateTime(iCalEvent.DtStart.Value.AddMinutes(model.DurationMins.Value));
if (model.EndDate.HasValue)
{
IRecurrencePattern recurrence = new RecurrencePattern(FrequencyType.Daily, 1)
{
Until = DateTime.SpecifyKind(model.MaxDate.Value, DateTimeKind.Utc).ToLocalTime()
};
iCalEvent.RecurrenceRules = new List<IRecurrencePattern> { recurrence };
iCalEvent.DtStart = new CalDateTime(iCalEvent.DtStart.Value.ToLocalTime(), "America/Phoenix");
iCalEvent.DtEnd = new CalDateTime(iCalEvent.DtEnd.Value.ToLocalTime(), "America/Phoenix");
iCal.AddTimeZone(new VTimeZone("America/Phoenix"));
}
Я не совсем уверен, что должно произойти, чтобы исправить стандартную / дневную ошибку с этой точки зрения.
ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ:
Прочитав этот пост, я обнаружил, что эта проблема уже решена по состоянию на последний ноябрь. Я проверил версию, которая была у нас в нашем проекте, и оказалось, что какой-то гений просто скопировал dll прямо, не настраивая его через nuget (и версию от нескольких лет назад не меньше). Я взял последнюю версию, и на этот раз указание часового пояса не вызвало никаких проблем в перспективе. Я все еще экспериментирую с addTimeZone и addLocalTimeZone, но я определенно на правильном пути. Спасибо rianjs за эту чрезвычайно полезную библиотеку. Я не знаю, как бы я мог работать с этим безумным календарным стандартом без него.
2 ответа
Повторяющееся событие всегда зависит от часового пояса отправителя (или, скорее, от местоположения события), а не от часового пояса получателя из-за изменений летнего времени, которые могут происходить в разное время между организатором и различными получателями.
Поэтому в большинстве случаев вы хотите использовать значимый часовой пояс в событии (т.е. не в формате UTC). Затем Outlook просто показывает, что событие действительно происходит в соответствии с заданным часовым поясом. Это указывает на то, что событие не всегда может быть в одно и то же время суток для получателя.
Поскольку мне потребовалось так много времени, чтобы понять, я мог бы также поделиться своим решением на тот случай, если кто-нибудь еще столкнется с этой проблемой и обнаружит ее.
Я определил DtStart/DtEnd с двумя датами времени, которые имели вид utc
calendarEvent.DtStart = new CalDateTime(model.EventTime.Value);
calendarEvent.DtEnd = new CalDateTime(model.EventTime.Value.AddMinutes(model.DurationMins.Value));
который отлично работал на однодневных мероприятиях, но с многодневным я в итоге сделал это
if (model.EndDate.HasValue)
{
RecurrencePattern recurrence = new RecurrencePattern(FrequencyType.Daily, 1)
{
Until = model.EndDate.Value //has kind: Utc
};
var timezoneOffsetString = "Etc/GMT";
if (timezoneOffset > 0) //client time zone offset, calculated through js
{
timezoneOffsetString += "-" + timezoneOffset;
}
else if (timezoneOffset < 0)
{
timezoneOffsetString += "+" + (-1 * timezoneOffset);
}
calendar.AddTimeZone(timezoneOffsetString);
calendarEvent.DtStart = calendarEvent.DtStart.ToTimeZone(timezoneOffsetString);
calendarEvent.DtEnd = calendarEvent.DtEnd.ToTimeZone(timezoneOffsetString);
calendarEvent.RecurrenceRules = new List<RecurrencePattern> { recurrence };
}
Он не является полностью защищенным, так как в некоторых местах могут быть странные проблемы с dst, но nodatime рассматривал tzid "Америка / Феникс" как время LMT, которое давало мне время, которое было как 28 минут... Кроме того, рассматривал все даты как GMT ближе к реализации, которую мы имеем в остальной части нашего приложения, так что это сработало для моей ситуации
Это решение дало мне идею собрать воедино материал Etc/GMT.