Send iCalendar recurring meeting requests for different timezone

Usually you define time of an event in relation to UTC timezone or local timezone.

If you need to define event on 9:00 o’clock in Alaska you simply need to subtract 9 hours from event time to get the event time in UTC
(18:00:00). 18 – 9 = 9.

It all works great in December (Alaska is UTC-9), but in May, daylight saving time is in effect in Alaska (Alaska is UTC-8 then). In May, event is going to be held at 10:00 Alaska time (18 – 8 = 10). Which is most likely not what you want.

If you need to define a single instance of the event it is still not a problem. To get UTC time for the event you subtract 9 hours in the winter and 8 hours in the summer.

But if the event is recurring, and should be held always at 9 Alaska time, you need to specify the timezone along with the event.

As the timezones in different parts of world change way to often to reflect these changes in Mail.dll, you’ll need to specify the timezone when creating new event (including the daylight savings time).

Here’s the sample:

// C#

using Fluent = Limilabs.Mail.Fluent;
using Limilabs.Client.SMTP;
using Limilabs.Mail;
using Limilabs.Mail.Appointments;

Appointment appointment = new Appointment();

// Create time zone
VTimeZone alaska = appointment.AddTimeZone();
alaska.TimeZoneId = "America/Anchorage";

// Define standard time offset
var standardRecurring = new RecurringRule();
standardRecurring.Frequency = Frequency.Yearly;
standardRecurring.ByDay.Add(Weekday.FirstSunday);
standardRecurring.ByMonths.Add(11);

var standard = new StandardOffset
{
    Name = "AKST",
    Start = new DateTime(1970, 11, 01, 02, 00, 00),
    OffsetFrom = TimeSpan.FromHours(-8),
    OffsetTo = TimeSpan.FromHours(-9),
    RecurringRule = standardRecurring
};

// Define daylight time offset
var daylightRecurring = new RecurringRule();
daylightRecurring.Frequency = Frequency.Yearly;
daylightRecurring.ByDay.Add(new Weekday(2, Weekday.Sunday));
daylightRecurring.ByMonths.Add(3);

var daylight = new DaylightOffset
{
    Name = "AKDT",
    Start = new DateTime(1970, 03, 08, 02, 00, 00),
    OffsetFrom = TimeSpan.FromHours(-9),
    OffsetTo = TimeSpan.FromHours(-8),
    RecurringRule = daylightRecurring
};

alaska.Standard.Add(standard);
alaska.Daylight.Add(daylight);

// Define event
Event e = appointment.AddEvent();
e.Start = new DateTime(2007, 08, 17, 12, 00, 00);
e.End = new DateTime(2007, 08, 17, 12, 30, 00);
e.Summary = "At noon in Alaska";
e.InTimeZone(alaska);

// Make event recurring
RecurringRule rule = e.AddRecurringRule();
rule.Interval = 1;
rule.Until = new DateTime(2011, 12, 1); // -or- rule.Count = 10;

// Every week on  Mon, Tue, Wed, Thu Fri:
rule.Frequency = Frequency.Weekly;
rule.ByDay.AddRange(new[] {
    Weekday.Monday,
    Weekday.Tuesday,
    Weekday.Wednesday,
    Weekday.Thursday,
    Weekday.Friday });

// Set participants
e.SetOrganizer(new Person("Alice", "alice@example.org"));

e.AddParticipant(
    new Participant("Bob", "bob@example.org", ParticipationRole.Required, true));
e.AddParticipant(
    new Participant("Tom", "tom@example.org", ParticipationRole.Optional, true));
e.AddParticipant(
    new Participant("Alice", "alice@example.org", ParticipationRole.Required, true));

// Add alarm
Alarm alarm = e.AddAlarm();
alarm.BeforeStart(TimeSpan.FromMinutes(15));

IMail email = Fluent.Mail
    .Text("Status meeting at noon in Alaska.")
    .Subject("Status meeting")
    .From("alice@example.org")
    .To("bob@example.org")
    .To("tom@example.org")
    .AddAppointment(appointment)
    .Create();

using (Smtp smtp = new Smtp())
{
    smtp.Connect("smtp.example.org"); // or ConnectSSL
    smtp.UseBestLogin("user", "password");
    smtp.SendMessage(email);
    smtp.Close();
}
' VB.NET

Imports Fluent = Limilabs.Mail.Fluent
Imports Limilabs.Client.SMTP
Imports Limilabs.Mail
Imports Limilabs.Mail.Appointments

Dim appointment As New Appointment()

' Create time zone
Dim alaska As VTimeZone = appointment.AddTimeZone()
alaska.TimeZoneId = "America/Anchorage"

' Define standard time offset
Dim standardRecurring = New RecurringRule()
standardRecurring.Frequency = Frequency.Yearly
standardRecurring.ByDay.Add(Weekday.FirstSunday)
standardRecurring.ByMonths.Add(11)

Dim standard = New StandardOffset() With { _
	.Name = "AKST", _
	.Start = New DateTime(1970, 11, 1, 2, 0, 0), _
	.OffsetFrom = TimeSpan.FromHours(-8), _
	.OffsetTo = TimeSpan.FromHours(-9), _
	.RecurringRule = standardRecurring _
}

' Define daylight time offset
Dim daylightRecurring = New RecurringRule()
daylightRecurring.Frequency = Frequency.Yearly
daylightRecurring.ByDay.Add(New Weekday(2, Weekday.Sunday))
daylightRecurring.ByMonths.Add(3)

