Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions Ical.Net.Benchmarks/OccurencePerfTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ public void GetOccurrences()
public void MultipleEventsWithUntilOccurrencesSearchingByWholeCalendar()
{
var searchStart = _calendarFourEvents.Events.First().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(-1)
.InZoneLeniently(tz);

var searchEnd = _calendarFourEvents.Events.Last().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(1)
.InZoneLeniently(tz)
Expand All @@ -59,13 +59,13 @@ public void MultipleEventsWithUntilOccurrencesSearchingByWholeCalendar()
public void MultipleEventsWithUntilOccurrences()
{
var searchStart = _calendarFourEvents.Events.First().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(-1)
.InZoneLeniently(tz);

var searchEnd = _calendarFourEvents.Events.Last().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(1)
.InZoneLeniently(tz)
Expand All @@ -80,13 +80,13 @@ public void MultipleEventsWithUntilOccurrences()
public void MultipleEventsWithUntilOccurrencesEventsAsParallel()
{
var searchStart = _calendarFourEvents.Events.First().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(-1)
.InZoneLeniently(tz);

var searchEnd = _calendarFourEvents.Events.Last().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(1)
.PlusDays(10)
Expand Down Expand Up @@ -195,13 +195,13 @@ public void MultipleEventsWithCountOccurrencesSearchingByWholeCalendar()
{
var calendar = GetFourCalendarEventsWithCountRule();
var searchStart = _calendarFourEvents.Events.First().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(-1)
.InZoneLeniently(tz);

var searchEnd = _calendarFourEvents.Events.Last().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(1)
.InZoneLeniently(tz)
Expand All @@ -215,13 +215,13 @@ public void MultipleEventsWithCountOccurrences()
{
var calendar = GetFourCalendarEventsWithCountRule();
var searchStart = _calendarFourEvents.Events.First().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(-1)
.InZoneLeniently(tz);

var searchEnd = _calendarFourEvents.Events.Last().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(1)
.InZoneLeniently(tz)
Expand All @@ -237,13 +237,13 @@ public void MultipleEventsWithCountOccurrencesEventsAsParallel()
{
var calendar = GetFourCalendarEventsWithCountRule();
var searchStart = _calendarFourEvents.Events.First().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(-1)
.InZoneLeniently(tz);

var searchEnd = _calendarFourEvents.Events.Last().DtStart!
.ToZonedOrDefault(tz)
.ToZonedOrDefault(tz, _calendarFourEvents.TimeZoneProvider)
.LocalDateTime
.PlusYears(1)
.PlusDays(10)
Expand Down
6 changes: 4 additions & 2 deletions Ical.Net.Tests/DeserializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ public void Bug2938007()
Assert.That(evt.End?.HasTime, Is.True);
}

var results = evt.GetOccurrences(new LocalDateTime(2010, 1, 17, 0, 0, 0).InZoneLeniently("Asia/Tokyo"))
.TakeWhileBefore(new LocalDateTime(2010, 2, 1, 0, 0, 0).InZoneLeniently("Asia/Tokyo").ToInstant());
var tz = iCal.TimeZoneProvider["Asia/Tokyo"];

var results = evt.GetOccurrences(new LocalDateTime(2010, 1, 17, 0, 0, 0).InZoneLeniently(tz))
.TakeWhileBefore(new LocalDateTime(2010, 2, 1, 0, 0, 0).InZoneLeniently(tz).ToInstant());

foreach (var o in results)
{
Expand Down
10 changes: 5 additions & 5 deletions Ical.Net.Tests/FreeBusyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.Collections.Generic;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
using Ical.Net.Utility;
using NodaTime;
using NUnit.Framework;
using Duration = Ical.Net.DataTypes.Duration;
Expand All @@ -31,8 +30,10 @@ public void GetFreeBusyStatusByDateTime()
evt.Start = new CalDateTime(2025, 10, 1, 8, 0, 0);
evt.End = new CalDateTime(2025, 10, 1, 9, 0, 0);

var tz = cal.TimeZoneProvider["America/New_York"];

var freeBusy = cal.GetFreeBusy(
DateUtil.GetZone("America/New_York"),
tz,
new CalDateTime(2025, 10, 1, 0, 0, 0),
new CalDateTime(2025, 10, 7, 11, 59, 59))!;

Expand Down Expand Up @@ -60,7 +61,7 @@ public void GetFreeBusyStatusByPeriod()
evt.End = new CalDateTime(2025, 6, 1, 10, 0, 0);

var freeBusy = cal.GetFreeBusy(
DateUtil.GetZone("UTC"),
cal.TimeZoneProvider["UTC"],
new CalDateTime(2025, 6, 1, 0, 0, 0, "UTC"),
new CalDateTime(2025, 6, 7, 0, 0, 0, "UTC"))!;

Expand Down Expand Up @@ -106,7 +107,6 @@ public void Contains_Tests()
var periodWithDuration = new FreeBusyEntry(new(start.InUtc().ToCalDateTime(), Duration.FromHours(1)), FreeBusyStatus.Free);
using (Assert.EnterMultipleScope())
{
Assert.That(periodWithDuration.Contains(null), Is.False, "Contains should return false for null dt.");
Assert.That(periodWithDuration.Contains(dtBefore), Is.False, "Contains should return false if dt is before start.");
Assert.That(periodWithDuration.Contains(dtAtStart), Is.True, "Contains should return true for dt equal to start.");
Assert.That(periodWithDuration.Contains(dtMid), Is.True, "Contains should return true for dt in the middle.");
Expand Down Expand Up @@ -263,7 +263,7 @@ public void CreateFiltersOccurrencesByRequestAttendees()
{
Assert.That(freeBusy.Entries, Has.Count.EqualTo(1));
Assert.That(freeBusy.Entries[0].Status, Is.EqualTo(FreeBusyStatus.Busy));
Assert.That(freeBusy.Entries[0].StartTime.ToDateTimeUtc(), Is.EqualTo(busyEvent.Start.ToDateTimeUtc()));
Assert.That(freeBusy.Entries[0].StartTime, Is.EqualTo(new CalDateTime(2025, 9, 1, 9, 0, 0, "UTC")));
}
}

Expand Down
105 changes: 105 additions & 0 deletions Ical.Net.Tests/MatchTimeZoneTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using System;
using System.Linq;
using Ical.Net.DataTypes;
using NodaTime;
using NodaTime.TimeZones;
using NUnit.Framework;

namespace Ical.Net.Tests;
Expand Down Expand Up @@ -241,4 +243,107 @@ public void MatchTimeZone_DateOnly()
Assert.That(occurrences.Count, Is.EqualTo(5));
}
}

[Test, Category("Recurrence")]
public void MatchTimeZone_CaseInsensitive_EventEval()
{
const string ical =
"""
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp//NONSGML Event//EN
BEGIN:VEVENT
UID:example1
SUMMARY:Event with local time and time zone
DTSTART;TZID=America/New_york:20231101T090000
RRULE:FREQ=DAILY;UNTIL=20231105T130000Z
DTEND;TZID=America/New_york:20231101T100000
END:VEVENT
END:VCALENDAR
""";

var calendar = Calendar.Load(ical)!;
var evt = calendar.Events.First();

// Throws because the default time zone provider
// expects "New_York" instead of "New_york".
Assert.Throws<DateTimeZoneNotFoundException>(() =>
{
var _ = evt.GetOccurrences(new CalDateTime(2023, 11, 01))
.TakeWhileBefore(new CalDateTime(2023, 11, 06));
});

// Set the calendar time zone provider to ignore case
calendar.TimeZoneProvider = CalendarTimeZoneProviders.TzdbWithAliasesIgnoreCase;

var occurrences = evt.GetOccurrences(new CalDateTime(2023, 11, 01))
.TakeWhileBefore(new CalDateTime(2023, 11, 06))
.ToList();

using (Assert.EnterMultipleScope())
{
Assert.That(occurrences, Has.Count.EqualTo(4));
Assert.That(occurrences[0].Start.Zone.Id, Is.EqualTo("America/New_York"));
}
}

[Test, Category("Recurrence")]
public void MatchTimeZone_CaseInsensitive_CalendarEval()
{
const string ical =
"""
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp//NONSGML Event//EN
BEGIN:VEVENT
UID:example1
SUMMARY:Event with local time and time zone
DTSTART;TZID=America/New_york:20231101T090000
RRULE:FREQ=DAILY;UNTIL=20231105T130000Z
DTEND;TZID=America/New_york:20231101T100000
END:VEVENT
BEGIN:VEVENT
UID:example2
SUMMARY:Event with local time and time zone
DTSTART;TZID=us-eastern:20231101T100000
RRULE:FREQ=DAILY;UNTIL=20231105T130000Z
DTEND;TZID=us-eastern:20231101T110000
END:VEVENT
BEGIN:VEVENT
UID:example3
SUMMARY:Event with local time and time zone
DTSTART;TZID=eastern standard time:20231101T110000
RRULE:FREQ=DAILY;UNTIL=20231105T130000Z
DTEND;TZID=eastern standard time:20231101T120000
END:VEVENT
END:VCALENDAR
""";

var calendar = Calendar.Load(ical)!;

var tz = calendar.TimeZoneProvider.GetZoneOrNull("America/Los_Angeles")!;

var start = new LocalDate(2023, 11, 1).AtStartOfDayInZone(tz);
var end = new LocalDate(2023, 11, 6).AtStartOfDayInZone(tz).ToInstant();

// Throws because the default time zone provider
// expects "New_York" instead of "New_york".
Assert.Throws<DateTimeZoneNotFoundException>(() =>
{
var _ = calendar.GetOccurrences(start).TakeWhileBefore(end);
});

// Set the calendar time zone provider to ignore case
calendar.TimeZoneProvider = CalendarTimeZoneProviders.TzdbWithAliasesIgnoreCase;

var occurrences = calendar.GetOccurrences(start)
.TakeWhileBefore(end)
.ToList();

using (Assert.EnterMultipleScope())
{
Assert.That(occurrences, Has.Count.EqualTo(12));
Assert.That(occurrences[0].Start.Zone.Id, Is.EqualTo("America/Los_Angeles"));
}
}
}
77 changes: 40 additions & 37 deletions Ical.Net.Tests/ProgramTest.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
//
//
// Copyright ical.net project maintainers and contributors.
// Licensed under the MIT license.
//

using System;
using System.Linq;
using Ical.Net.DataTypes;
using NodaTime;
using NUnit.Framework;

namespace Ical.Net.Tests;
Expand Down Expand Up @@ -49,24 +50,26 @@ public void Merge1()
var evt1 = iCal1.Events.First();
var evt2 = iCal1.Events.Skip(1).First();

var tz = iCal1.TimeZoneProvider[_tzid];

// Get occurrences for the first event
var occurrences = evt1.GetOccurrences(
new CalDateTime(1996, 1, 1).ToZonedDateTime(_tzid))
.TakeWhileBefore(new CalDateTime(2000, 1, 1).ToZonedDateTime(_tzid).ToInstant()).ToList();
new LocalDate(1996, 1, 1).AtStartOfDayInZone(tz))
.TakeWhileBefore(new LocalDate(2000, 1, 1).AtStartOfDayInZone(tz).ToInstant()).ToList();

var dateTimes = new[]
var dateTimes = new LocalDate[]
{
new CalDateTime(1997, 9, 10, 9, 0, 0, _tzid).ToZonedDateTime(),
new CalDateTime(1997, 9, 11, 9, 0, 0, _tzid).ToZonedDateTime(),
new CalDateTime(1997, 9, 12, 9, 0, 0, _tzid).ToZonedDateTime(),
new CalDateTime(1997, 9, 13, 9, 0, 0, _tzid).ToZonedDateTime(),
new CalDateTime(1997, 9, 14, 9, 0, 0, _tzid).ToZonedDateTime(),
new CalDateTime(1997, 9, 15, 9, 0, 0, _tzid).ToZonedDateTime(),
new CalDateTime(1999, 3, 10, 9, 0, 0, _tzid).ToZonedDateTime(),
new CalDateTime(1999, 3, 11, 9, 0, 0, _tzid).ToZonedDateTime(),
new CalDateTime(1999, 3, 12, 9, 0, 0, _tzid).ToZonedDateTime(),
new CalDateTime(1999, 3, 13, 9, 0, 0, _tzid).ToZonedDateTime(),
};
new(1997, 9, 10),
new(1997, 9, 11),
new(1997, 9, 12),
new(1997, 9, 13),
new(1997, 9, 14),
new(1997, 9, 15),
new(1999, 3, 10),
new(1999, 3, 11),
new(1999, 3, 12),
new(1999, 3, 13),
}.Select(x => x.At(new LocalTime(9, 0)).InZoneStrictly(tz)).ToArray();

for (var i = 0; i < dateTimes.Length; i++)
{
Expand All @@ -79,30 +82,30 @@ public void Merge1()

// Get occurrences for the 2nd event
occurrences = evt2.GetOccurrences(
new CalDateTime(1996, 1, 1).ToZonedDateTime(_tzid))
.TakeWhileBefore(new CalDateTime(1998, 4, 1).ToZonedDateTime(_tzid).ToInstant()).ToList();
new LocalDate(1996, 1, 1).AtStartOfDayInZone(tz))
.TakeWhileBefore(new LocalDate(1998, 4, 1).AtStartOfDayInZone(tz).ToInstant()).ToList();

var dateTimes1 = new[]
var dateTimes1 = new LocalDate[]
{
new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid),
new CalDateTime(1997, 9, 9, 9, 0, 0, _tzid),
new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid),
new CalDateTime(1997, 9, 23, 9, 0, 0, _tzid),
new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid),
new CalDateTime(1997, 11, 4, 9, 0, 0, _tzid),
new CalDateTime(1997, 11, 11, 9, 0, 0, _tzid),
new CalDateTime(1997, 11, 18, 9, 0, 0, _tzid),
new CalDateTime(1997, 11, 25, 9, 0, 0, _tzid),
new CalDateTime(1998, 1, 6, 9, 0, 0, _tzid),
new CalDateTime(1998, 1, 13, 9, 0, 0, _tzid),
new CalDateTime(1998, 1, 20, 9, 0, 0, _tzid),
new CalDateTime(1998, 1, 27, 9, 0, 0, _tzid),
new CalDateTime(1998, 3, 3, 9, 0, 0, _tzid),
new CalDateTime(1998, 3, 10, 9, 0, 0, _tzid),
new CalDateTime(1998, 3, 17, 9, 0, 0, _tzid),
new CalDateTime(1998, 3, 24, 9, 0, 0, _tzid),
new CalDateTime(1998, 3, 31, 9, 0, 0, _tzid)
}.Select(x => x.ToZonedDateTime()).ToArray();
new (1997, 9, 2),
new (1997, 9, 9),
new (1997, 9, 16),
new (1997, 9, 23),
new (1997, 9, 30),
new (1997, 11, 4),
new (1997, 11, 11),
new (1997, 11, 18),
new (1997, 11, 25),
new (1998, 1, 6),
new (1998, 1, 13),
new (1998, 1, 20),
new (1998, 1, 27),
new (1998, 3, 3),
new (1998, 3, 10),
new (1998, 3, 17),
new (1998, 3, 24),
new (1998, 3, 31)
}.Select(x => x.At(new LocalTime(9, 0)).InZoneStrictly(tz)).ToArray();

using (Assert.EnterMultipleScope())
{
Expand Down
14 changes: 0 additions & 14 deletions Ical.Net.Tests/RecurrenceIdentifierTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,5 @@ public void RecurrenceIdentifierSerializer_LowLevel()
}
}

[TestCase("20250831", RecurrenceRange.ThisInstance, 1)] // other earlier
[TestCase("20250901", RecurrenceRange.ThisInstance, 0)] // same date, same range
[TestCase("20250901", RecurrenceRange.ThisAndFuture, -1)] // same date, higher range
[TestCase("20250902", RecurrenceRange.ThisInstance, -1)] // other later
[TestCase("20250902", RecurrenceRange.ThisAndFuture, -1)] // other later, higher range
public void CompareToTests(string dt, RecurrenceRange range, int expected)
{
var self = new RecurrenceIdentifier(new CalDateTime("20250901"), RecurrenceRange.ThisInstance);
var other = new RecurrenceIdentifier(new CalDateTime(dt), range);

Assert.That(self.CompareTo(other), Is.EqualTo(expected));
Assert.That(self.CompareTo(null), Is.EqualTo(1));
}

#pragma warning restore CS0618 // Type or member is obsolete
}
Loading
Loading