Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ex date fixes #261

Merged
merged 6 commits into from
Apr 6, 2017
Merged
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
8 changes: 8 additions & 0 deletions NugetTester/NugetTester/Program.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Ical.Net;
using Ical.Net.DataTypes;
using Ical.Net.Interfaces.Components;
using Ical.Net.Interfaces.DataTypes;
using Ical.Net.Serialization.iCalendar.Serializers;

namespace NugetTester
{
Expand All @@ -27,5 +31,9 @@ private static CalendarCollection DeserializeCalendar(string ical)
return Calendar.LoadFromStream(reader) as CalendarCollection;
}
}

private static string SerializeToString(IEvent calendarEvent) => SerializeToString(new Calendar { Events = { calendarEvent } });

private static string SerializeToString(Calendar iCalendar) => new CalendarSerializer().SerializeToString(iCalendar);
}
}
78 changes: 39 additions & 39 deletions net-core/Ical.Net/Ical.Net.UnitTests/CalendarEventTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.IO;
using System.Linq;
using Ical.Net.Serialization.iCalendar.Serializers;
using NUnit.Framework.Interfaces;

namespace Ical.Net.UnitTests
{
Expand All @@ -19,10 +20,10 @@ public class CalendarEventTest
/// <summary>
/// Ensures that events can be properly added to a calendar.
/// </summary>
[Test, Category("Event")]
[Test, Category("CalendarEvent")]
public void Add1()
{
Calendar cal = new Calendar();
var cal = new Calendar();

var evt = new CalendarEvent
{
Expand All @@ -33,16 +34,16 @@ public void Add1()

cal.Events.Add(evt);
Assert.AreEqual(1, cal.Children.Count);
Assert.AreSame(evt, cal.Children[0]);
Assert.AreSame(evt, cal.Children[0]);
}

/// <summary>
/// Ensures that events can be properly removed from a calendar.
/// </summary>
[Test, Category("Event")]
[Test, Category("CalendarEvent")]
public void Remove1()
{
Calendar cal = new Calendar();
var cal = new Calendar();

var evt = new CalendarEvent
{
Expand All @@ -63,10 +64,10 @@ public void Remove1()
/// <summary>
/// Ensures that events can be properly removed from a calendar.
/// </summary>
[Test, Category("Event")]
[Test, Category("CalendarEvent")]
public void Remove2()
{
Calendar cal = new Calendar();
var cal = new Calendar();

var evt = new CalendarEvent
{
Expand All @@ -87,10 +88,10 @@ public void Remove2()
/// <summary>
/// Ensures that event DTSTAMP is set.
/// </summary>
[Test, Category("Event")]
[Test, Category("CalendarEvent")]
public void EnsureDTSTAMPisNotNull()
{
Calendar cal = new Calendar();
var cal = new Calendar();

// Do not set DTSTAMP manually
var evt = new CalendarEvent
Expand All @@ -107,10 +108,10 @@ public void EnsureDTSTAMPisNotNull()
/// <summary>
/// Ensures that automatically set DTSTAMP property is of kind UTC.
/// </summary>
[Test, Category("Event")]
[Test, Category("CalendarEvent")]
public void EnsureDTSTAMPisOfTypeUTC()
{
Calendar cal = new Calendar();
var cal = new Calendar();

var evt = new CalendarEvent
{
Expand All @@ -124,40 +125,39 @@ public void EnsureDTSTAMPisOfTypeUTC()
}

/// <summary>
/// Ensures that correct set DTSTAMP property is being serialized with kind UTC.
/// Ensures that automatically set DTSTAMP property is being serialized with kind UTC.
/// </summary>
[Test, Category("Deserialization")]
public void EnsureCorrectSetDTSTAMPisSerializedAsKindUTC()
[Test, Category("Deserialization"), TestCaseSource(nameof(EnsureAutomaticallySetDtStampIsSerializedAsUtcKind_TestCases))]
public bool EnsureAutomaticallySetDTSTAMPisSerializedAsKindUTC(string serialized)
{
var ical = new Ical.Net.Calendar();
var evt = new Ical.Net.CalendarEvent();
evt.DtStamp = new CalDateTime(new DateTime(2016, 8, 17, 2, 30, 0, DateTimeKind.Utc));
ical.Events.Add(evt);

var serializer = new Ical.Net.Serialization.iCalendar.Serializers.CalendarSerializer();
var serializedCalendar = serializer.SerializeToString(ical);

var lines = serializedCalendar.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
var lines = serialized.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
var result = lines.First(s => s.StartsWith("DTSTAMP"));
Assert.AreEqual("DTSTAMP:20160817T023000Z", result);

//Both of these are correct, since the library no longer asserts that UTC must elide an explicit TZID in favor of the Z suffix on UTC times
return !result.Contains("TZID=") && result.EndsWith("Z")
|| result.Contains("TZID=") && !result.EndsWith("Z");
}

/// <summary>
/// Ensures that automatically set DTSTAMP property is being serialized with kind UTC.
/// </summary>
[Test, Category("Deserialization")]
public void EnsureAutomaticallySetDTSTAMPisSerializedAsKindUTC()
public static IEnumerable<ITestCaseData> EnsureAutomaticallySetDtStampIsSerializedAsUtcKind_TestCases()
{
var ical = new Ical.Net.Calendar();
var evt = new Ical.Net.CalendarEvent();
ical.Events.Add(evt);
var emptyCalendar = new Calendar();
var evt = new CalendarEvent();
emptyCalendar.Events.Add(evt);

var serializer = new Ical.Net.Serialization.iCalendar.Serializers.CalendarSerializer();
var serializedCalendar = serializer.SerializeToString(ical);
var serializer = new CalendarSerializer();
yield return new TestCaseData(serializer.SerializeToString(emptyCalendar))
.SetName("Empty calendar with empty event returns true")
.Returns(true);

var lines = serializedCalendar.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
var result = lines.First(s => s.StartsWith("DTSTAMP"));
Assert.AreEqual($"DTSTAMP:{evt.DtStamp.Year}{evt.DtStamp.Month:00}{evt.DtStamp.Day:00}T{evt.DtStamp.Hour:00}{evt.DtStamp.Minute:00}{evt.DtStamp.Second:00}Z", result);
var explicitDtStampCalendar = new Calendar();
var explicitDtStampEvent = new CalendarEvent
{
DtStamp = new CalDateTime(new DateTime(2016, 8, 17, 2, 30, 0, DateTimeKind.Utc))
};
explicitDtStampCalendar.Events.Add(explicitDtStampEvent);
yield return new TestCaseData(serializer.SerializeToString(explicitDtStampCalendar))
.SetName("CalendarEvent with explicitly-set DTSTAMP property returns true")
.Returns(true);
}

[Test]
Expand Down Expand Up @@ -221,6 +221,7 @@ public void EventWithExDateShouldNotBeEqualToSameEventWithoutExDate()
{
DtStart = new CalDateTime(_now),
DtEnd = new CalDateTime(_later),
Uid = _uid,
};

[Test]
Expand Down Expand Up @@ -281,7 +282,7 @@ public void AddingExdateToEventShouldNotBeEqualToOriginal()
//Serialize to string, and deserialize
//Change the original calendar.Event to have an ExDate
//Serialize to string, and deserialize
//Event and Calendar hash codes and equality should NOT be the same
//CalendarEvent and Calendar hash codes and equality should NOT be the same
var serializer = new CalendarSerializer();

var vEvent = GetSimpleEvent();
Expand Down Expand Up @@ -423,7 +424,6 @@ public void HourMinuteSecondOffsetParsingTest()
END:STANDARD
END:VTIMEZONE
END:VCALENDAR";

using (var reader = new StringReader(ical))
{
var timezones = Calendar.LoadFromStream(reader)
Expand Down
25 changes: 1 addition & 24 deletions net-core/Ical.Net/Ical.Net.UnitTests/DateTimeSerializerTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Linq;
using Ical.Net.DataTypes;
using Ical.Net.Serialization.iCalendar.Serializers.DataTypes;
using NUnit.Framework;
Expand All @@ -9,38 +8,16 @@ namespace Ical.Net.UnitTests.Serialization.iCalendar.Serializers.DataTypes
[TestFixture]
public class DateTimeSerializerTests
{
[Test, Category("Deserialization")]
public void TZIDPropertyMustNotBeAppliedToUtcDateTime()
{
var ical = new Ical.Net.Calendar();
var evt = new Ical.Net.CalendarEvent();
evt.DtStamp = new CalDateTime(new DateTime(2016, 8, 17, 2, 30, 0, DateTimeKind.Utc));
ical.Events.Add(evt);

var serializer = new Ical.Net.Serialization.iCalendar.Serializers.CalendarSerializer();
var serializedCalendar = serializer.SerializeToString(ical);

var lines = serializedCalendar.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
var result = lines.First(s => s.StartsWith("DTSTAMP"));
Assert.AreEqual("DTSTAMP:20160817T023000Z", result);
}

[Test, Category("Deserialization")]
public void TZIDPropertyShouldBeAppliedForLocalTimezones()
{
// see http://www.ietf.org/rfc/rfc2445.txt p.36
var result = DateTimeSerializer()
var result = new DateTimeSerializer()
.SerializeToString(
new CalDateTime(new DateTime(1997, 7, 14, 13, 30, 0, DateTimeKind.Local), "US-Eastern"));

// TZID is applied elsewhere - just make sure this doesn't have 'Z' appended.
Assert.AreEqual("19970714T133000", result);
}


private static DateTimeSerializer DateTimeSerializer()
{
return new DateTimeSerializer();
}
}
}
54 changes: 54 additions & 0 deletions net-core/Ical.Net/Ical.Net.UnitTests/RecurrenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using Ical.Net.DataTypes;
using Ical.Net.Evaluation;
Expand All @@ -12,6 +13,7 @@
using Ical.Net.Serialization.iCalendar.Serializers.DataTypes;
using Ical.Net.Utility;
using NUnit.Framework;
using static Ical.Net.UnitTests.SerializationHelpers;

namespace Ical.Net.UnitTests
{
Expand Down Expand Up @@ -3128,5 +3130,57 @@ private static CalendarEvent GetEventWithRecurrenceRules()
};
return calendarEvent;
}

[Test]
public void ExDateFold_Tests()
{
var start = _now.AddYears(-1);
var end = start.AddHours(1);
var rrule = new RecurrencePattern(FrequencyType.Daily) { Until = start.AddYears(2) };
var e = new CalendarEvent
{
DtStart = new CalDateTime(start),
DtEnd = new CalDateTime(end),
RecurrenceRules = new List<RecurrencePattern> { rrule }
};

var firstExclusion = new CalDateTime(start.AddDays(4));
e.ExceptionDates = new List<PeriodList> { new PeriodList { new Period(firstExclusion) } };
var serialized = SerializeToString(e);
Assert.AreEqual(1, Regex.Matches(serialized, "EXDATE:").Count);

var secondExclusion = new CalDateTime(start.AddDays(5));
e.ExceptionDates.First().Add(new Period(secondExclusion));
serialized = SerializeToString(e);
Assert.AreEqual(1, Regex.Matches(serialized, "EXDATE:").Count);
}

[Test]
public void ExDateTimeZone_Tests()
{
const string tzid = "Europe/Stockholm";

//Repeat daily for 10 days
var rrule = new RecurrencePattern(FrequencyType.Daily, 1) { Count = 10 };

var e = new CalendarEvent
{
DtStart = new CalDateTime(_now, tzid),
DtEnd = new CalDateTime(_later, tzid),
RecurrenceRules = new List<RecurrencePattern> { rrule },
};

var exceptionDateList = new PeriodList { TzId = tzid };
exceptionDateList.Add(new Period(new CalDateTime(_now.AddDays(1))));
e.ExceptionDates.Add(exceptionDateList);

var serialized = SerializeToString(e);
const string expected = "TZID=Europe/Stockholm";
Assert.AreEqual(3, Regex.Matches(serialized, expected).Count);

e.ExceptionDates.First().Add(new Period(new CalDateTime(_now.AddDays(2))));
serialized = SerializeToString(e);
Assert.AreEqual(3, Regex.Matches(serialized, expected).Count);
}
}
}
28 changes: 28 additions & 0 deletions net-core/Ical.Net/Ical.Net.UnitTests/SerializationHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.IO;
using System.Linq;
using Ical.Net.Serialization.iCalendar.Serializers;

namespace Ical.Net.UnitTests
{
internal class SerializationHelpers
{
public static CalendarEvent DeserializeCalendarEvent(string ical)
{
var calendar = DeserializeCalendar(ical);
var calendarEvent = calendar.First().Events.First();
return calendarEvent;
}

public static CalendarCollection DeserializeCalendar(string ical)
{
using (var reader = new StringReader(ical))
{
return Calendar.LoadFromStream(reader);
}
}

public static string SerializeToString(CalendarEvent calendarEvent) => SerializeToString(new Calendar { Events = { calendarEvent } });

public static string SerializeToString(Calendar iCalendar) => new CalendarSerializer().SerializeToString(iCalendar);
}
}
2 changes: 1 addition & 1 deletion net-core/Ical.Net/Ical.Net.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Ical.Net</id>
<version>3.0.1-net-core-alpha</version>
<version>3.0.3-net-core-alpha</version>
<title>Ical.Net</title>
<authors>Rian Stockbower, Douglas Day, M. David Peterson</authors>
<owners>Rian Stockbower</owners>
Expand Down
29 changes: 28 additions & 1 deletion net-core/Ical.Net/Ical.Net/DataTypes/PeriodList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Ical.Net.DataTypes
/// <summary>
/// An iCalendar list of recurring dates (or date exclusions)
/// </summary>
public class PeriodList : EncodableDataType, IEnumerable<Period>
public class PeriodList : EncodableDataType, IList<Period>
{
public string TzId { get; set; }
public int Count => Periods.Count;
Expand Down Expand Up @@ -80,5 +80,32 @@ public Period this[int index]
public IEnumerator<Period> GetEnumerator() => Periods.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => Periods.GetEnumerator();
public void Clear()
{
Periods.Clear();
}

public bool Contains(Period item) => Periods.Contains(item);

public void CopyTo(Period[] array, int arrayIndex)
{
Periods.CopyTo(array, arrayIndex);
}

public bool Remove(Period item) => Periods.Remove(item);

public bool IsReadOnly => Periods.IsReadOnly;

public int IndexOf(Period item) => Periods.IndexOf(item);

public void Insert(int index, Period item)
{
Periods.Insert(index, item);
}

public void RemoveAt(int index)
{
Periods.RemoveAt(index);
}
}
}
Loading