Search code examples
c#outlookicalendarical-dotnet

Recurring events lose automatic timezone conversion


I'm setting up a calendar invite email using ical.net. Sending out a non-recurring event seems to work perfectly: I set the start and end date like this

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));

when the email arrives, the time zone has been converted to the recipients timezone (The timezone is -7, the eventTime is 4pm and the duration is 3 hours)

The timezone is -7, the eventTime is 4pm and the duration is 3 hours

However, when I take this same exact code and add this line to it

IRecurrencePattern recurrence = new RecurrencePattern(FrequencyType.Daily, 1)
{
    Until = DateTime.SpecifyKind(model.endDate.Value.AddDays(1), DateTimeKind.Utc)
};

iCalEvent.RecurrenceRules = new List<IRecurrencePattern> { recurrence };

Suddenly my timezone is no longer converted when the email is received (The timezone is -7, the eventTime is 4pm and the duration is 3 hours. The endDate is on the 28th)

The timezone is -7, the eventTime is 4pm and the duration is 3 hours. The endDate is on the 28th

I need the DateTime to be displayed to the user in their own timezone and I need to display recurring events from the eventTime to the endDate

It may also be useful to note that I do not have a timezone property specified on Calendar as it was causing the sent email to show a "not supported calendar message" in outlook. Before I removed it, it looked like this

iCal.AddTimeZone(new VTimeZone("UTC"));

when I opened ical files that had this time zone specified, they seemed to work correctly for multi day events, but as I need them to appear in outlook with the accept/decline/tentative buttons, it is out of the question to add it back

i've also tried specifying datetimes like this

iCalEvent.DtStart = new CalDateTime(leEvent.EventTime.Value, "UTC");

but nothing changed

EDIT: I now understand that the issue is due to a recurring event needing a timezone as specified here, but I'm not quite sure where the timezone needs to be specified. I went back to adding the vTimeZone back in and validating it through this site, and it appears that the iCal file is missing the standard/daylight section inside of the timezone block

The result of the validity checker

I have also tried specifying the timezone as GMT and specifying the timezone as "\"America/Phoenix\"" so that the tzid came out as TZID:"America/Phoenix" (with quotes in the ical file.

This is my code at the moment that causes the issue.

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"));
}

I'm not quite sure what needs to happen to correct the standard/daylight ical error from this point.

FINAL EDIT:

after reading through this post, I found that this issue has already been solved as of last november. I checked the version we had in our project and it turned out some genius just copied the dll straight in without setting it up through nuget (and a version from several years ago no less). I grabbed the latest version and this time specifying the timezone caused no issues in outlook. I'm still experimenting with addTimeZone and addLocalTimeZone but I'm definitely on the right track. Thank you to rianjs for this extremely useful library. I don't know how I would possible work with this crazy calendar standard without it.


Solution

  • A recurring event is always relative to the sender's timezone (or rather to the event location), and not to the recipient's timezone, because of daylight saving changes which may happen at different time between the organiser and the various recipients.

    So in most cases you want to use a meaningful timezone in the event (i.e. not UTC). Then Outlook is simply showing that the event is indeed happening according to the given timezone. This is an indication that the event may not always be at the same time of day for the recipient.