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);
January 16th, 2017 at 17:59
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
January 17th, 2017 at 08:10
@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.
April 11th, 2017 at 17:16
Instead of adding a recurring rule, can I specify all the dates of the recurring meeting?
April 15th, 2017 at 15:06
@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.