Hello,
The fun that one can have with dates, time and time zones seems almost infinite. I just stumbled across an issue with the Scheduler component where deleting a single occurrence of an appointment series did not work correctly sometimes. Specifically, it doesn't work in my use case for daily and hourly recurrences, but works fine for the others. When it does not work, the problem is that the recurrence exceptions do not match the actual start time of the event that they are supposed to "except". For compatibility reasons with other libraries, we have to feed the scheduler with events that have all of their dates and times represented as DateTime with DateTime.Kind == DateTimeKind.Unspecified .
I traced the issue to the RecurrenceCalculator where for both the GetNextDailyOccurrence and GetNextHourlyOccurence, the DateTime of the exception is created from the original event's start date, but with the DateTimeKind explicitly set to UTC. For example, if I have a daily recurring event from 2025-08-11 13:00 to 14:00 (with unspecified DateTimeKind) and then I delete the occurrence for 2025-08-12 in the scheduler, then the exception that is added excludes "2025-08-12T14:00:00.000Z" (with UTC DateTimeKind) which is clearly not correct. It is also not consistent with the other recurrence frequencies.
In the code of the RecurrenceCalculator
new DateTime(year, month, day, date.Hour, date.Minute, date.Second, date.Millisecond, DateTimeKind.Utc)
creates a new UTC DateTime regardless of whether the original date had DateTimeKind UTC, local or unspecified. Therefore I'm pretty sure this qualifies as a bug. There is an argument to be had about which "way" would be correct as the rest of the code creates new DateTime instance with DateTimeKind.Unspecified instead by not specifying the kind at all.
I personally would argue that for all occurrences, new DateTime instances should always be created with the same kind as the original DateTime.
Also, the events that we are displaying definitely don't happen in the UTC time zone and converting everything to UTC is really not an option as the events would be displayed incorrectly. I also don't want to "reinterpret" all the times as UTC without actually converting the time because that would end up being extremely confusing.
Regards,
// Lukas Angerer