Does DDay Ical library calculate recurring rules correctly?
Asked Answered
E

3

6

I've run some tests. Here is my code:

var systemTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var icalTimeZone = iCalTimeZone.FromSystemTimeZone(systemTimeZone);

var startTimeSearch = new DateTime(2015, 9, 8, 0, 0, 0, DateTimeKind.Utc);
var endTimeSearch = new DateTime(2015, 12, 1, 00, 0, 0, DateTimeKind.Utc);

var iCalendar = new iCalendar();
var pacificTimeZone = _iCalendar.AddTimeZone(icalTimeZone);

var event = new Event
{
    Summary = "This is an event at 2015-09-08 10:30 PST (2015-09-08 17:30 UTC)",
    DTStart = new iCalDateTime(2015, 9, 8, 10, 30, 0, pacificTimeZone.TZID, iCalendar),
    Duration = new TimeSpan(0, 1, 0, 0)
};

var rp = new RecurrencePattern("FREQ=WEEKLY;UNTIL=20151112T080000Z;WKST=SU;BYDAY=TU");

event.RecurrenceRules.Add(rp);
iCalendar.Events.Add(_event);
var occurrences = iCalendar.GetOccurrences(startTimeSearch, endTimeSearch);

Here's the result:

10 occurences - here are the occurences' Period.StartTime.Value and UTC properties

Value - 9/8/2015 10:30:00 - UTC 9/8/2015 17:30:00
Value - 9/15/2015 10:30:00 - UTC 9/15/2015 17:30:00
Value - 9/22/2015 10:30:00 - UTC 9/22/2015 17:30:00
Value - 9/29/2015 10:30:00 - UTC 9/29/2015 17:30:00
Value - 10/6/2015 10:30:00 - UTC 10/6/2015 17:30:00
Value - 10/13/2015 10:30:00 - UTC 10/13/2015 17:30:00
Value - 10/20/2015 10:30:00 - UTC 10/20/2015 17:30:00
Value - 10/27/2015 10:30:00 - UTC 10/27/2015 17:30:00
Value -11/3/2015 10:30:00 - UTC 11/3/2015 17:30:00 (THIS SHOULD BE 18:30:00!)
Value - 11/10/2015 10:30:00 - UTC 11/10/2015 17:30:00 (THIS SHOULD BE 18:30:00!)

enter image description here

As you can see, the last two should have a UTC time of 18:30:00. So I'm wondering if this is just the way DDay Ical works and I shouldn't count on it getting the UTC datetime right, or if I'm doing something wrong.

Elasticize answered 25/6, 2016 at 6:27 Comment(1)
could it have something to do with daylight savings?Gunnysack
N
8

You are getting this time difference due to daylight savings. One possible solution is not to get the time zone by name Pacific Standard Time

 // First load a file containing time zone information for Pacific Standard Time
var systemTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");

In place of this use system time zone like

var systemTimeZone = TimeZoneInfo.GetSystemTimeZones().FirstOrDefault();

Or simply add the local timezone:

iCalendar iCalendar= new iCalendar();
iCalendar.AddLocalTimeZone();

To find all registered timezones, click here

ReadOnlyCollection<TimeZoneInfo> zones = TimeZoneInfo.GetSystemTimeZones();
Console.WriteLine("The local system has the following {0} time zones", zones.Count);
foreach (TimeZoneInfo zone in zones)
   Console.WriteLine(zone.Id);

I simply use GetSystemTimeZones() in my code like

public static void Test1()
    {
        var systemTimeZone = TimeZoneInfo.GetSystemTimeZones().FirstOrDefault();
        //TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
        var icalTimeZone = iCalTimeZone.FromSystemTimeZone(systemTimeZone);

        var startTimeSearch = new DateTime(2015, 9, 8, 0, 0, 0, DateTimeKind.Utc);
        var endTimeSearch = new DateTime(2015, 12, 1, 00, 0, 0, DateTimeKind.Utc);

        var iCalendar = new iCalendar();
        var pacificTimeZone = iCalendar.AddTimeZone(icalTimeZone);

        var _event =
        new Event
        {
            Summary = "This is an event at 2015-09-08 10:30 PST (2015-09-08 17:30 UTC)",
            DTStart = new iCalDateTime(2015, 9, 8, 10, 30, 0, pacificTimeZone.TZID, iCalendar),
            Duration = new TimeSpan(0, 1, 0, 0)
        };

        var rp = new RecurrencePattern("FREQ=WEEKLY;UNTIL=20151112T080000Z;WKST=SU;BYDAY=TU");

        _event.RecurrenceRules.Add(rp);
        iCalendar.Events.Add(_event);

        var occurrences = iCalendar.GetOccurrences(startTimeSearch, endTimeSearch);
    }

when I debug it got got output like

stack

you can change the time zone accordingly and get the result. Hope it helps you.

Natiha answered 27/6, 2016 at 9:55 Comment(3)
Thanks. I'm aware of the issue with Daylight savings. As my question shows, I am getting the correct PST values - it's the UTC that is incorrect. I don't see how your answer solves my problem.Elasticize
Ok so the answer would be no, DDay Ical doesn't calculate occurences correctly. Is that correct?Elasticize
I don't think it's a mistake or bug. This is how DDay is design. And the occurrences is correct if you keep day light saving in mind.Natiha
D
2

Don't use dday.ical; use ical.net.

This should get you started:

var iCalendar = new Calendar();

var start = new DateTime(2015, 9, 8, 10, 30, 0);
var e = new Event
{
    Summary = "This is an event at 2015-09-08 10:30 PST (2015-09-08 17:30 UTC)",
    DtStart = new CalDateTime(start, "Pacific Standard Time"),
    Duration = TimeSpan.FromHours(1)
};

var rp = new RecurrencePattern("FREQ=WEEKLY;UNTIL=20151112T080000Z;WKST=SU;BYDAY=TU");
e.RecurrenceRules.Add(rp);
iCalendar.Events.Add(e);

var startTimeSearch = new DateTime(2015, 9, 8, 0, 0, 0, DateTimeKind.Utc);
var endTimeSearch = new DateTime(2015, 12, 1, 00, 0, 0, DateTimeKind.Utc);
var occurrences = iCalendar.GetOccurrences(startTimeSearch, endTimeSearch);

Results:

ical-net-recurrence-result

Dunstable answered 27/8, 2016 at 18:53 Comment(0)
G
0

I could resolve this. It turns out that you shouldn't specify the time in the ExceptionDates, just add the date component only,

That seems to work, GetOccurances now properly recognizes the exception dates. Hopefully this will help someone going through the same pain.

Guff answered 20/4, 2018 at 22:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.