Managing Date and Time Properties in Calendars

There are several types of date and time objects exist in iCalendar format. To manipulate date and time, you will typically use ICalDate and IDate interfaces, Date class and ICalendar2.CreateCalDateProp helper method.

The iCalendar standard does not allow UTC time offsets. That is why, to avoid any confusion with offsets, the IT Hit Collab library is using DateTime .NET structure and not the DateTimeOffset.

ICalDate Interface

There are several types of date and time properties that ICalDate interface can represent:

Date and time with time zone

This is the most widely used format. Here is the example of creating such property:

evt.Start = cal.CreateCalDateProp(new DateTime(2017, 4, 20, 9, 40, 0), "Africa/Johannesburg", false);

or

ICalDate startProp = cal.CreateProperty<ICalDate>();
startProp.Value = newDate(new DateTime(2017, 4, 20, 9, 40, 0));
startProp.TimeZoneId = "Africa/Johannesburg";
evt.Start = startProp;

In the iCalendar output stream you will find that TZID property is added and no “Z” is specified in date-time value:

DTSTART;TZID=Africa/Johannesburg:20170420T094000

Date and time in Universal Coordinated Time (UTC)

To create time in UTC pass “UTC” string as the second parameter to CreateCalDateProp:

evt.Start   = cal.CreateCalDateProp(new DateTime(2017, 4, 20, 9, 40, 0), "UTC", false);

or

ICalDate startProp = cal.CreateProperty<ICalDate>();
startProp.Value = new Date(new DateTime(2017, 4, 20, 9, 40, 0, DateTimeKind.Utc));
evt.Start = startProp;

Note that you do not set the TimeZoneId property in the last example, instead DateTimeKind.Utc is specified.

In the iCalendar output stream there would be no TZID property but “Z” is added to date-time value, meaning this is a UTC time:

DTSTART:20170420T094000Z

Floating date and time

In this case, the date and time are specified in local date and time without time zone. Pass null as the second parameter to CreateCalDateProp:

evt.Start   = cal.CreateCalDateProp(new DateTime(2017, 4, 20, 9, 40, 0), null, false);

or

ICalDate startProp = cal.CreateProperty<ICalDate>();
startProp.Value = new Date(new DateTime(2017, 4, 20, 9, 40, 0));
evt.Start = startProp;

In the iCalendar output stream, there would be no TZID property and no “Z” added to date-time value:

DTSTART:20170420T094000

All day events

In this case, time is not specified. Pass true as an allDay parameter to CreateCalDateProp:

evt.Start   = cal.CreateCalDateProp(newDateTime(2017, 4, 20, 0, 0, 0), null, true);

or

ICalDate startProp = cal.CreateProperty<ICalDate>();
startProp.Value = new Date(new DateTime(2017, 4, 20, 0, 0, 0), DateComponents.Date);
evt.Start = startProp;

As soon as DataTime .NET Framework class does not allow to specify date without specifying time, the Date class constructor accepts a flag enum that specifies which parts of DateTime are meaningful. In the above example, we specified that only date part should be used.

For all-day events in the iCalendar output stream you will find the VALUE=DATE parameter:

DTSTART;VALUE=DATE:20170420

There also could be all-day events with time zone:

DTSTART;VALUE=DATE;TZID=Africa/Johannesburg:20170420

IDate Interface

The ICalDate is derived from IDate interface that is common for both calendars and business cards. The major difference between these interfaces is in TimeZoneId property - the IDate does not have a time zone and typically used to represent UTC time for properties such as IJournal.CreatedUtc and IJournal.LastModifiedUtc:

evt.CreatedUtc      = cal.CreateDateProp(new DateTime(2017, 4, 20, 10, 50, 0), DateTimeKind.Utc);
evt.LastModifiedUtc = cal.CreateDateProp(new DateTime(2017, 4, 20, 11, 10, 0), DateTimeKind.Utc);