Skip to content
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
2 changes: 2 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ insert_final_newline = true
csharp_new_line_before_members_in_anonymous_types = true

[*.cs]
#parsing and formatting should be implemented in a culture-invariant manner
dotnet_diagnostic.CA1305.severity = warning

#place catch statements on a new line
csharp_new_line_before_catch = true
Expand Down
1 change: 1 addition & 0 deletions Ical.Net.Benchmarks/Ical.Net.Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ical.Net\Ical.Net.csproj" />
Expand Down
6 changes: 3 additions & 3 deletions Ical.Net.Tests/CalDateTimeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public static IEnumerable ToTimeZoneTestCases()
[Test(Description = "A certain date/time value applied to different timezones should return the same UTC date/time")]
public void SameDateTimeWithDifferentTzIdShouldReturnSameUtc()
{
var someTime = DateTimeOffset.Parse("2018-05-21T11:35:00-04:00");
var someTime = DateTimeOffset.Parse("2018-05-21T11:35:00-04:00", CultureInfo.InvariantCulture);

var someDt = new CalDateTime(someTime.DateTime, "America/New_York");
var firstUtc = someDt.AsUtc;
Expand All @@ -111,7 +111,7 @@ public DateTimeKind DateTimeKindOverrideTests(DateTime dateTime, string tzId)
public static IEnumerable DateTimeKindOverrideTestCases()
{
const string localTz = "America/New_York";
var localDt = DateTime.SpecifyKind(DateTime.Parse("2018-05-21T11:35:33"), DateTimeKind.Unspecified);
var localDt = DateTime.SpecifyKind(DateTime.Parse("2018-05-21T11:35:33", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);

yield return new TestCaseData(localDt, "UTC")
.Returns(DateTimeKind.Unspecified)
Expand Down Expand Up @@ -317,7 +317,7 @@ public void Simple_PropertyAndMethod_HasTime_Tests()
Assert.That(c.DayOfYear, Is.EqualTo(dt.DayOfYear));
Assert.That(c.Time?.ToTimeSpan(), Is.EqualTo(dt.TimeOfDay));
Assert.That(c.Add(-Duration.FromSeconds(dt.Second)).Value.Second, Is.EqualTo(0));
Assert.That(c.ToString("dd.MM.yyyy"), Is.EqualTo("02.01.2025 Europe/Berlin"));
Assert.That(c.ToString("dd.MM.yyyy", CultureInfo.InvariantCulture), Is.EqualTo("02.01.2025 Europe/Berlin"));
// Create a date-only CalDateTime from a CalDateTime
Assert.That(new CalDateTime(new CalDateTime(2025, 1, 1)), Is.EqualTo(new CalDateTime(2025, 1, 1)));
});
Expand Down
13 changes: 7 additions & 6 deletions Ical.Net.Tests/DocumentationExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
Expand Down Expand Up @@ -50,8 +51,8 @@ public void EveryOtherTuesdayUntilTheEndOfTheYear_Test()
// An event taking place between 07:00 and 08:00, beginning July 5 (a Tuesday)
var vEvent = new CalendarEvent
{
DtStart = new CalDateTime(DateTime.Parse("2016-07-05T07:00")),
DtEnd = new CalDateTime(DateTime.Parse("2016-07-05T08:00")),
DtStart = new CalDateTime(DateTime.Parse("2016-07-05T07:00", CultureInfo.InvariantCulture)),
DtEnd = new CalDateTime(DateTime.Parse("2016-07-05T08:00",CultureInfo.InvariantCulture)),
};

// Recurring every other Tuesday until Dec 31
Expand All @@ -77,8 +78,8 @@ public void FourthThursdayOfNovember_Tests()
// An event taking place between 07:00 and 19:00, beginning July 5 (a Tuesday)
var vEvent = new CalendarEvent
{
DtStart = new CalDateTime(DateTime.Parse("2000-11-23T07:00")),
DtEnd = new CalDateTime(DateTime.Parse("2000-11-23T19:00")),
DtStart = new CalDateTime(DateTime.Parse("2000-11-23T07:00", CultureInfo.InvariantCulture)),
DtEnd = new CalDateTime(DateTime.Parse("2000-11-23T19:00", CultureInfo.InvariantCulture)),
};

// Recurring every other Tuesday until Dec 31
Expand Down Expand Up @@ -108,8 +109,8 @@ public void DailyExceptSunday_Test()
//An event that happens daily through 2016, except for Sundays
var vEvent = new CalendarEvent
{
DtStart = new CalDateTime(DateTime.Parse("2016-01-01T07:00")),
DtEnd = new CalDateTime(DateTime.Parse("2016-12-31T08:00")),
DtStart = new CalDateTime(DateTime.Parse("2016-01-01T07:00", CultureInfo.InvariantCulture)),
DtEnd = new CalDateTime(DateTime.Parse("2016-12-31T08:00", CultureInfo.InvariantCulture)),
RecurrenceRules = new List<RecurrencePattern> { new RecurrencePattern(FrequencyType.Daily, 1) },
};

Expand Down
3 changes: 2 additions & 1 deletion Ical.Net.Tests/EqualityAndHashingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Ical.Net.CalendarComponents;
Expand All @@ -19,7 +20,7 @@ namespace Ical.Net.Tests;
public class EqualityAndHashingTests
{
private const string TzId = "America/Los_Angeles";
private static readonly DateTime _nowTime = DateTime.SpecifyKind(DateTime.Parse("2016-07-16T16:47:02.9310521-04:00"), DateTimeKind.Unspecified);
private static readonly DateTime _nowTime = DateTime.SpecifyKind(DateTime.Parse("2016-07-16T16:47:02.9310521-04:00", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
private static readonly DateTime _later = _nowTime.AddHours(1);

[Test, TestCaseSource(nameof(CalDateTime_TestCases))]
Expand Down
9 changes: 5 additions & 4 deletions Ical.Net.Tests/GetOccurrenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
Expand All @@ -20,12 +21,12 @@ internal class GetOccurrenceTests
[Test]
public void WrongDurationTest()
{
var firstStart = new CalDateTime(DateTime.Parse("2016-01-01"));
var firstEnd = new CalDateTime(DateTime.Parse("2016-01-05"));
var firstStart = new CalDateTime(DateTime.Parse("2016-01-01", CultureInfo.InvariantCulture));
var firstEnd = new CalDateTime(DateTime.Parse("2016-01-05", CultureInfo.InvariantCulture));
var vEvent = new CalendarEvent { DtStart = firstStart, DtEnd = firstEnd, };

var secondStart = new CalDateTime(DateTime.Parse("2016-03-01"));
var secondEnd = new CalDateTime(DateTime.Parse("2016-03-05"));
var secondStart = new CalDateTime(DateTime.Parse("2016-03-01", CultureInfo.InvariantCulture));
var secondEnd = new CalDateTime(DateTime.Parse("2016-03-05", CultureInfo.InvariantCulture));
var vEvent2 = new CalendarEvent { DtStart = secondStart, DtEnd = secondEnd, };

var calendar = new Calendar();
Expand Down
1 change: 1 addition & 0 deletions Ical.Net.Tests/Ical.Net.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" PrivateAssets="all" />
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
44 changes: 22 additions & 22 deletions Ical.Net.Tests/RecurrenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2773,7 +2773,7 @@ public void Issue432()
};
var vEvent = new CalendarEvent
{
Start = new CalDateTime(DateTime.Parse("2019-01-04T08:00Z").ToUniversalTime()),
Start = new CalDateTime(DateTime.Parse("2019-01-04T08:00Z", CultureInfo.InvariantCulture).ToUniversalTime()),
};

vEvent.RecurrenceRules.Add(rrule);
Expand Down Expand Up @@ -2806,8 +2806,8 @@ public void Issue432_AllDay()
{
var vEvent = new CalendarEvent
{
Start = new CalDateTime(DateTime.Parse("2020-01-11")), // no time means all day
End = new CalDateTime(DateTime.Parse("2020-01-11T00:00")),
Start = new CalDateTime(DateTime.Parse("2020-01-11", CultureInfo.InvariantCulture)), // no time means all day
End = new CalDateTime(DateTime.Parse("2020-01-11T00:00", CultureInfo.InvariantCulture)),
};

var occurrences = vEvent.GetOccurrences(new CalDateTime(2020,01, 10, 0, 0, 0)).TakeUntil(new CalDateTime(2020, 01, 11, 00, 00, 00));
Expand Down Expand Up @@ -3174,20 +3174,20 @@ public void RDateShouldBeUnionedWithRecurrenceSet()

var calendar = Calendar.Load(ical)!;
var firstEvent = calendar.Events.First();
var startSearch = new CalDateTime(DateTime.Parse("2015-08-28T07:00:00"), _tzid);
var endSearch = new CalDateTime(DateTime.Parse("2016-08-28T07:00:00").AddDays(7), _tzid);
var startSearch = new CalDateTime(DateTime.Parse("2015-08-28T07:00:00", CultureInfo.InvariantCulture), _tzid);
var endSearch = new CalDateTime(DateTime.Parse("2016-08-28T07:00:00", CultureInfo.InvariantCulture).AddDays(7), _tzid);

var occurrences = firstEvent.GetOccurrences(startSearch).TakeUntil(endSearch)
.Select(o => o.Period)
.ToList();

var firstExpectedOccurrence = new CalDateTime(DateTime.Parse("2016-08-29T08:00:00"), _tzid);
var firstExpectedOccurrence = new CalDateTime(DateTime.Parse("2016-08-29T08:00:00", CultureInfo.InvariantCulture), _tzid);
Assert.That(occurrences.First().StartTime, Is.EqualTo(firstExpectedOccurrence));

var firstExpectedRDate = new CalDateTime(DateTime.Parse("2016-08-30T10:00:00"), _tzid);
var firstExpectedRDate = new CalDateTime(DateTime.Parse("2016-08-30T10:00:00", CultureInfo.InvariantCulture), _tzid);
Assert.That(occurrences[1].StartTime.Equals(firstExpectedRDate), Is.True);

var secondExpectedRDate = new CalDateTime(DateTime.Parse("2016-08-31T10:00:00"), _tzid);
var secondExpectedRDate = new CalDateTime(DateTime.Parse("2016-08-31T10:00:00", CultureInfo.InvariantCulture), _tzid);
Assert.That(occurrences[2].StartTime.Equals(secondExpectedRDate), Is.True);
}

Expand Down Expand Up @@ -3215,7 +3215,7 @@ public void OccurrenceMustBeCompletelyContainedWithinSearchRange()
ByDay = new List<WeekDay> { new WeekDay(DayOfWeek.Wednesday) },
};

var start = DateTime.Parse("2016-08-01T07:00:00");
var start = DateTime.Parse("2016-08-01T07:00:00", CultureInfo.InvariantCulture);
var end = start.AddHours(1);
var e = new CalendarEvent
{
Expand All @@ -3233,10 +3233,10 @@ public void OccurrenceMustBeCompletelyContainedWithinSearchRange()

Assert.That(firstEvent, Is.EqualTo(e));

var startSearch = new CalDateTime(DateTime.Parse("2016-07-01T00:00:00"), "UTC");
var endSearch = new CalDateTime(DateTime.Parse("2016-08-31T07:00:00"), "UTC");
var startSearch = new CalDateTime(DateTime.Parse("2016-07-01T00:00:00", CultureInfo.InvariantCulture), "UTC");
var endSearch = new CalDateTime(DateTime.Parse("2016-08-31T07:00:00", CultureInfo.InvariantCulture), "UTC");

var lastExpected = new CalDateTime(DateTime.Parse("2016-08-31T07:00:00"), "UTC");
var lastExpected = new CalDateTime(DateTime.Parse("2016-08-31T07:00:00", CultureInfo.InvariantCulture), "UTC");
var occurrences = firstEvent.GetOccurrences(startSearch).TakeUntil(endSearch)
.Select(o => o.Period)
.ToList();
Expand Down Expand Up @@ -3320,16 +3320,16 @@ public void EventsWithShareUidsShouldGenerateASingleRecurrenceSet()
.Select(o => o.Period)
.ToList();

var expectedSept1Start = new CalDateTime(DateTime.Parse("2016-09-01T16:30:00"), "Europe/Bucharest");
var expectedSept1End = new CalDateTime(DateTime.Parse("2016-09-01T22:00:00"), "Europe/Bucharest");
var expectedSept1Start = new CalDateTime(DateTime.Parse("2016-09-01T16:30:00", CultureInfo.InvariantCulture), "Europe/Bucharest");
var expectedSept1End = new CalDateTime(DateTime.Parse("2016-09-01T22:00:00", CultureInfo.InvariantCulture), "Europe/Bucharest");
Assert.Multiple(() =>
{
Assert.That(orderedOccurrences[3].StartTime, Is.EqualTo(expectedSept1Start));
Assert.That(orderedOccurrences[3].EndTime, Is.EqualTo(expectedSept1End));
});

var expectedSept3Start = new CalDateTime(DateTime.Parse("2016-09-03T07:00:00"), "Europe/Bucharest");
var expectedSept3End = new CalDateTime(DateTime.Parse("2016-09-03T12:30:00"), "Europe/Bucharest");
var expectedSept3Start = new CalDateTime(DateTime.Parse("2016-09-03T07:00:00", CultureInfo.InvariantCulture), "Europe/Bucharest");
var expectedSept3End = new CalDateTime(DateTime.Parse("2016-09-03T12:30:00", CultureInfo.InvariantCulture), "Europe/Bucharest");
Assert.Multiple(() =>
{
Assert.That(orderedOccurrences[5].StartTime, Is.EqualTo(expectedSept3Start));
Expand Down Expand Up @@ -3432,8 +3432,8 @@ public void OneDayRange()
{
var vEvent = new CalendarEvent
{
Start = new CalDateTime(DateTime.Parse("2019-06-07 0:00:00")),
End = new CalDateTime(DateTime.Parse("2019-06-08 00:00:00"))
Start = new CalDateTime(DateTime.Parse("2019-06-07 0:00:00", CultureInfo.InvariantCulture)),
End = new CalDateTime(DateTime.Parse("2019-06-08 00:00:00", CultureInfo.InvariantCulture))
};

//Testing on both the first day and the next, results used to be different
Expand All @@ -3457,8 +3457,8 @@ public void SpecificMinute()
};
var vEvent = new CalendarEvent
{
Start = new CalDateTime(DateTime.Parse("2009-01-01 09:00:00")),
End = new CalDateTime(DateTime.Parse("2009-01-01 17:00:00"))
Start = new CalDateTime(DateTime.Parse("2009-01-01 09:00:00", CultureInfo.InvariantCulture)),
End = new CalDateTime(DateTime.Parse("2009-01-01 17:00:00", CultureInfo.InvariantCulture))
};

vEvent.RecurrenceRules.Add(rrule);
Expand Down Expand Up @@ -3703,8 +3703,8 @@ public void InclusiveRruleUntil()
const string timeZoneId = @"Eastern Standard Time";
var calendar = Calendar.Load(icalText)!;
var firstEvent = calendar.Events.First();
var startSearch = new CalDateTime(DateTime.Parse("2017-07-01T00:00:00"), timeZoneId);
var endSearch = new CalDateTime(DateTime.Parse("2018-07-01T00:00:00"), timeZoneId);
var startSearch = new CalDateTime(DateTime.Parse("2017-07-01T00:00:00", CultureInfo.InvariantCulture), timeZoneId);
var endSearch = new CalDateTime(DateTime.Parse("2018-07-01T00:00:00", CultureInfo.InvariantCulture), timeZoneId);

var occurrences = firstEvent.GetOccurrences(startSearch).TakeUntil(endSearch).ToList();
Assert.That(occurrences, Has.Count.EqualTo(5));
Expand Down
9 changes: 5 additions & 4 deletions Ical.Net.Tests/RecurrenceTests_From_Issues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
Expand Down Expand Up @@ -314,8 +315,8 @@ public void Daylight_Savings_Changes_567()
{
// GetOccurrences Creates event with invalid time due to Daylight Savings changes #567

var calStart = new CalDateTime(DateTimeOffset.Parse("2023-01-14T19:21:03.700Z").UtcDateTime, "UTC");
var calFinish = new CalDateTime(DateTimeOffset.Parse("2023-03-14T18:21:03.700Z").UtcDateTime, "UTC");
var calStart = new CalDateTime(DateTimeOffset.Parse("2023-01-14T19:21:03.700Z", CultureInfo.InvariantCulture).UtcDateTime, "UTC");
var calFinish = new CalDateTime(DateTimeOffset.Parse("2023-03-14T18:21:03.700Z", CultureInfo.InvariantCulture).UtcDateTime, "UTC");
var tz = "Pacific Standard Time";
var pattern = new RecurrencePattern(
"FREQ=WEEKLY;BYDAY=SU,MO,TU,WE"); //Adjust the date to today so that the times remain constant
Expand Down Expand Up @@ -483,8 +484,8 @@ public void Except_Tuesday_Thursday_Saturday_Sunday()
Summary = "BIO CLASS",//subject
Description = "Details at CLASS",//description of meeting
Location = "Building 101",//location
DtStart = new CalDateTime(DateTime.Parse("2017-06-01T08:00")),
DtEnd = new CalDateTime(DateTime.Parse("2017-06-01T09:30")),
DtStart = new CalDateTime(DateTime.Parse("2017-06-01T08:00", CultureInfo.InvariantCulture)),
DtEnd = new CalDateTime(DateTime.Parse("2017-06-01T09:30", CultureInfo.InvariantCulture)),
RecurrenceRules = new List<RecurrencePattern> { new RecurrencePattern(FrequencyType.Daily, 1) },
};

Expand Down
55 changes: 49 additions & 6 deletions Ical.Net.Tests/SerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -115,19 +114,19 @@ public static void CompareEnumerables(IEnumerable a1, IEnumerable a2, string val
public static string InspectSerializedSection(string serialized, string sectionName, IEnumerable<string> elements)
{
const string notFound = "expected '{0}' not found";
var searchFor = "BEGIN:" + sectionName;
var searchFor = string.Format(CultureInfo.InvariantCulture, "BEGIN:{0}", sectionName);
var begin = serialized.IndexOf(searchFor, StringComparison.Ordinal);
Assert.That(begin, Is.Not.EqualTo(-1), () => string.Format(notFound, searchFor));
Assert.That(begin, Is.Not.EqualTo(-1), () => string.Format(CultureInfo.InvariantCulture, notFound, searchFor));

searchFor = "END:" + sectionName;
searchFor = string.Format(CultureInfo.InvariantCulture, "END:{0}", sectionName);
var end = serialized.IndexOf(searchFor, begin, StringComparison.Ordinal);
Assert.That(end, Is.Not.EqualTo(-1), () => string.Format(notFound, searchFor));
Assert.That(end, Is.Not.EqualTo(-1), () => string.Format(CultureInfo.InvariantCulture, notFound, searchFor));

var searchRegion = serialized.Substring(begin, end - begin + searchFor.Length);

foreach (var e in elements)
{
Assert.That(searchRegion, Does.Contain(SerializationConstants.LineBreak + e + SerializationConstants.LineBreak), () => string.Format(notFound, e));
Assert.That(searchRegion, Does.Contain(SerializationConstants.LineBreak + e + SerializationConstants.LineBreak), () => string.Format(CultureInfo.InvariantCulture, notFound, e));
}

return searchRegion;
Expand Down Expand Up @@ -601,4 +600,48 @@ public void SerializeSubcomponent()
Assert.That(!serialized.Contains("VCALENDAR", StringComparison.Ordinal), Is.True);
});
}

[TestCase("en-US")] // English (United States)
[TestCase("de-DE")] // German (Germany)
// failed before fixing CA1305 warnings
[TestCase("ar-SA")] // Arabic (Saudi Arabia)
// failed before fixing CA1305 warnings
[TestCase("he-IL")] // Hebrew (Israel)
[TestCase("hi-IN")] // Hindi (India)
[TestCase("zh-CN")] // Chinese (Simplified, China)
[TestCase("ja-JP")] // Japanese (Japan)
[TestCase("th-TH")] // Thai (Thailand)
[TestCase("ru-RU")] // Russian (Russia)
[TestCase("ko-KR")] // Korean (Korea)
public void TestConvertToInt32WithNegativeNumberInDifferentCultures(string cultureStr)
{
var originalCulture = CultureInfo.CurrentCulture;
try
{
var culture = new CultureInfo(cultureStr);
CultureInfo.CurrentCulture = culture;

Assert.Multiple(() =>
{
// Deserialize
Assert.That(() => Calendar.Load(
"""
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART:20251231
RRULE:FREQ=YEARLY;BYYEARDAY=-1
END:VEVENT
END:VCALENDAR
"""), Throws.Nothing);
// Serialize
Assert.That(() => new DurationSerializer().SerializeToString(new Duration(null, -1)), Is.EqualTo("-P1D"));

});
}
finally
{
CultureInfo.CurrentCulture = originalCulture;
}
}

}
Loading
Loading