diff --git a/.editorconfig b/.editorconfig
index e72ea925..a77e827f 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -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
diff --git a/Ical.Net.Benchmarks/Ical.Net.Benchmarks.csproj b/Ical.Net.Benchmarks/Ical.Net.Benchmarks.csproj
index 65c8583a..845b39aa 100644
--- a/Ical.Net.Benchmarks/Ical.Net.Benchmarks.csproj
+++ b/Ical.Net.Benchmarks/Ical.Net.Benchmarks.csproj
@@ -7,6 +7,7 @@
+
diff --git a/Ical.Net.Tests/CalDateTimeTests.cs b/Ical.Net.Tests/CalDateTimeTests.cs
index 5afdaefa..6463a158 100644
--- a/Ical.Net.Tests/CalDateTimeTests.cs
+++ b/Ical.Net.Tests/CalDateTimeTests.cs
@@ -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;
@@ -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)
@@ -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)));
});
diff --git a/Ical.Net.Tests/DocumentationExamples.cs b/Ical.Net.Tests/DocumentationExamples.cs
index 342a6729..9c961258 100644
--- a/Ical.Net.Tests/DocumentationExamples.cs
+++ b/Ical.Net.Tests/DocumentationExamples.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
@@ -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
@@ -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
@@ -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 { new RecurrencePattern(FrequencyType.Daily, 1) },
};
diff --git a/Ical.Net.Tests/EqualityAndHashingTests.cs b/Ical.Net.Tests/EqualityAndHashingTests.cs
index cfd7f5d9..f379e3b4 100644
--- a/Ical.Net.Tests/EqualityAndHashingTests.cs
+++ b/Ical.Net.Tests/EqualityAndHashingTests.cs
@@ -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;
@@ -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))]
diff --git a/Ical.Net.Tests/GetOccurrenceTests.cs b/Ical.Net.Tests/GetOccurrenceTests.cs
index 9313183d..e1912808 100644
--- a/Ical.Net.Tests/GetOccurrenceTests.cs
+++ b/Ical.Net.Tests/GetOccurrenceTests.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
@@ -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();
diff --git a/Ical.Net.Tests/Ical.Net.Tests.csproj b/Ical.Net.Tests/Ical.Net.Tests.csproj
index fe2b4581..a6cb41c8 100644
--- a/Ical.Net.Tests/Ical.Net.Tests.csproj
+++ b/Ical.Net.Tests/Ical.Net.Tests.csproj
@@ -14,6 +14,7 @@
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Ical.Net.Tests/RecurrenceTests.cs b/Ical.Net.Tests/RecurrenceTests.cs
index 781dff78..4c9ffb65 100644
--- a/Ical.Net.Tests/RecurrenceTests.cs
+++ b/Ical.Net.Tests/RecurrenceTests.cs
@@ -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);
@@ -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));
@@ -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);
}
@@ -3215,7 +3215,7 @@ public void OccurrenceMustBeCompletelyContainedWithinSearchRange()
ByDay = new List { 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
{
@@ -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();
@@ -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));
@@ -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
@@ -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);
@@ -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));
diff --git a/Ical.Net.Tests/RecurrenceTests_From_Issues.cs b/Ical.Net.Tests/RecurrenceTests_From_Issues.cs
index 1e53be41..50008b1b 100644
--- a/Ical.Net.Tests/RecurrenceTests_From_Issues.cs
+++ b/Ical.Net.Tests/RecurrenceTests_From_Issues.cs
@@ -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;
@@ -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
@@ -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 { new RecurrencePattern(FrequencyType.Daily, 1) },
};
diff --git a/Ical.Net.Tests/SerializationTests.cs b/Ical.Net.Tests/SerializationTests.cs
index 7ac557a7..4a326ed4 100644
--- a/Ical.Net.Tests/SerializationTests.cs
+++ b/Ical.Net.Tests/SerializationTests.cs
@@ -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;
@@ -115,19 +114,19 @@ public static void CompareEnumerables(IEnumerable a1, IEnumerable a2, string val
public static string InspectSerializedSection(string serialized, string sectionName, IEnumerable 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;
@@ -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;
+ }
+ }
+
}
diff --git a/Ical.Net/DataTypes/GeographicLocation.cs b/Ical.Net/DataTypes/GeographicLocation.cs
index 395f66b3..0727d88e 100644
--- a/Ical.Net/DataTypes/GeographicLocation.cs
+++ b/Ical.Net/DataTypes/GeographicLocation.cs
@@ -4,6 +4,7 @@
//
using System.Diagnostics;
+using System.Globalization;
using Ical.Net.CalendarComponents;
using Ical.Net.Serialization.DataTypes;
@@ -48,7 +49,7 @@ public override void CopyFrom(ICopyable obj)
Longitude = geo.Longitude;
}
- public override string ToString() => Latitude.ToString("0.000000") + ";" + Longitude.ToString("0.000000");
+ public override string ToString() => Latitude.ToString("0.000000", CultureInfo.InvariantCulture) + ";" + Longitude.ToString("0.000000", CultureInfo.InvariantCulture);
protected bool Equals(GeographicLocation other) => Latitude.Equals(other.Latitude) && Longitude.Equals(other.Longitude);
diff --git a/Ical.Net/DataTypes/UTCOffset.cs b/Ical.Net/DataTypes/UTCOffset.cs
index d7de9703..d7e65d04 100644
--- a/Ical.Net/DataTypes/UTCOffset.cs
+++ b/Ical.Net/DataTypes/UTCOffset.cs
@@ -4,6 +4,7 @@
//
using System;
+using System.Globalization;
using Ical.Net.Serialization.DataTypes;
namespace Ical.Net.DataTypes;
@@ -64,7 +65,11 @@ public override bool Equals(object? obj)
public override int GetHashCode() => Offset.GetHashCode();
- public override string ToString() => (Positive ? "+" : "-") + Hours.ToString("00") + Minutes.ToString("00") + (Seconds != 0 ? Seconds.ToString("00") : string.Empty);
+ public override string ToString() => (Positive ? "+" : "-")
+ + Hours.ToString("00", CultureInfo.InvariantCulture) +
+ Minutes.ToString("00", CultureInfo.InvariantCulture) + (Seconds != 0
+ ? Seconds.ToString("00", CultureInfo.InvariantCulture)
+ : string.Empty);
///
public override void CopyFrom(ICopyable obj)
diff --git a/Ical.Net/Ical.Net.csproj b/Ical.Net/Ical.Net.csproj
index 89e558aa..08627e3e 100644
--- a/Ical.Net/Ical.Net.csproj
+++ b/Ical.Net/Ical.Net.csproj
@@ -8,6 +8,7 @@
+
diff --git a/Ical.Net/Serialization/DataTypes/DateTimeSerializer.cs b/Ical.Net/Serialization/DataTypes/DateTimeSerializer.cs
index 5e557b15..73848981 100644
--- a/Ical.Net/Serialization/DataTypes/DateTimeSerializer.cs
+++ b/Ical.Net/Serialization/DataTypes/DateTimeSerializer.cs
@@ -6,6 +6,7 @@
using Ical.Net.DataTypes;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
@@ -44,10 +45,11 @@ public DateTimeSerializer(SerializationContext ctx) : base(ctx) { }
// properties whose time values are specified in UTC.
var value = new StringBuilder(512);
- value.Append($"{dt.Year:0000}{dt.Month:00}{dt.Day:00}");
+ // NOSONAR: netstandard2.x does not support string.Create(CultureInfo.InvariantCulture, $"{...}");
+ value.Append(FormattableString.Invariant($"{dt.Year:0000}{dt.Month:00}{dt.Day:00}")); // NOSONAR
if (dt.HasTime)
{
- value.Append($"T{dt.Hour:00}{dt.Minute:00}{dt.Second:00}");
+ value.Append(FormattableString.Invariant($"T{dt.Hour:00}{dt.Minute:00}{dt.Second:00}")); // NOSONAR
if (dt.IsUtc)
{
value.Append("Z");
@@ -89,15 +91,15 @@ public DateTimeSerializer(SerializationContext ctx) : base(ctx) { }
if (match.Groups[1].Success)
{
- datePart = new DateOnly(Convert.ToInt32(match.Groups[2].Value),
- Convert.ToInt32(match.Groups[3].Value),
- Convert.ToInt32(match.Groups[4].Value));
+ datePart = new DateOnly(Convert.ToInt32(match.Groups[2].Value, CultureInfo.InvariantCulture),
+ Convert.ToInt32(match.Groups[3].Value, CultureInfo.InvariantCulture),
+ Convert.ToInt32(match.Groups[4].Value, CultureInfo.InvariantCulture));
}
if (match.Groups.Count >= 6 && match.Groups[5].Success)
{
- timePart = new TimeOnly(Convert.ToInt32(match.Groups[6].Value),
- Convert.ToInt32(match.Groups[7].Value),
- Convert.ToInt32(match.Groups[8].Value));
+ timePart = new TimeOnly(Convert.ToInt32(match.Groups[6].Value, CultureInfo.InvariantCulture),
+ Convert.ToInt32(match.Groups[7].Value, CultureInfo.InvariantCulture),
+ Convert.ToInt32(match.Groups[8].Value, CultureInfo.InvariantCulture));
}
var isUtc = match.Groups[9].Success;
diff --git a/Ical.Net/Serialization/DataTypes/DurationSerializer.cs b/Ical.Net/Serialization/DataTypes/DurationSerializer.cs
index 4f15c95f..616f192c 100644
--- a/Ical.Net/Serialization/DataTypes/DurationSerializer.cs
+++ b/Ical.Net/Serialization/DataTypes/DurationSerializer.cs
@@ -4,6 +4,7 @@
//
using System;
+using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
@@ -34,20 +35,22 @@ private static string SerializeToString(Duration ts)
sb.Append('-');
sb.Append('P');
+ // NOSONAR: netstandard2.x does not support string.Create(CultureInfo.InvariantCulture, $"{...}");
if (ts.Weeks != null)
- sb.Append($"{sign * ts.Weeks}W");
+ sb.Append(FormattableString.Invariant($"{sign * ts.Weeks}W")); // NOSONAR
if (ts.Days != null)
- sb.Append($"{sign * ts.Days}D");
+ sb.Append(FormattableString.Invariant($"{sign * ts.Days}D")); // NOSONAR
if (ts.Hours != null || ts.Minutes != null || ts.Seconds != null)
{
sb.Append('T');
+
if (ts.Hours != null)
- sb.Append($"{sign * ts.Hours}H");
+ sb.Append(FormattableString.Invariant($"{sign * ts.Hours}H")); // NOSONAR
if (ts.Minutes != null)
- sb.Append($"{sign * ts.Minutes}M");
+ sb.Append(FormattableString.Invariant($"{sign * ts.Minutes}M")); // NOSONAR
if (ts.Seconds != null)
- sb.Append($"{sign * ts.Seconds}S");
+ sb.Append(FormattableString.Invariant($"{sign * ts.Seconds}S")); // NOSONAR
}
return sb.ToString();
@@ -91,7 +94,7 @@ private static string SerializeToString(Duration ts)
sign = -1;
int? GetGroupInt(string key)
- => match.Groups[key].Success ? Convert.ToInt32(match.Groups[key].Value) : null;
+ => match.Groups[key].Success ? Convert.ToInt32(match.Groups[key].Value, CultureInfo.InvariantCulture) : null;
weeks = GetGroupInt("week");
if (match.Groups["main"].Success)
diff --git a/Ical.Net/Serialization/DataTypes/IntegerSerializer.cs b/Ical.Net/Serialization/DataTypes/IntegerSerializer.cs
index 9a50f2b2..56acb1a3 100644
--- a/Ical.Net/Serialization/DataTypes/IntegerSerializer.cs
+++ b/Ical.Net/Serialization/DataTypes/IntegerSerializer.cs
@@ -4,6 +4,7 @@
//
using System;
+using System.Globalization;
using System.IO;
using Ical.Net.DataTypes;
@@ -21,7 +22,7 @@ public IntegerSerializer(SerializationContext ctx) : base(ctx) { }
{
try
{
- var i = Convert.ToInt32(obj);
+ var i = Convert.ToInt32(obj, CultureInfo.InvariantCulture);
if (SerializationContext.Peek() is ICalendarObject calObject)
{
@@ -30,9 +31,9 @@ public IntegerSerializer(SerializationContext ctx) : base(ctx) { }
{
AssociatedObject = calObject
};
- return Encode(dt, i.ToString());
+ return Encode(dt, i.ToString(CultureInfo.InvariantCulture));
}
- return i.ToString();
+ return i.ToString(CultureInfo.InvariantCulture);
}
catch
{
diff --git a/Ical.Net/Serialization/DataTypes/RecurrencePatternSerializer.cs b/Ical.Net/Serialization/DataTypes/RecurrencePatternSerializer.cs
index 12833099..80c3af31 100644
--- a/Ical.Net/Serialization/DataTypes/RecurrencePatternSerializer.cs
+++ b/Ical.Net/Serialization/DataTypes/RecurrencePatternSerializer.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
using Ical.Net.DataTypes;
@@ -38,7 +39,7 @@ protected static void AddInt32Values(IList list, string value)
var values = value.Split(',');
foreach (var v in values)
{
- list.Add(Convert.ToInt32(v));
+ list.Add(Convert.ToInt32(v, CultureInfo.InvariantCulture));
}
}
@@ -96,7 +97,7 @@ private static void SerializeByValue(List aggregate, IList byValue,
{
if (byValue.Any())
{
- aggregate.Add($"{name}={string.Join(",", byValue.Select(i => i.ToString()))}");
+ aggregate.Add($"{name}={string.Join(",", byValue.Select(i => i.ToString(CultureInfo.InvariantCulture)))}");
}
}
@@ -265,11 +266,11 @@ private void ProcessKeyValuePair(string key, string value, RecurrencePattern r,
break;
case "count":
- r.Count = Convert.ToInt32(value);
+ r.Count = Convert.ToInt32(value, CultureInfo.InvariantCulture);
break;
case "interval":
- r.Interval = Convert.ToInt32(value);
+ r.Interval = Convert.ToInt32(value, CultureInfo.InvariantCulture);
break;
case "bysecond":
diff --git a/Ical.Net/Serialization/DataTypes/StatusCodeSerializer.cs b/Ical.Net/Serialization/DataTypes/StatusCodeSerializer.cs
index 595287ed..deead0b8 100644
--- a/Ical.Net/Serialization/DataTypes/StatusCodeSerializer.cs
+++ b/Ical.Net/Serialization/DataTypes/StatusCodeSerializer.cs
@@ -4,6 +4,7 @@
//
using System;
+using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using Ical.Net.DataTypes;
@@ -28,7 +29,7 @@ public StatusCodeSerializer(SerializationContext ctx) : base(ctx) { }
var vals = new string[sc.Parts.Length];
for (var i = 0; i < sc.Parts.Length; i++)
{
- vals[i] = sc.Parts[i].ToString();
+ vals[i] = sc.Parts[i].ToString(CultureInfo.InvariantCulture);
}
return Encode(sc, Escape(string.Join(".", vals)));
}
diff --git a/Ical.Net/Serialization/DataTypes/UtcOffsetSerializer.cs b/Ical.Net/Serialization/DataTypes/UtcOffsetSerializer.cs
index 0e62c0ba..aff8f0f3 100644
--- a/Ical.Net/Serialization/DataTypes/UtcOffsetSerializer.cs
+++ b/Ical.Net/Serialization/DataTypes/UtcOffsetSerializer.cs
@@ -22,8 +22,9 @@ public UtcOffsetSerializer(SerializationContext ctx) : base(ctx) { }
{
if (obj is not UtcOffset offset) return null;
- var value = (offset.Positive ? "+" : "-") + offset.Hours.ToString("00") + offset.Minutes.ToString("00") +
- (offset.Seconds != 0 ? offset.Seconds.ToString("00") : string.Empty);
+ var value = (offset.Positive ? "+" : "-") + offset.Hours.ToString("00", CultureInfo.InvariantCulture) +
+ offset.Minutes.ToString("00", CultureInfo.InvariantCulture) +
+ (offset.Seconds != 0 ? offset.Seconds.ToString("00", CultureInfo.InvariantCulture) : string.Empty);
// Encode the value as necessary
return Encode(offset, value);
diff --git a/Ical.Net/Serialization/DataTypes/WeekDaySerializer.cs b/Ical.Net/Serialization/DataTypes/WeekDaySerializer.cs
index 721e16b5..ed725220 100644
--- a/Ical.Net/Serialization/DataTypes/WeekDaySerializer.cs
+++ b/Ical.Net/Serialization/DataTypes/WeekDaySerializer.cs
@@ -4,6 +4,7 @@
//
using System;
+using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using Ical.Net.DataTypes;
@@ -68,7 +69,7 @@ public WeekDaySerializer(SerializationContext ctx) : base(ctx) { }
if (match.Groups[2].Success)
{
- ds.Offset = Convert.ToInt32(match.Groups[2].Value);
+ ds.Offset = Convert.ToInt32(match.Groups[2].Value, CultureInfo.InvariantCulture);
if (match.Groups[1].Success && match.Groups[1].Value.Contains("-"))
{
ds.Offset *= -1;