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

V2 fixes for RecurrenceUtil.GetOccurrences and CalDateTime.ToTimeZone #368

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
12 changes: 6 additions & 6 deletions v2/ical.NET.UnitTests/EqualityAndHashingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,12 @@ public void Resources_Tests()
Assert.IsFalse(serialized.Contains("Hello"));
}

internal static (byte[] original, byte[] copy) GetAttachments()
internal static Tuple<byte[] /*original*/, byte[] /*copy*/> GetAttachments()
{
var payload = Encoding.UTF8.GetBytes("This is an attachment!");
var payloadCopy = new byte[payload.Length];
Array.Copy(payload, payloadCopy, payload.Length);
return (payload, payloadCopy);
return Tuple.Create(payload, payloadCopy);
}

[Test, TestCaseSource(nameof(RecurringComponentAttachment_TestCases))]
Expand All @@ -275,7 +275,7 @@ public void RecurringComponentAttachmentTests(RecurringComponent noAttachment, R
Assert.AreNotEqual(noAttachment, withAttachment);
Assert.AreNotEqual(noAttachment.GetHashCode(), withAttachment.GetHashCode());

noAttachment.Attachments.Add(new Attachment(attachments.copy));
noAttachment.Attachments.Add(new Attachment(attachments.Item2/*copy*/));

Assert.AreEqual(noAttachment, withAttachment);
Assert.AreEqual(noAttachment.GetHashCode(), withAttachment.GetHashCode());
Expand All @@ -287,17 +287,17 @@ public static IEnumerable<ITestCaseData> RecurringComponentAttachment_TestCases(

var journalNoAttach = new Journal {Start = new CalDateTime(_nowTime), Summary = "A summary!", Class = "Some class!"};
var journalWithAttach = new Journal {Start = new CalDateTime(_nowTime), Summary = "A summary!", Class = "Some class!"};
journalWithAttach.Attachments.Add(new Attachment(attachments.original));
journalWithAttach.Attachments.Add(new Attachment(attachments.Item1/*original*/));
yield return new TestCaseData(journalNoAttach, journalWithAttach).SetName("Journal recurring component attachment");

var todoNoAttach = new Todo { Start = new CalDateTime(_nowTime), Summary = "A summary!", Class = "Some class!" };
var todoWithAttach = new Todo { Start = new CalDateTime(_nowTime), Summary = "A summary!", Class = "Some class!"};
todoWithAttach.Attachments.Add(new Attachment(attachments.original));
todoWithAttach.Attachments.Add(new Attachment(attachments.Item1/*original*/));
yield return new TestCaseData(todoNoAttach, todoWithAttach).SetName("Todo recurring component attachment");

var eventNoAttach = GetSimpleEvent();
var eventWithAttach = GetSimpleEvent();
eventWithAttach.Attachments.Add(new Attachment(attachments.original));
eventWithAttach.Attachments.Add(new Attachment(attachments.Item1/*original*/));
yield return new TestCaseData(eventNoAttach, eventWithAttach).SetName("Event recurring component attachment");
}

Expand Down
2 changes: 1 addition & 1 deletion v2/ical.NET.UnitTests/Ical.Net.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
<ItemGroup>
<Reference Include="NodaTime, Version=1.3.0.0, Culture=neutral, PublicKeyToken=4226afe0d9b296d1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NodaTime.1.3.1\lib\net35-Client\NodaTime.dll</HintPath>
<HintPath>..\packages\NodaTime.1.3.6\lib\net35-Client\NodaTime.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=3.4.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.4.1\lib\net40\nunit.framework.dll</HintPath>
Expand Down
2 changes: 1 addition & 1 deletion v2/ical.NET.UnitTests/packages.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NodaTime" version="1.3.1" targetFramework="net461" />
<package id="NodaTime" version="1.3.6" targetFramework="net461" />
<package id="NUnit" version="3.4.1" targetFramework="net40" />
<package id="System.ValueTuple" version="4.3.0" targetFramework="net40" />
</packages>
10 changes: 8 additions & 2 deletions v2/ical.NET/Components/VTimeZone.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,10 @@ public string TzId

public Uri Url
{
get => _url ?? (_url = Properties.Get<Uri>("TZURL"));
get
{
return _url ?? (_url = Properties.Get<Uri>("TZURL"));
}
set
{
_url = value;
Expand All @@ -334,7 +337,10 @@ public Uri Url
private string _location;
public string Location
{
get => _location ?? (_location = Properties.Get<string>("X-LIC-LOCATION"));
get
{
return _location ?? (_location = Properties.Get<string>("X-LIC-LOCATION"));
}
set
{
_location = value;
Expand Down
11 changes: 7 additions & 4 deletions v2/ical.NET/DataTypes/CalDateTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,14 @@ public IDateTime ToTimeZone(string newTimeZone)
throw new ArgumentException("You must provide a valid TZID to the ToTimeZone() method", nameof(newTimeZone));
}

var newDt = string.IsNullOrWhiteSpace(TzId)
? DateUtil.ToZonedDateTimeLeniently(Value, newTimeZone).ToDateTimeUtc()
: DateUtil.FromTimeZoneToTimeZone(Value, TzId, newTimeZone).ToDateTimeUtc();
// If TzId is empty, it's a system-local datetime, so we should use the system time zone as the starting point.
var originalTzId = string.IsNullOrWhiteSpace(TzId) ? TimeZoneInfo.Local.Id : TzId;

return new CalDateTime(newDt, newTimeZone);
var zonedOriginal = DateUtil.ToZonedDateTimeLeniently(Value, originalTzId);
var converted = zonedOriginal.WithZone(DateUtil.GetZone(newTimeZone));

return new CalDateTime(converted.Zone == NodaTime.DateTimeZone.Utc ?
converted.ToDateTimeUtc() : converted.ToDateTimeUnspecified(), newTimeZone);
}

public IDateTime Add(TimeSpan ts)
Expand Down
9 changes: 6 additions & 3 deletions v2/ical.NET/DataTypes/Period.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,12 @@ private void ExtrapolateTimes()
private IDateTime _startTime;
public virtual IDateTime StartTime
{
get => _startTime.HasTime
? _startTime
: new CalDateTime(new DateTime(_startTime.Value.Year, _startTime.Value.Month, _startTime.Value.Day, 0,0,0), _startTime.TzId);
get
{
return _startTime.HasTime
? _startTime
: new CalDateTime(new DateTime(_startTime.Value.Year, _startTime.Value.Month, _startTime.Value.Day, 0, 0, 0), _startTime.TzId);
}
set
{
if (Equals(_startTime, value))
Expand Down
4 changes: 2 additions & 2 deletions v2/ical.NET/DataTypes/PeriodList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ public override int GetHashCode()

public IPeriod this[int index]
{
get => Periods[index];
set => Periods[index] = value;
get { return Periods[index]; }
set { Periods[index] = value; }
}

public bool Remove(IPeriod item) => Periods.Remove(item);
Expand Down
11 changes: 3 additions & 8 deletions v2/ical.NET/Evaluation/RecurrencePatternEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private IRecurrencePattern ProcessRecurrencePattern(IDateTime referenceDate)
// Convert the UNTIL value to one that matches the same time information as the reference date
if (r.Until != DateTime.MinValue)
{
r.Until = DateUtil.MatchTimeZone(referenceDate, new CalDateTime(r.Until)).Value;
r.Until = DateUtil.GetSimpleDateTimeData(DateUtil.MatchTimeZone(referenceDate, new CalDateTime(r.Until, r.Until.Kind == DateTimeKind.Utc ? "UTC" : referenceDate.TzId)));
}

if (r.Frequency > FrequencyType.Secondly && r.BySecond.Count == 0 && referenceDate.HasTime
Expand Down Expand Up @@ -279,10 +279,7 @@ private HashSet<DateTime> GetDates(IDateTime seed, DateTime periodStart, DateTim
{
noCandidateIncrementCount = 0;

// sort candidates for identifying when UNTIL date is exceeded..
candidates.Sort();

foreach (var t in candidates.Where(t => t >= originalDate))
foreach (var t in candidates.OrderBy(c => c).Where(t => t >= originalDate))
{
candidate = t;

Expand All @@ -301,8 +298,7 @@ private HashSet<DateTime> GetDates(IDateTime seed, DateTime periodStart, DateTim
}
else if (pattern.Until == DateTime.MinValue || candidate <= pattern.Until)
{
var utcCandidate = DateUtil.FromTimeZoneToTimeZone(candidate, DateUtil.GetZone(seed.TzId), DateTimeZone.Utc).ToDateTimeUtc();
if (!dates.Contains(candidate) && (pattern.Until == DateTime.MinValue || utcCandidate <= pattern.Until))
if (!dates.Contains(candidate))
{
dates.Add(candidate);
}
Expand All @@ -321,7 +317,6 @@ private HashSet<DateTime> GetDates(IDateTime seed, DateTime periodStart, DateTim
IncrementDate(ref seedCopy, pattern, pattern.Interval);
}

// sort final list..
return dates;
}

Expand Down
4 changes: 2 additions & 2 deletions v2/ical.NET/Evaluation/TimeZoneInfoEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public class TimeZoneInfoEvaluator : RecurringEvaluator

protected ITimeZoneInfo TimeZoneInfo
{
get => Recurrable as ITimeZoneInfo;
set => Recurrable = value;
get { return Recurrable as ITimeZoneInfo; }
set { Recurrable = value; }
}

#endregion
Expand Down
2 changes: 1 addition & 1 deletion v2/ical.NET/Ical.Net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="NodaTime, Version=1.3.0.0, Culture=neutral, PublicKeyToken=4226afe0d9b296d1, processorArchitecture=MSIL">
<HintPath>..\packages\NodaTime.1.3.1\lib\net35-Client\NodaTime.dll</HintPath>
<HintPath>..\packages\NodaTime.1.3.6\lib\net35-Client\NodaTime.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public override string SerializeToString(object obj)
{
var dt = obj as IDateTime;

// RFC 5545 3.3.5:
// RFC 5545 3.3.5:
// The date with UTC time, or absolute time, is identified by a LATIN
// CAPITAL LETTER Z suffix character, the UTC designator, appended to
// the time value. The "TZID" property parameter MUST NOT be applied to DATE-TIME
Expand Down Expand Up @@ -134,6 +134,7 @@ public override object Deserialize(TextReader tr)
if (match.Groups[9].Success)
{
dt.IsUniversalTime = true;
dt.TzId = "UTC";
}

dt.Value = CoerceDateTime(year, month, date, hour, minute, second, DateTimeKind.Utc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ public override object Deserialize(TextReader tr)
var dt = serializer?.Deserialize(new StringReader(keyValue)) as IDateTime;
if (dt != null)
{
r.Until = dt.Value;
r.Until = Utility.DateUtil.GetSimpleDateTimeData(dt);
}
}
break;
Expand Down
12 changes: 10 additions & 2 deletions v2/ical.NET/Utility/RecurrenceUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,16 @@ public static HashSet<Occurrence> GetOccurrences(IRecurrable recurrable, IDateTi

// Change the time zone of periodStart/periodEnd as needed
// so they can be used during the evaluation process.
periodStart = DateUtil.MatchTimeZone(start, periodStart);
periodEnd = DateUtil.MatchTimeZone(start, periodEnd);
if (string.IsNullOrEmpty(periodStart.TzId) && !periodStart.IsUniversalTime)
{
periodStart.TzId = start.TzId;
periodEnd.TzId = start.TzId;
}
else
{
periodStart = DateUtil.MatchTimeZone(start, periodStart);
periodEnd = DateUtil.MatchTimeZone(start, periodEnd);
}

var periods = evaluator.Evaluate(start, DateUtil.GetSimpleDateTimeData(periodStart), DateUtil.GetSimpleDateTimeData(periodEnd), includeReferenceDateInResults);

Expand Down
2 changes: 1 addition & 1 deletion v2/ical.NET/packages.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NodaTime" version="1.3.1" targetFramework="net40" />
<package id="NodaTime" version="1.3.6" targetFramework="net40" />
<package id="System.Runtime.Serialization.Primitives" version="4.3.0" targetFramework="net46" />
</packages>