Erica Stockwell-Alpert
Erica Stockwell-Alpert

Reputation: 4863

Specifying timezone in DateTime object for .ics file - times are off by an hour (C#, Sitecore 9)

I have events in Sitecore that each have a Start Date, End Date, and a Time Zone, and a link that generates a .ics file to add these events to your calendar (such as Outlook). Initially, the times were way off, because (I think) the times stored in Sitecore are UTC so although it displays on the page as, say 12:00 - 3:00, because that time is UTC the calendar event will show it as something like 5:00 - 8:00.

This was the original code:

StringBuilder sb = new StringBuilder();
sb.AppendLine("BEGIN:VCALENDAR");
sb.AppendLine("VERSION:2.0");
sb.AppendLine("PRODID:-//IFT.org//NONSGML Events//EN");
sb.AppendLine("BEGIN:VEVENT");
sb.AppendFormat("DTSTART;VALUE DATE-TIME:{0}\n", eventDates.Start_Date.ToUniversalTime().ToString("yyyyMMddTHHmmssZ"));
sb.AppendFormat("DTEND;VALUE DATE-TIME:{0}\n", eventDates.End_Date.ToUniversalTime().ToString("yyyyMMddTHHmmssZ"));

I added the following code to factor in the specified timezone:

var timezone = eventDates.Time_Zone?._Name;
sb.AppendFormat("DTSTART;VALUE DATE-TIME:{0}\n", GetTime(eventDates.Start_Date, timezone));
sb.AppendFormat("DTEND;VALUE DATE-TIME:{0}\n", GetTime(eventDates.End_Date, timezone));

public String GetTime(DateTime date, String timezone)
{
    var timezoneKey = TimezoneDictionary[timezone];
    var tz = TimeZoneInfo.FindSystemTimeZoneById(timezoneKey);
    TimeSpan offset = new TimeSpan(0, 0, 0);
    if (tz != null)
    {
        offset = tz.BaseUtcOffset;
    }
    DateTimeOffset dto = new DateTimeOffset(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, offset);

    DateTime utcDate = dto.UtcDateTime;
    return utcDate.ToString("yyyyMMddTHHmmssZ");
}

This all looks like it works correctly - when I step through it, I get that tz is the Eastern Standard Time timezone (which I am in), which has an offset of -5:00. dto appears to be 10/21/2019 12:00, with an offset of -5:00; utcDate.toString("yyyyMMddTHHmmssZ") gives me 20191023T170000Z which looks right (because 12:00 + 5:00 = 17:00). However, when I open the .ics file, the times appear as 1:00 and 4:00 instead of 12:00 and 3:00 (the timezone says Eastern Time)

I'm not sure if this is a problem with my code or with Outlook, but this is my .ics file:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//IFT.org//NONSGML Events//EN
BEGIN:VEVENT
DTSTART;VALUE DATE-TIME:20191023T170000Z
DTEND;VALUE DATE-TIME:20191026T000000Z
SUMMARY:summary
DESCRIPTION:description
LOCATION:Sun Valley, Idaho
URL;VALUE=URI:http://mysite/events/event-listing/2019/oct/symposium
UID:f10b3138-2737-46d6-b1c0-cbdc18cc0ef6
END:VEVENT
END:VCALENDAR

Upvotes: 1

Views: 2198

Answers (1)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241798

tz.BaseUtcOffset returns the offset that is in effect during standard time - regardless of whether standard time is actually in effect or not. At the time of your event, Eastern Daylight Time is in effect, which is UTC-4 rather than UTC-5.

Don't be confused by the time zone string being "Eastern Standard Time" - that is indeed the correct the Id, but it represents both EST and EDT. You can think of it as just "Eastern Time".

To get the offset in effect, you can change your code to:

offset = tz.GetUtcOffset(date)

If you wanted to simplify your code, you could also just use TimeZoneInfo.ConvertTimeToUtc instead of figuring out the offset yourself.

Upvotes: 2

Related Questions