Dim daylight = New DaylightOffset() With { _
	.Name = "AKDT", _
	.Start = New DateTime(1970, 3, 8, 2, 0, 0), _
	.OffsetFrom = TimeSpan.FromHours(-9), _
	.OffsetTo = TimeSpan.FromHours(-8), _
	.RecurringRule = daylightRecurring _
}

alaska.Standard.Add(standard)
alaska.Daylight.Add(daylight)

' Define event
Dim e As [Event] = appointment.AddEvent()
e.Start = New DateTime(2007, 8, 17, 12, 0, 0)
e.[End] = New DateTime(2007, 8, 17, 12, 30, 0)
e.Summary = "At noon in Alaska"
e.InTimeZone(alaska)

' Make event recurring
Dim rule As RecurringRule = e.AddRecurringRule()
rule.Interval = 1
rule.Until = New DateTime(2011, 12, 1)
' -or- rule.Count = 10;
' Every week on  Mon, Tue, Wed, Thu Fri:
rule.Frequency = Frequency.Weekly
rule.ByDay.AddRange(New () {Weekday.Monday, Weekday.Tuesday, Weekday.Wednesday, Weekday.Thursday, Weekday.Friday})

' Set participants
e.SetOrganizer(New Person("Alice", "alice@example.org"))

e.AddParticipant( _
	New Participant("Bob", "bob@example.org", ParticipationRole.Required, True))
e.AddParticipant( _
	New Participant("Tom", "tom@example.org", ParticipationRole.[Optional], True))
e.AddParticipant( _
	New Participant("Alice", "alice@example.org", ParticipationRole.Required, True))

' Add alarm
Dim alarm As Alarm = e.AddAlarm()
alarm.BeforeStart(TimeSpan.FromMinutes(15))

Dim email As IMail = Fluent.Mail _
	.Text("Status meeting at noon in Alaska.") _
	.Subject("Status meeting") _
	.From("alice@example.org") _
	.[To]("bob@example.org") _
	.[To]("tom@example.org") _
	.AddAppointment(appointment) _
	.Create()

Using smtp As New Smtp()
	smtp.Connect("smtp.example.org") 	' or ConnectSSL
	smtp.UseBestLogin("user", "password")
	smtp.SendMessage(email)
	smtp.Close()
End Using

Western European Time Zone (WET)

Western European Time Zone (WET) with its Daylight Saving Time – Western European Summer Time (WEST) is defined below:

// Create time zone
VTimeZone western = appointment.AddTimeZone();
western.TimeZoneId = "W. Europe Standard Time";

// Define standard time offset
var standardRecurring = new RecurringRule();
standardRecurring.Frequency = Frequency.Yearly;
standardRecurring.ByDay.Add(new Weekday(-1, Weekday.Sunday));
standardRecurring.ByMonths.Add(10);

var standard = new StandardOffset
{
    Name = "WET", // Western European Time
    Start = new DateTime(1601,01,01,03,00,00),
    OffsetFrom = TimeSpan.FromHours(2),
    OffsetTo = TimeSpan.FromHours(1),
    RecurringRule = standardRecurring
};

// Define daylight time offset
var daylightRecurring = new RecurringRule();
daylightRecurring.Frequency = Frequency.Yearly;
daylightRecurring.ByDay.Add(new Weekday(-1, Weekday.Sunday));
daylightRecurring.ByMonths.Add(3);

var daylight = new DaylightOffset
{
    Name = "WEST", // Western European Summer Time
    Start = new DateTime(1601,01,01,02,00,00),
    OffsetFrom = TimeSpan.FromHours(1),
    OffsetTo = TimeSpan.FromHours(2),
    RecurringRule = daylightRecurring
};

western.Standard.Add(standard);
western.Daylight.Add(daylight);


Event e = appointment.AddEvent();
e.Start = new DateTime(2013, 04, 12, 15, 00, 00);
e.End = new DateTime(2013, 04, 12, 16, 00, 00);
e.Summary = "";
e.InTimeZone(western);

Tags: , , , ,

4 Responses to “Send iCalendar recurring meeting requests for different timezone”

  1. Ron Says:

    What are the valid values for “TimeZoneId”?
    Is there a way to programatically determine the proper value for the local machine?
    In this example ‘standard’ time and ‘daylight savings’ time are hard coded. Is there a way to add this info automatically or to read if from the local machine?

    Thank you
    Ron

  2. Limilabs support Says:

    @Ron,

    > What are the valid values for “TimeZoneId”?
    Any value is valid, as you are defining the timezone.
    When defining regular timezone I’d use time zone abbreviations defined here: http://www.timeanddate.com/library/abbreviations/timezones/

    > Is there a way to programatically determine the proper value for the local machine?
    You can use TimeZoneInfo class for that (it is available since .NET 4.0) in particular GetAdjustmentRules method is what you are after.

    > In this example ‘standard’ time and ‘daylight savings’ time are hard coded.
    If you are on .NET 4.0 or greater, you can use TimeZoneInfo class.

  3. Ron Says:

    Instead of adding a recurring rule, can I specify all the dates of the recurring meeting?

  4. Limilabs support Says:

    @Ron,

    With recurring rule, I don’t think iCalendar specification allows that.

    But you can add multiple events (with different start and end dates) to a single Appointment object using AddEvent() method.

Questions?

Consider using our Q&A forum for asking any questions.