From 18abe785504e933e3f7b78ed7684f11d8f769f42 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 27 Aug 2019 15:01:09 -0400 Subject: [PATCH 01/27] feat: Better handling of JSON DateTimes in Net Standard --- CHANGELOG.md | 1 + ICD.Common.Utils.Tests/Json/JsonUtilsTest.cs | 24 +------- .../Extensions/JsonReaderExtensions.cs | 50 +++++++++++++--- ICD.Common.Utils/Json/JsonUtils.cs | 58 ------------------- 4 files changed, 44 insertions(+), 89 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30921a0..c1f1d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - Fixed a bug where ANSI color encoded strings with percentages were being scrambled + - Improvements to JSON DateTime parsing, particularly in Net Standard ## [9.7.0] - 2019-08-15 ### Added diff --git a/ICD.Common.Utils.Tests/Json/JsonUtilsTest.cs b/ICD.Common.Utils.Tests/Json/JsonUtilsTest.cs index 0eae21e..b257c8d 100644 --- a/ICD.Common.Utils.Tests/Json/JsonUtilsTest.cs +++ b/ICD.Common.Utils.Tests/Json/JsonUtilsTest.cs @@ -10,29 +10,7 @@ namespace ICD.Common.Utils.Tests.Json public sealed class JsonUtilsTest { [Test] - public void CacheTypeTest() - { - Assert.Inconclusive(); - } - - [Test] - public void ParseDateTimeTest() - { - const string dataA = "2016-02-26T19:24:59"; - const string dataB = "2019-04-01T12:41:15-04:00"; - - Assert.DoesNotThrow(() => JsonUtils.ParseDateTime(dataA)); - Assert.DoesNotThrow(() => JsonUtils.ParseDateTime(dataB)); - } - - [Test] - public void TryParseDateTimeTest() - { - Assert.Inconclusive(); - } - - [Test] - public void PrintTest() + public void FormatTest() { Assert.Inconclusive(); } diff --git a/ICD.Common.Utils/Extensions/JsonReaderExtensions.cs b/ICD.Common.Utils/Extensions/JsonReaderExtensions.cs index 808b25c..263e616 100644 --- a/ICD.Common.Utils/Extensions/JsonReaderExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonReaderExtensions.cs @@ -1,6 +1,5 @@ using System; using ICD.Common.Properties; -using ICD.Common.Utils.Json; using Newtonsoft.Json; namespace ICD.Common.Utils.Extensions @@ -21,7 +20,12 @@ namespace ICD.Common.Utils.Extensions if (extends == null) throw new ArgumentNullException("extends"); - JsonSerializer serializer = new JsonSerializer(); + JsonSerializer serializer = +#if SIMPLSHARP + new JsonSerializer(); +#else + JsonSerializer.CreateDefault(); +#endif return extends.ReadAsObject(serializer); } @@ -145,7 +149,13 @@ namespace ICD.Common.Utils.Extensions { if (extends == null) throw new ArgumentNullException("extends"); - + +#if !SIMPLSHARP + // Newer versions of NewtonSoft try to be helpful and interpret strings as DateTimes without any consideration for different DateTime formats. + if (extends.TokenType == JsonToken.Date && extends.DateParseHandling != DateParseHandling.None) + throw new InvalidOperationException("DateParseHandling needs to be set to None"); +#endif + if (!extends.TokenType.IsPrimitive()) throw new FormatException("Expected primitive token type but got " + extends.TokenType); @@ -213,12 +223,36 @@ namespace ICD.Common.Utils.Extensions if (extends == null) throw new ArgumentNullException("extends"); -#if SIMPLSHARP - string stringValue = extends.GetValueAsString(); - return JsonUtils.ParseDateTime(stringValue); -#else - return (DateTime)extends.Value; +#if !SIMPLSHARP + // Newer NewtonSoft tries to be helpful by assuming that anything that looks like a DateTime must be a date. + if (extends.DateParseHandling != DateParseHandling.None) + return (DateTime)extends.Value; #endif + + string stringValue = extends.GetValueAsString(); + return DateTime.Parse(stringValue); + } + + /// + /// Gets the current value as a date. + /// + /// + /// + /// + /// + public static DateTime GetValueAsDateTimeExact(this JsonReader extends, string format, IFormatProvider provider) + { + if (extends == null) + throw new ArgumentNullException("extends"); + +#if !SIMPLSHARP + // Newer NewtonSoft tries to be helpful by assuming that anything that looks like a DateTime must be a date. + if (extends.DateParseHandling != DateParseHandling.None) + throw new InvalidOperationException("DateParseHandling needs to be set to None"); +#endif + + string stringValue = extends.GetValueAsString(); + return DateTime.ParseExact(stringValue, format, provider); } } } diff --git a/ICD.Common.Utils/Json/JsonUtils.cs b/ICD.Common.Utils/Json/JsonUtils.cs index 73e7140..4051688 100644 --- a/ICD.Common.Utils/Json/JsonUtils.cs +++ b/ICD.Common.Utils/Json/JsonUtils.cs @@ -5,7 +5,6 @@ using ICD.Common.Properties; using ICD.Common.Utils.Extensions; using ICD.Common.Utils.IO; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace ICD.Common.Utils.Json { @@ -18,63 +17,6 @@ namespace ICD.Common.Utils.Json private const string MESSAGE_NAME_PROPERTY = "m"; private const string MESSAGE_DATA_PROPERTY = "d"; - /// - /// Gets the data as a DateTime value. - /// - /// - /// - public static DateTime ParseDateTime(string data) - { - return DateTime.Parse(data); - } - - /// - /// Gets the token as a DateTime value. - /// - /// - /// - [PublicAPI] - public static DateTime ParseDateTime(JToken token) - { - if (token == null) - throw new ArgumentNullException("token"); - -#if SIMPLSHARP - return ParseDateTime((string)token); -#else - return (DateTime)token; -#endif - } - - /// - /// Gets the token as a DateTime value. - /// - /// - /// - /// - [PublicAPI] - public static bool TryParseDateTime(JToken token, out DateTime output) - { - if (token == null) - throw new ArgumentNullException("token"); - - output = default(DateTime); - - try - { - output = ParseDateTime(token); - return true; - } - catch (FormatException) - { - return false; - } - catch (InvalidCastException) - { - return false; - } - } - /// /// Serializes the given item and formats the JSON into a human-readable form. /// From c23d81e0239361d441ee8d073864364e3aa8c6fe Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 29 Aug 2019 14:13:55 -0400 Subject: [PATCH 02/27] chore: Updating nuget packages --- .../ICD.Common.Utils.Tests_NetStandard.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICD.Common.Utils.Tests/ICD.Common.Utils.Tests_NetStandard.csproj b/ICD.Common.Utils.Tests/ICD.Common.Utils.Tests_NetStandard.csproj index 65402a3..6379051 100644 --- a/ICD.Common.Utils.Tests/ICD.Common.Utils.Tests_NetStandard.csproj +++ b/ICD.Common.Utils.Tests/ICD.Common.Utils.Tests_NetStandard.csproj @@ -22,7 +22,7 @@ - + From bb41d59a4bf1dce2b9294dd3a041b0a1228c6b90 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 29 Aug 2019 17:21:57 -0400 Subject: [PATCH 03/27] feat: Adding methods for deserializing an XML array of items --- .../Xml/IcdXmlConvertTest.cs | 35 +++++++++++ ICD.Common.Utils/Xml/IcdXmlConvert.cs | 60 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 ICD.Common.Utils.Tests/Xml/IcdXmlConvertTest.cs diff --git a/ICD.Common.Utils.Tests/Xml/IcdXmlConvertTest.cs b/ICD.Common.Utils.Tests/Xml/IcdXmlConvertTest.cs new file mode 100644 index 0000000..0a9fa49 --- /dev/null +++ b/ICD.Common.Utils.Tests/Xml/IcdXmlConvertTest.cs @@ -0,0 +1,35 @@ +using System.Linq; +using ICD.Common.Utils.Xml; +using NUnit.Framework; + +namespace ICD.Common.Utils.Tests.Xml +{ + [TestFixture] + public sealed class IcdXmlConvertTest + { + [Test] + public void DeserializeArrayGenericTest() + { + const string xml = @" + 1 + 2 +"; + + using (IcdXmlReader reader = new IcdXmlReader(xml)) + { + // Read to the first element + reader.Read(); + + int[] values = IcdXmlConvert.DeserializeArray(reader).ToArray(); + + Assert.AreEqual(new[] {1, 2}, values); + } + } + + [Test] + public void DeserializeArrayTest() + { + Assert.Inconclusive(); + } + } +} diff --git a/ICD.Common.Utils/Xml/IcdXmlConvert.cs b/ICD.Common.Utils/Xml/IcdXmlConvert.cs index 11f8034..5cc796a 100644 --- a/ICD.Common.Utils/Xml/IcdXmlConvert.cs +++ b/ICD.Common.Utils/Xml/IcdXmlConvert.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Text; using ICD.Common.Utils.IO; #if SIMPLSHARP @@ -112,6 +114,64 @@ namespace ICD.Common.Utils.Xml return converter.ReadXml(reader); } + /// + /// Deserializes the child elements as items in an array. + /// + /// + /// + /// + public static IEnumerable DeserializeArray(IcdXmlReader reader) + { + if (reader == null) + throw new ArgumentNullException("reader"); + + return DeserializeArray(typeof(T), reader).Cast(); + } + + /// + /// Deserializes the child elements as items in an array. + /// + /// + /// + /// + public static IEnumerable DeserializeArray(Type type, IcdXmlReader reader) + { + if (type == null) + throw new ArgumentNullException("type"); + + if (reader == null) + throw new ArgumentNullException("reader"); + + if (reader.NodeType != XmlNodeType.Element) + throw new FormatException("Expected start element for array"); + + string arrayName = reader.Name; + + // Read into the first element + do + { + reader.Read(); + } while (reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.EndElement); + + // Empty array + if (reader.NodeType == XmlNodeType.EndElement) + yield break; + + // Read the items + IXmlConverter converter = XmlConverterAttribute.GetConverterForType(type); + while (reader.NodeType != XmlNodeType.EndElement) + { + yield return converter.ReadXml(reader); + reader.SkipInsignificantWhitespace(); + } + + if (reader.NodeType != XmlNodeType.EndElement || reader.Name != arrayName) + throw new FormatException("Expected end element for array"); + + // Read out of the array end element + reader.Read(); + } + public static string ToString(int value) { return XmlConvert.ToString(value); From 629ceec84e72d00e752c909d9fa05ea5495c5f1d Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Fri, 30 Aug 2019 17:18:18 -0400 Subject: [PATCH 04/27] feat: Added Public API Property to get the program install date based on the creation date of core dll file for Net Standard and SimplSharp --- ICD.Common.Utils/ProgramUtils.SimplSharp.cs | 13 ++++++++++++- ICD.Common.Utils/ProgramUtils.Standard.cs | 11 ++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ICD.Common.Utils/ProgramUtils.SimplSharp.cs b/ICD.Common.Utils/ProgramUtils.SimplSharp.cs index c1c692f..d4d9e5f 100644 --- a/ICD.Common.Utils/ProgramUtils.SimplSharp.cs +++ b/ICD.Common.Utils/ProgramUtils.SimplSharp.cs @@ -1,4 +1,5 @@ -using ICD.Common.Utils.Services; +using ICD.Common.Utils.IO; +using ICD.Common.Utils.Services; using ICD.Common.Utils.Services.Logging; #if SIMPLSHARP using Crestron.SimplSharp; @@ -86,6 +87,16 @@ namespace ICD.Common.Utils } } + /// + /// Returns the date and time the program was installed. + /// + /// + [PublicAPI] + public static DateTime ProgramInstallDate + { + get { return IcdFile.GetCreationTime(PathUtils.Join(PathUtils.ProgramPath, ProgramFile)); } + } + /// /// Parses the prog comments and pulls program information. /// diff --git a/ICD.Common.Utils/ProgramUtils.Standard.cs b/ICD.Common.Utils/ProgramUtils.Standard.cs index cfbaafc..916dfc4 100644 --- a/ICD.Common.Utils/ProgramUtils.Standard.cs +++ b/ICD.Common.Utils/ProgramUtils.Standard.cs @@ -55,6 +55,15 @@ namespace ICD.Common.Utils return Assembly.GetEntryAssembly().GetName().Name; } } - } + + /// + /// Gets the date and time the program was installed. + /// + [PublicAPI] + public static DateTime ProgramInstallDate + { + get { return IcdFile.GetCreationTime(PathUtils.Join(PathUtils.ProgramPath, ProgramFile)); } + } + } } #endif From 438b3d48e49c81e49b283565fe61c53a09a7b541 Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Fri, 30 Aug 2019 17:19:17 -0400 Subject: [PATCH 05/27] feat: Implemented Processor Utils for Net Standard to get the system uptime and the program uptime. --- ICD.Common.Utils/ProcessorUtils.Standard.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ICD.Common.Utils/ProcessorUtils.Standard.cs b/ICD.Common.Utils/ProcessorUtils.Standard.cs index 5755431..a69cd0d 100644 --- a/ICD.Common.Utils/ProcessorUtils.Standard.cs +++ b/ICD.Common.Utils/ProcessorUtils.Standard.cs @@ -142,8 +142,7 @@ namespace ICD.Common.Utils [PublicAPI] public static TimeSpan GetSystemUptime() { - // TODO - return default(TimeSpan); + return TimeSpan.FromMilliseconds(Environment.TickCount); } /// @@ -153,8 +152,8 @@ namespace ICD.Common.Utils [PublicAPI] public static TimeSpan GetProgramUptime() { - // TODO - return default(TimeSpan); + var current = System.Diagnostics.Process.GetCurrentProcess(); + return IcdEnvironment.GetLocalTime() - current.StartTime; } #endregion From 9c07b3da04934eefb2b90b36563f119561871ee7 Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Fri, 30 Aug 2019 17:21:17 -0400 Subject: [PATCH 06/27] docs: updating changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1f1d7f..a9780ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + - Added Public API Properties to get the program install date based on the creation date of core dll file for NetStandard and SimplSharp + - Implemented processor utils for NetStandard to get the system uptime and the program uptime ### Changed - Fixed a bug where ANSI color encoded strings with percentages were being scrambled From 71bb3200579624af2efbeff912db37faff00d6c2 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 3 Sep 2019 10:52:19 -0400 Subject: [PATCH 07/27] chore: Updating changelog, incrementing minor version --- CHANGELOG.md | 3 +++ ICD.Common.Utils/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9780ba..865a965 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [9.8.0] - 2019-09-03 ### Added - Added Public API Properties to get the program install date based on the creation date of core dll file for NetStandard and SimplSharp - Implemented processor utils for NetStandard to get the system uptime and the program uptime + - Added methods for deserializing an XML array ### Changed - Fixed a bug where ANSI color encoded strings with percentages were being scrambled diff --git a/ICD.Common.Utils/Properties/AssemblyInfo.cs b/ICD.Common.Utils/Properties/AssemblyInfo.cs index 10a9662..78b81a1 100644 --- a/ICD.Common.Utils/Properties/AssemblyInfo.cs +++ b/ICD.Common.Utils/Properties/AssemblyInfo.cs @@ -4,4 +4,4 @@ using System.Reflection; [assembly: AssemblyCompany("ICD Systems")] [assembly: AssemblyProduct("ICD.Common.Utils")] [assembly: AssemblyCopyright("Copyright © ICD Systems 2019")] -[assembly: AssemblyVersion("9.7.0.0")] +[assembly: AssemblyVersion("9.8.0.0")] From 091ad100685270bd324229800d0e8cbcb6ea2afb Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 3 Sep 2019 16:09:03 -0400 Subject: [PATCH 08/27] test: Updating test framework version --- .../ICD.Common.Utils.Tests_NetStandard.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICD.Common.Utils.Tests/ICD.Common.Utils.Tests_NetStandard.csproj b/ICD.Common.Utils.Tests/ICD.Common.Utils.Tests_NetStandard.csproj index 6379051..3e36a22 100644 --- a/ICD.Common.Utils.Tests/ICD.Common.Utils.Tests_NetStandard.csproj +++ b/ICD.Common.Utils.Tests/ICD.Common.Utils.Tests_NetStandard.csproj @@ -22,7 +22,7 @@ - + From dc1b60e6298f0109bae5517812b5f018f403b178 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 4 Sep 2019 12:36:54 -0400 Subject: [PATCH 09/27] feat: Added an extension method for getting the hour in 12 hour format --- CHANGELOG.md | 3 ++ .../Extensions/DateTimeExtensionsTest.cs | 29 +++++++++++++------ .../Extensions/DateTimeExtensions.cs | 10 +++++++ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 865a965..37d7988 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + - Added an extension method for getting the hour in 12 hour format + ## [9.8.0] - 2019-09-03 ### Added - Added Public API Properties to get the program install date based on the creation date of core dll file for NetStandard and SimplSharp diff --git a/ICD.Common.Utils.Tests/Extensions/DateTimeExtensionsTest.cs b/ICD.Common.Utils.Tests/Extensions/DateTimeExtensionsTest.cs index 12e610d..a186f96 100644 --- a/ICD.Common.Utils.Tests/Extensions/DateTimeExtensionsTest.cs +++ b/ICD.Common.Utils.Tests/Extensions/DateTimeExtensionsTest.cs @@ -1,18 +1,29 @@ -using NUnit.Framework; +using System; +using ICD.Common.Utils.Extensions; +using NUnit.Framework; namespace ICD.Common.Utils.Tests.Extensions { [TestFixture] - public sealed class DateTimeExtensionsTest - { - [Test] - public static void ToShortTimeStringTest() - { - Assert.Inconclusive(); - } + public sealed class DateTimeExtensionsTest + { + [TestCase(1, 1)] + [TestCase(0, 12)] + [TestCase(12, 12)] + [TestCase(23, 11)] + public void Get12Hour(int hour, int expected) + { + Assert.AreEqual(expected, new DateTime(2019, 1, 1, hour, 0, 0).Get12Hour()); + } [Test] - public static void ToLongTimeStringWithMillisecondsTest() + public void ToShortTimeStringTest() + { + Assert.Inconclusive(); + } + + [Test] + public void ToLongTimeStringWithMillisecondsTest() { Assert.Inconclusive(); } diff --git a/ICD.Common.Utils/Extensions/DateTimeExtensions.cs b/ICD.Common.Utils/Extensions/DateTimeExtensions.cs index acdc661..ecba069 100644 --- a/ICD.Common.Utils/Extensions/DateTimeExtensions.cs +++ b/ICD.Common.Utils/Extensions/DateTimeExtensions.cs @@ -10,6 +10,16 @@ namespace ICD.Common.Utils.Extensions /// public static class DateTimeExtensions { + /// + /// Gets the hour in 12 hour format (1 through 12). + /// + /// + /// + public static int Get12Hour(this DateTime extends) + { + return ((extends.Hour + 11) % 12) + 1; + } + /// /// Replacement for missing DateTime.ToShortTimeString() absent from NetStandard. /// From 027c9ffe821b9dbd4c4762e7ed80329d39ed793b Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 4 Sep 2019 14:30:45 -0400 Subject: [PATCH 10/27] refactor: Changed DateTime extension method to a simple util method --- CHANGELOG.md | 2 +- ICD.Common.Utils.Tests/DateTimeUtilsTest.cs | 17 +++++++++++++++++ .../Extensions/DateTimeExtensionsTest.cs | 13 +------------ ICD.Common.Utils/DateTimeUtils.cs | 15 +++++++++++++++ .../Extensions/DateTimeExtensions.cs | 10 ---------- .../ICD.Common.Utils_SimplSharp.csproj | 1 + ICD.Common.Utils/IcdEnvironment.SimplSharp.cs | 10 ++++++++++ ICD.Common.Utils/IcdEnvironment.Standard.cs | 10 ++++++++++ 8 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 ICD.Common.Utils.Tests/DateTimeUtilsTest.cs create mode 100644 ICD.Common.Utils/DateTimeUtils.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 37d7988..dfbe750 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added - - Added an extension method for getting the hour in 12 hour format + - Added a method for converting 24 hour to 12 hour format ## [9.8.0] - 2019-09-03 ### Added diff --git a/ICD.Common.Utils.Tests/DateTimeUtilsTest.cs b/ICD.Common.Utils.Tests/DateTimeUtilsTest.cs new file mode 100644 index 0000000..a3957ee --- /dev/null +++ b/ICD.Common.Utils.Tests/DateTimeUtilsTest.cs @@ -0,0 +1,17 @@ +using NUnit.Framework; + +namespace ICD.Common.Utils.Tests +{ + [TestFixture] + public sealed class DateTimeUtilsTest + { + [TestCase(1, 1)] + [TestCase(0, 12)] + [TestCase(12, 12)] + [TestCase(23, 11)] + public void Get12Hour(int hour, int expected) + { + Assert.AreEqual(expected, DateTimeUtils.To12Hour(hour)); + } + } +} diff --git a/ICD.Common.Utils.Tests/Extensions/DateTimeExtensionsTest.cs b/ICD.Common.Utils.Tests/Extensions/DateTimeExtensionsTest.cs index a186f96..f712305 100644 --- a/ICD.Common.Utils.Tests/Extensions/DateTimeExtensionsTest.cs +++ b/ICD.Common.Utils.Tests/Extensions/DateTimeExtensionsTest.cs @@ -1,21 +1,10 @@ -using System; -using ICD.Common.Utils.Extensions; -using NUnit.Framework; +using NUnit.Framework; namespace ICD.Common.Utils.Tests.Extensions { [TestFixture] public sealed class DateTimeExtensionsTest { - [TestCase(1, 1)] - [TestCase(0, 12)] - [TestCase(12, 12)] - [TestCase(23, 11)] - public void Get12Hour(int hour, int expected) - { - Assert.AreEqual(expected, new DateTime(2019, 1, 1, hour, 0, 0).Get12Hour()); - } - [Test] public void ToShortTimeStringTest() { diff --git a/ICD.Common.Utils/DateTimeUtils.cs b/ICD.Common.Utils/DateTimeUtils.cs new file mode 100644 index 0000000..edcda83 --- /dev/null +++ b/ICD.Common.Utils/DateTimeUtils.cs @@ -0,0 +1,15 @@ +namespace ICD.Common.Utils +{ + public static class DateTimeUtils + { + /// + /// Converts the hour in 24 hour format to 12 hour format (1 through 12). + /// + /// + /// + public static int To12Hour(int hour) + { + return ((hour + 11) % 12) + 1; + } + } +} diff --git a/ICD.Common.Utils/Extensions/DateTimeExtensions.cs b/ICD.Common.Utils/Extensions/DateTimeExtensions.cs index ecba069..acdc661 100644 --- a/ICD.Common.Utils/Extensions/DateTimeExtensions.cs +++ b/ICD.Common.Utils/Extensions/DateTimeExtensions.cs @@ -10,16 +10,6 @@ namespace ICD.Common.Utils.Extensions /// public static class DateTimeExtensions { - /// - /// Gets the hour in 12 hour format (1 through 12). - /// - /// - /// - public static int Get12Hour(this DateTime extends) - { - return ((extends.Hour + 11) % 12) + 1; - } - /// /// Replacement for missing DateTime.ToShortTimeString() absent from NetStandard. /// diff --git a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj index 0614074..ec7247f 100644 --- a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj +++ b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj @@ -86,6 +86,7 @@ + diff --git a/ICD.Common.Utils/IcdEnvironment.SimplSharp.cs b/ICD.Common.Utils/IcdEnvironment.SimplSharp.cs index b85dc8f..39dcf48 100644 --- a/ICD.Common.Utils/IcdEnvironment.SimplSharp.cs +++ b/ICD.Common.Utils/IcdEnvironment.SimplSharp.cs @@ -190,6 +190,16 @@ namespace ICD.Common.Utils return CrestronEnvironment.GetLocalTime(); } + public static void SetLocalTime(DateTime localTime) + { + CrestronEnvironment.SetTimeAndDate((ushort)localTime.Hour, + (ushort)localTime.Minute, + (ushort)localTime.Second, + (ushort)localTime.Month, + (ushort)localTime.Day, + (ushort)localTime.Year); + } + public static eEthernetEventType GetEthernetEventType(Crestron.SimplSharp.eEthernetEventType type) { switch (type) diff --git a/ICD.Common.Utils/IcdEnvironment.Standard.cs b/ICD.Common.Utils/IcdEnvironment.Standard.cs index a7a618a..62d607c 100644 --- a/ICD.Common.Utils/IcdEnvironment.Standard.cs +++ b/ICD.Common.Utils/IcdEnvironment.Standard.cs @@ -79,6 +79,16 @@ namespace ICD.Common.Utils return DateTime.Now; } + public static void SetLocalTime(DateTime localTime) + { +#if DEBUG + IcdConsole.PrintLine(eConsoleColor.Magenta, "Debug Build - Skipped setting local time to {0}", + localTime.ToString("s")); +#else + throw new NotSupportedException(); +#endif + } + /// /// Converts 12 digit address to XX:XX:XX... format /// From b09f614ef5515cdecd74d378b392561beb760637 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 4 Sep 2019 14:31:16 -0400 Subject: [PATCH 11/27] feat: Added a method for determining if a culture uses 24 hour format --- CHANGELOG.md | 1 + .../Extensions/CultureInfoExtensions.cs | 17 +++++++++++++++++ .../ICD.Common.Utils_SimplSharp.csproj | 1 + 3 files changed, 19 insertions(+) create mode 100644 ICD.Common.Utils/Extensions/CultureInfoExtensions.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index dfbe750..d7094d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Added a method for converting 24 hour to 12 hour format + - Added a method for determining if a culture uses 24 hour format ## [9.8.0] - 2019-09-03 ### Added diff --git a/ICD.Common.Utils/Extensions/CultureInfoExtensions.cs b/ICD.Common.Utils/Extensions/CultureInfoExtensions.cs new file mode 100644 index 0000000..4199c54 --- /dev/null +++ b/ICD.Common.Utils/Extensions/CultureInfoExtensions.cs @@ -0,0 +1,17 @@ +using System.Globalization; + +namespace ICD.Common.Utils.Extensions +{ + public static class CultureInfoExtensions + { + /// + /// Returns true if the given culture uses a 24 hour time format. + /// + /// + /// + public static bool Uses24HourFormat(this CultureInfo extends) + { + return extends.DateTimeFormat.ShortTimePattern.Contains("H"); + } + } +} diff --git a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj index ec7247f..9ec13c9 100644 --- a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj +++ b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj @@ -110,6 +110,7 @@ + From 45ee3e70b04acb63895d22e9aa6ea548e2ff6f1f Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Mon, 9 Sep 2019 10:06:08 -0400 Subject: [PATCH 12/27] feat: Added mod method to MathUtils --- CHANGELOG.md | 1 + ICD.Common.Utils.Tests/MathUtilsTest.cs | 21 +++++++++++++++------ ICD.Common.Utils/DateTimeUtils.cs | 2 +- ICD.Common.Utils/MathUtils.cs | 12 ++++++++++++ 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7094d4..618f1de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Added a method for converting 24 hour to 12 hour format - Added a method for determining if a culture uses 24 hour format + - Added math util method for mod ## [9.8.0] - 2019-09-03 ### Added diff --git a/ICD.Common.Utils.Tests/MathUtilsTest.cs b/ICD.Common.Utils.Tests/MathUtilsTest.cs index ebf3280..74129a1 100644 --- a/ICD.Common.Utils.Tests/MathUtilsTest.cs +++ b/ICD.Common.Utils.Tests/MathUtilsTest.cs @@ -1,14 +1,13 @@ using NUnit.Framework; using System.Collections.Generic; using System.Linq; -using ICD.Common.Properties; namespace ICD.Common.Utils.Tests { - [TestFixture, UsedImplicitly] + [TestFixture] public sealed class MathUtilsTest { - [Test, UsedImplicitly] + [Test] public void ClampTest() { Assert.AreEqual(MathUtils.Clamp(-10, 0, 0), 0); @@ -24,7 +23,7 @@ namespace ICD.Common.Utils.Tests Assert.AreEqual(MathUtils.Clamp(20, 10, 10), 10); } - [Test, UsedImplicitly] + [Test] public void MapRangeTest() { Assert.AreEqual(5, MathUtils.MapRange(-100, 100, 0, 10, 0)); @@ -40,7 +39,7 @@ namespace ICD.Common.Utils.Tests Assert.AreEqual(100, MathUtils.MapRange(0, 10, 0, 100, 10)); } - [Test, UsedImplicitly] + [Test] public void GetRangesTest() { IEnumerable values = new [] { 1, 3, 5, 6, 7, 8, 9, 10, 12 }; @@ -61,11 +60,21 @@ namespace ICD.Common.Utils.Tests Assert.AreEqual(12, ranges[3][1]); } - [Test, UsedImplicitly] + [Test] public void RoundToNearestTest() { IEnumerable values = new [] { 0, 15, 30, 45 }; Assert.AreEqual(15, MathUtils.RoundToNearest(21, values)); } + + [TestCase(10, 10, 0)] + [TestCase(-10, 10, 0)] + [TestCase(9, 3, 0)] + [TestCase(3, 2, 1)] + [TestCase(-3, 2, 1)] + public void ModTest(int value, int mod, int expected) + { + Assert.AreEqual(expected, MathUtils.Mod(value, mod)); + } } } diff --git a/ICD.Common.Utils/DateTimeUtils.cs b/ICD.Common.Utils/DateTimeUtils.cs index edcda83..a424ffd 100644 --- a/ICD.Common.Utils/DateTimeUtils.cs +++ b/ICD.Common.Utils/DateTimeUtils.cs @@ -9,7 +9,7 @@ /// public static int To12Hour(int hour) { - return ((hour + 11) % 12) + 1; + return MathUtils.Mod(hour + 11, 12) + 1; } } } diff --git a/ICD.Common.Utils/MathUtils.cs b/ICD.Common.Utils/MathUtils.cs index 832ccba..ee6ebe5 100644 --- a/ICD.Common.Utils/MathUtils.cs +++ b/ICD.Common.Utils/MathUtils.cs @@ -209,5 +209,17 @@ namespace ICD.Common.Utils return nearest.Aggregate((x, y) => Math.Abs(x - number) < Math.Abs(y - number) ? x : y); } + + /// + /// Calculates the modulus of the given number. + /// + /// + /// + /// + public static int Mod(int number, int mod) + { + int remainder = number % mod; + return remainder < 0 ? remainder + mod : remainder; + } } } From 9a6f197aa0deb26f80d3d8e510884d81479e6da3 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Mon, 9 Sep 2019 10:06:51 -0400 Subject: [PATCH 13/27] feat: Added TimeSpan extension methods for cycling hours and minutes without modifying the day --- CHANGELOG.md | 1 + ICD.Common.Utils.Tests/DateTimeUtilsTest.cs | 2 +- .../Extensions/TimeSpanExtensionsTest.cs | 43 +++++++++++++++++++ .../Extensions/TimeSpanExtensions.cs | 43 +++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 ICD.Common.Utils.Tests/Extensions/TimeSpanExtensionsTest.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 618f1de..92f2ac1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added a method for converting 24 hour to 12 hour format - Added a method for determining if a culture uses 24 hour format - Added math util method for mod + - Added TimeSpan extension methods for cycling hours and minutes without modifying the day ## [9.8.0] - 2019-09-03 ### Added diff --git a/ICD.Common.Utils.Tests/DateTimeUtilsTest.cs b/ICD.Common.Utils.Tests/DateTimeUtilsTest.cs index a3957ee..8347322 100644 --- a/ICD.Common.Utils.Tests/DateTimeUtilsTest.cs +++ b/ICD.Common.Utils.Tests/DateTimeUtilsTest.cs @@ -9,7 +9,7 @@ namespace ICD.Common.Utils.Tests [TestCase(0, 12)] [TestCase(12, 12)] [TestCase(23, 11)] - public void Get12Hour(int hour, int expected) + public void To12HourTest(int hour, int expected) { Assert.AreEqual(expected, DateTimeUtils.To12Hour(hour)); } diff --git a/ICD.Common.Utils.Tests/Extensions/TimeSpanExtensionsTest.cs b/ICD.Common.Utils.Tests/Extensions/TimeSpanExtensionsTest.cs new file mode 100644 index 0000000..740756f --- /dev/null +++ b/ICD.Common.Utils.Tests/Extensions/TimeSpanExtensionsTest.cs @@ -0,0 +1,43 @@ +using System; +using ICD.Common.Utils.Extensions; +using NUnit.Framework; + +namespace ICD.Common.Utils.Tests.Extensions +{ + [TestFixture] + public sealed class TimeSpanExtensionsTest + { + [Test] + public void ToReadableStringTest() + { + Assert.Inconclusive(); + } + + [TestCase(0, 0, 0)] + [TestCase(12, 1, 13)] + [TestCase(23, 1, 0)] + [TestCase(6, -12, 18)] + public void AddHoursAndWrapTest(int hours, int addHours, int expectedHours) + { + Assert.AreEqual(expectedHours, new TimeSpan(hours, 0, 0).AddHoursAndWrap(addHours).Hours); + } + + [TestCase(0, 0, 0)] + [TestCase(12, 1, 13)] + [TestCase(23, 1, 12)] + [TestCase(6, -12, 6)] + public void AddHoursAndWrap12Hour(int hours, int addHours, int expectedHours) + { + Assert.AreEqual(expectedHours, new TimeSpan(hours, 0, 0).AddHoursAndWrap12Hour(addHours).Hours); + } + + [TestCase(0, 0, 0)] + [TestCase(30, 1, 31)] + [TestCase(59, 1, 0)] + [TestCase(30, -60, 30)] + public void AddMinutesAndWrap(int minutes, int addMinutes, int expectedMinutes) + { + Assert.AreEqual(expectedMinutes, new TimeSpan(0, minutes, 0).AddMinutesAndWrap(addMinutes).Minutes); + } + } +} diff --git a/ICD.Common.Utils/Extensions/TimeSpanExtensions.cs b/ICD.Common.Utils/Extensions/TimeSpanExtensions.cs index e1e0b28..6cb9e00 100644 --- a/ICD.Common.Utils/Extensions/TimeSpanExtensions.cs +++ b/ICD.Common.Utils/Extensions/TimeSpanExtensions.cs @@ -25,5 +25,48 @@ namespace ICD.Common.Utils.Extensions return builder.ToString(); } + + /// + /// Adds the given number of hours to the time, wrapping every 24 hours without modifying the day. + /// + /// + /// + /// + public static TimeSpan AddHoursAndWrap(this TimeSpan extends, int hours) + { + hours = MathUtils.Mod(hours + extends.Hours, 24); + return new TimeSpan(extends.Days, hours, extends.Minutes, extends.Seconds, extends.Milliseconds); + } + + /// + /// Adds the given number of hours to the time, wrapping within the current 12 hour span, without modifying the day. + /// + /// + /// + /// + public static TimeSpan AddHoursAndWrap12Hour(this TimeSpan extends, int hours) + { + int currentHour = extends.Hours; + bool am = extends.Hours < 12; + + int current12Hour = MathUtils.Mod(currentHour, 12); + int new12Hour = MathUtils.Mod(current12Hour + hours, 12); + + return am + ? new TimeSpan(extends.Days, new12Hour, extends.Minutes, extends.Seconds, extends.Milliseconds) + : new TimeSpan(extends.Days, new12Hour + 12, extends.Minutes, extends.Seconds, extends.Milliseconds); + } + + /// + /// Adds the given number of minutes to the time, wrapping every 60 minutes without modifying the hour. + /// + /// + /// + /// + public static TimeSpan AddMinutesAndWrap(this TimeSpan extends, int minutes) + { + minutes = MathUtils.Mod(minutes + extends.Minutes, 60); + return new TimeSpan(extends.Days, extends.Hours, minutes, extends.Seconds, extends.Milliseconds); + } } } From 0f618198b54dfa3bfdf890e9c045f15867e26319 Mon Sep 17 00:00:00 2001 From: Drew Tingen Date: Mon, 9 Sep 2019 15:06:39 -0400 Subject: [PATCH 14/27] fix: Rename "Mod" to "Modulus" to keep S+ from throwing a fit --- ICD.Common.Utils/DateTimeUtils.cs | 2 +- ICD.Common.Utils/Extensions/TimeSpanExtensions.cs | 8 ++++---- ICD.Common.Utils/MathUtils.cs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ICD.Common.Utils/DateTimeUtils.cs b/ICD.Common.Utils/DateTimeUtils.cs index a424ffd..06efee2 100644 --- a/ICD.Common.Utils/DateTimeUtils.cs +++ b/ICD.Common.Utils/DateTimeUtils.cs @@ -9,7 +9,7 @@ /// public static int To12Hour(int hour) { - return MathUtils.Mod(hour + 11, 12) + 1; + return MathUtils.Modulus(hour + 11, 12) + 1; } } } diff --git a/ICD.Common.Utils/Extensions/TimeSpanExtensions.cs b/ICD.Common.Utils/Extensions/TimeSpanExtensions.cs index 6cb9e00..d0acfe5 100644 --- a/ICD.Common.Utils/Extensions/TimeSpanExtensions.cs +++ b/ICD.Common.Utils/Extensions/TimeSpanExtensions.cs @@ -34,7 +34,7 @@ namespace ICD.Common.Utils.Extensions /// public static TimeSpan AddHoursAndWrap(this TimeSpan extends, int hours) { - hours = MathUtils.Mod(hours + extends.Hours, 24); + hours = MathUtils.Modulus(hours + extends.Hours, 24); return new TimeSpan(extends.Days, hours, extends.Minutes, extends.Seconds, extends.Milliseconds); } @@ -49,8 +49,8 @@ namespace ICD.Common.Utils.Extensions int currentHour = extends.Hours; bool am = extends.Hours < 12; - int current12Hour = MathUtils.Mod(currentHour, 12); - int new12Hour = MathUtils.Mod(current12Hour + hours, 12); + int current12Hour = MathUtils.Modulus(currentHour, 12); + int new12Hour = MathUtils.Modulus(current12Hour + hours, 12); return am ? new TimeSpan(extends.Days, new12Hour, extends.Minutes, extends.Seconds, extends.Milliseconds) @@ -65,7 +65,7 @@ namespace ICD.Common.Utils.Extensions /// public static TimeSpan AddMinutesAndWrap(this TimeSpan extends, int minutes) { - minutes = MathUtils.Mod(minutes + extends.Minutes, 60); + minutes = MathUtils.Modulus(minutes + extends.Minutes, 60); return new TimeSpan(extends.Days, extends.Hours, minutes, extends.Seconds, extends.Milliseconds); } } diff --git a/ICD.Common.Utils/MathUtils.cs b/ICD.Common.Utils/MathUtils.cs index ee6ebe5..e40f116 100644 --- a/ICD.Common.Utils/MathUtils.cs +++ b/ICD.Common.Utils/MathUtils.cs @@ -216,7 +216,7 @@ namespace ICD.Common.Utils /// /// /// - public static int Mod(int number, int mod) + public static int Modulus(int number, int mod) { int remainder = number % mod; return remainder < 0 ? remainder + mod : remainder; From fc4ae67e40eeafdb093cbcc39d85a04019cdd2ba Mon Sep 17 00:00:00 2001 From: Drew Tingen Date: Mon, 9 Sep 2019 15:16:23 -0400 Subject: [PATCH 15/27] chore: changelog slightly more specific --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92f2ac1..61d8f17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Added a method for converting 24 hour to 12 hour format - Added a method for determining if a culture uses 24 hour format - - Added math util method for mod + - Added math util method for modulus - Added TimeSpan extension methods for cycling hours and minutes without modifying the day ## [9.8.0] - 2019-09-03 From f8fc68e08f73482b471870cc7c69bec6331379f0 Mon Sep 17 00:00:00 2001 From: Drew Tingen Date: Mon, 9 Sep 2019 15:17:32 -0400 Subject: [PATCH 16/27] chore: remarks explaining method name limitations --- ICD.Common.Utils/MathUtils.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/ICD.Common.Utils/MathUtils.cs b/ICD.Common.Utils/MathUtils.cs index e40f116..e81584a 100644 --- a/ICD.Common.Utils/MathUtils.cs +++ b/ICD.Common.Utils/MathUtils.cs @@ -216,6 +216,7 @@ namespace ICD.Common.Utils /// /// /// + /// method name can't be "Mod", due to S+ compatability issues public static int Modulus(int number, int mod) { int remainder = number % mod; From 0f27d68edfd8a81ebf7e9a9a6e10c7c36f8987d0 Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Mon, 9 Sep 2019 15:25:35 -0400 Subject: [PATCH 17/27] fix: Net Standard: the Root Config Path is now ICD.Connect in the current environments ProgramData directory --- ICD.Common.Utils/PathUtils.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ICD.Common.Utils/PathUtils.cs b/ICD.Common.Utils/PathUtils.cs index bf53748..7faa121 100644 --- a/ICD.Common.Utils/PathUtils.cs +++ b/ICD.Common.Utils/PathUtils.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using ICD.Common.Properties; using ICD.Common.Utils.Extensions; @@ -48,7 +49,7 @@ namespace ICD.Common.Utils #elif LINUX return Join(RootPath, "opt", "ICD.Connect"); #else - return Join(RootPath, "ProgramData", "ICD.Connect"); + return Join(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "ICD.Connect"); #endif } } From 8c0416f70e70dd52a80858815d0b149ed8374fef Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Mon, 9 Sep 2019 15:28:03 -0400 Subject: [PATCH 18/27] docs: updating changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92f2ac1..818ffb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] - ### Added - Added a method for converting 24 hour to 12 hour format - Added a method for determining if a culture uses 24 hour format - Added math util method for mod - Added TimeSpan extension methods for cycling hours and minutes without modifying the day +### Changed + - The Root Config path in Net Standard will now be the ICD.Connect folder in the current environments ProgramData directory + ## [9.8.0] - 2019-09-03 ### Added - Added Public API Properties to get the program install date based on the creation date of core dll file for NetStandard and SimplSharp From 9d02ee0022142a50f8275a9525a42c90f07b8d98 Mon Sep 17 00:00:00 2001 From: Drew Tingen Date: Mon, 9 Sep 2019 15:33:31 -0400 Subject: [PATCH 19/27] fix: Fixing MathUtilsTest after rename --- ICD.Common.Utils.Tests/MathUtilsTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ICD.Common.Utils.Tests/MathUtilsTest.cs b/ICD.Common.Utils.Tests/MathUtilsTest.cs index 74129a1..77a7d82 100644 --- a/ICD.Common.Utils.Tests/MathUtilsTest.cs +++ b/ICD.Common.Utils.Tests/MathUtilsTest.cs @@ -72,9 +72,9 @@ namespace ICD.Common.Utils.Tests [TestCase(9, 3, 0)] [TestCase(3, 2, 1)] [TestCase(-3, 2, 1)] - public void ModTest(int value, int mod, int expected) + public void ModulusTest(int value, int mod, int expected) { - Assert.AreEqual(expected, MathUtils.Mod(value, mod)); + Assert.AreEqual(expected, MathUtils.Modulus(value, mod)); } } } From 0821dcb3ca9864d88f07592315fa4bc8a372e92a Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 10 Sep 2019 17:16:31 -0400 Subject: [PATCH 20/27] fix: Fixed a bug where CultureInfo was not being cloned correctly --- CHANGELOG.md | 2 + .../Globalization/IcdCultureInfo.cs | 83 ++++++++++--------- 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bd9f03..0ef320d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] + ### Added - Added a method for converting 24 hour to 12 hour format - Added a method for determining if a culture uses 24 hour format @@ -13,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - The Root Config path in Net Standard will now be the ICD.Connect folder in the current environments ProgramData directory + - Fixed a bug where CultureInfo was not being cloned correctly ## [9.8.0] - 2019-09-03 ### Added diff --git a/ICD.Common.Utils/Globalization/IcdCultureInfo.cs b/ICD.Common.Utils/Globalization/IcdCultureInfo.cs index 50aa17f..7f86252 100644 --- a/ICD.Common.Utils/Globalization/IcdCultureInfo.cs +++ b/ICD.Common.Utils/Globalization/IcdCultureInfo.cs @@ -204,16 +204,17 @@ namespace ICD.Common.Utils.Globalization { get { - if (m_IsResident) - return base.DateTimeFormat; - - ThrowIfNeutralCulture(this); - if (m_DatetimeFormat == null) { + if (m_IsResident) + return base.DateTimeFormat; + + ThrowIfNeutralCulture(this); + DateTimeFormatInfo dateTimeFormatInfo = GetDateTimeFormat(m_DatetimeFormatId); if (IsReadOnly) dateTimeFormatInfo = DateTimeFormatInfo.ReadOnly(dateTimeFormatInfo); + m_DatetimeFormat = dateTimeFormatInfo; } return m_DatetimeFormat; @@ -221,13 +222,13 @@ namespace ICD.Common.Utils.Globalization set { if (m_IsResident) - { base.DateTimeFormat = value; - return; - } + ThrowIfReadOnly(); + if (value == null) throw new ArgumentException("value"); + m_DatetimeFormat = value; } } @@ -246,16 +247,17 @@ namespace ICD.Common.Utils.Globalization { get { - if (m_IsResident) - return base.NumberFormat; - - ThrowIfNeutralCulture(this); - if (m_NumberFormat == null) { + if (m_IsResident) + return base.NumberFormat; + + ThrowIfNeutralCulture(this); + NumberFormatInfo numberFormatInfo = GetNumberFormat(m_NumberFormatId); if (IsReadOnly) numberFormatInfo = NumberFormatInfo.ReadOnly(numberFormatInfo); + m_NumberFormat = numberFormatInfo; } return m_NumberFormat; @@ -263,13 +265,13 @@ namespace ICD.Common.Utils.Globalization set { if (m_IsResident) - { base.NumberFormat = value; - return; - } + ThrowIfReadOnly(); + if (value == null) throw new ArgumentException("value"); + m_NumberFormat = value; } } @@ -851,24 +853,25 @@ namespace ICD.Common.Utils.Globalization try { m_CompareInfo = ci.CompareInfo; - goto IL_CE; } catch (PlatformNotSupportedException) { m_CompareInfo = CultureInfo.InvariantCulture.CompareInfo; - goto IL_CE; } } - m_Calendar = icdCultureInfo.m_Calendar; - m_CalendarType = icdCultureInfo.m_CalendarType; - m_GregorianCalendarType = icdCultureInfo.m_GregorianCalendarType; - m_OptionalCalendars = icdCultureInfo.m_OptionalCalendars; - m_OptionalCalendarTypes = icdCultureInfo.m_OptionalCalendarTypes; - m_OptionalGregorianCalendarTypes = icdCultureInfo.m_OptionalGregorianCalendarTypes; - m_Parent = icdCultureInfo.m_Parent; - m_TextInfo = icdCultureInfo.m_TextInfo; - m_CompareInfo = icdCultureInfo.m_CompareInfo; - IL_CE: + else + { + m_Calendar = icdCultureInfo.m_Calendar; + m_CalendarType = icdCultureInfo.m_CalendarType; + m_GregorianCalendarType = icdCultureInfo.m_GregorianCalendarType; + m_OptionalCalendars = icdCultureInfo.m_OptionalCalendars; + m_OptionalCalendarTypes = icdCultureInfo.m_OptionalCalendarTypes; + m_OptionalGregorianCalendarTypes = icdCultureInfo.m_OptionalGregorianCalendarTypes; + m_Parent = icdCultureInfo.m_Parent; + m_TextInfo = icdCultureInfo.m_TextInfo; + m_CompareInfo = icdCultureInfo.m_CompareInfo; + } + m_EnglishName = ci.EnglishName; m_IsNeutralCulture = ci.IsNeutralCulture; m_Lcid = ci.LCID; @@ -877,19 +880,21 @@ namespace ICD.Common.Utils.Globalization m_ThreeLetterIsoLanguageName = ci.ThreeLetterISOLanguageName; m_ThreeLetterWindowsLanguageName = ci.ThreeLetterWindowsLanguageName; m_TwoLetterIsoLanguageName = ci.TwoLetterISOLanguageName; - if (!m_IsNeutralCulture) + + if (m_IsNeutralCulture) + return; + + if (icdCultureInfo == null) { - if (icdCultureInfo == null) - { - m_DatetimeFormat = ci.DateTimeFormat; - m_NumberFormat = ci.NumberFormat; - return; - } - m_DatetimeFormatId = icdCultureInfo.m_DatetimeFormatId; - m_DatetimeFormat = icdCultureInfo.m_DatetimeFormat; - m_NumberFormatId = icdCultureInfo.m_NumberFormatId; - m_NumberFormat = icdCultureInfo.m_NumberFormat; + m_DatetimeFormat = ci.DateTimeFormat.Clone() as DateTimeFormatInfo; + m_NumberFormat = ci.NumberFormat.Clone() as NumberFormatInfo; + return; } + + m_DatetimeFormatId = icdCultureInfo.m_DatetimeFormatId; + m_DatetimeFormat = icdCultureInfo.m_DatetimeFormat.Clone() as DateTimeFormatInfo; + m_NumberFormatId = icdCultureInfo.m_NumberFormatId; + m_NumberFormat = icdCultureInfo.m_NumberFormat.Clone() as NumberFormatInfo; } #region Methods From 83bc344ab3eab1cecf564efdf2524847d5031381 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 10 Sep 2019 17:17:09 -0400 Subject: [PATCH 21/27] feat: Added an event that is raised when the system time is set --- ICD.Common.Utils/IcdEnvironment.SimplSharp.cs | 5 ++++- ICD.Common.Utils/IcdEnvironment.Standard.cs | 2 ++ ICD.Common.Utils/IcdEnvironment.cs | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ICD.Common.Utils/IcdEnvironment.SimplSharp.cs b/ICD.Common.Utils/IcdEnvironment.SimplSharp.cs index 39dcf48..3b7aad2 100644 --- a/ICD.Common.Utils/IcdEnvironment.SimplSharp.cs +++ b/ICD.Common.Utils/IcdEnvironment.SimplSharp.cs @@ -1,4 +1,5 @@ -#if SIMPLSHARP +using ICD.Common.Utils.Extensions; +#if SIMPLSHARP using System; using System.Collections.Generic; using Crestron.SimplSharp; @@ -198,6 +199,8 @@ namespace ICD.Common.Utils (ushort)localTime.Month, (ushort)localTime.Day, (ushort)localTime.Year); + + OnSystemDateTimeChanged.Raise(null); } public static eEthernetEventType GetEthernetEventType(Crestron.SimplSharp.eEthernetEventType type) diff --git a/ICD.Common.Utils/IcdEnvironment.Standard.cs b/ICD.Common.Utils/IcdEnvironment.Standard.cs index 62d607c..62274a6 100644 --- a/ICD.Common.Utils/IcdEnvironment.Standard.cs +++ b/ICD.Common.Utils/IcdEnvironment.Standard.cs @@ -86,6 +86,8 @@ namespace ICD.Common.Utils localTime.ToString("s")); #else throw new NotSupportedException(); + + OnSystemDateTimeChanged.Raise(null); #endif } diff --git a/ICD.Common.Utils/IcdEnvironment.cs b/ICD.Common.Utils/IcdEnvironment.cs index 1804ed5..9ab155f 100644 --- a/ICD.Common.Utils/IcdEnvironment.cs +++ b/ICD.Common.Utils/IcdEnvironment.cs @@ -62,6 +62,11 @@ namespace ICD.Common.Utils /// public static event EventHandler OnProgramInitializationComplete; + /// + /// Raised when the system date/time has been set. + /// + public static event EventHandler OnSystemDateTimeChanged; + private static readonly SafeCriticalSection s_ProgramInitializationSection = new SafeCriticalSection(); private static bool s_ProgramInitializationComplete; From b4d82a855ef640819f82866e73fb7ba80492ca10 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 10 Sep 2019 17:18:12 -0400 Subject: [PATCH 22/27] feat: Added a dictionary extension method for getting or adding a new value via func --- CHANGELOG.md | 1 + .../Extensions/DictionaryExtensions.cs | 28 +++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ef320d..baf4273 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added a method for determining if a culture uses 24 hour format - Added math util method for modulus - Added TimeSpan extension methods for cycling hours and minutes without modifying the day + - Added a dictionary extension method for getting or adding a new value via func ### Changed - The Root Config path in Net Standard will now be the ICD.Connect folder in the current environments ProgramData directory diff --git a/ICD.Common.Utils/Extensions/DictionaryExtensions.cs b/ICD.Common.Utils/Extensions/DictionaryExtensions.cs index 9397b4c..58bf7f8 100644 --- a/ICD.Common.Utils/Extensions/DictionaryExtensions.cs +++ b/ICD.Common.Utils/Extensions/DictionaryExtensions.cs @@ -147,14 +147,38 @@ namespace ICD.Common.Utils.Extensions if (extends == null) throw new ArgumentNullException("extends"); - // ReSharper disable once CompareNonConstrainedGenericWithNull +// ReSharper disable CompareNonConstrainedGenericWithNull if (key == null) +// ReSharper restore CompareNonConstrainedGenericWithNull + throw new ArgumentNullException("key"); + + return extends.GetOrAddNew(key, () => ReflectionUtils.CreateInstance()); + } + + /// + /// If the key is present in the dictionary return the value, otherwise add a new value to the dictionary and return it. + /// + /// + /// + /// + /// + /// + /// + [PublicAPI] + public static TValue GetOrAddNew(this IDictionary extends, TKey key, Func valueFunc) + { + if (extends == null) + throw new ArgumentNullException("extends"); + +// ReSharper disable CompareNonConstrainedGenericWithNull + if (key == null) +// ReSharper restore CompareNonConstrainedGenericWithNull throw new ArgumentNullException("key"); TValue value; if (!extends.TryGetValue(key, out value)) { - value = ReflectionUtils.CreateInstance(); + value = valueFunc(); extends.Add(key, value); } From 96d2df88711c87fed84d2ecca1df7592030161a2 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 10 Sep 2019 17:19:00 -0400 Subject: [PATCH 23/27] feat: Added CultureInfo extensions for converting between 12 hour and 24 hour time formatting --- CHANGELOG.md | 1 + .../Extensions/CultureInfoExtensions.cs | 75 ++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index baf4273..893dec5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added math util method for modulus - Added TimeSpan extension methods for cycling hours and minutes without modifying the day - Added a dictionary extension method for getting or adding a new value via func + - Added CultureInfo extensions for converting between 12 hour and 24 hour time formatting ### Changed - The Root Config path in Net Standard will now be the ICD.Connect folder in the current environments ProgramData directory diff --git a/ICD.Common.Utils/Extensions/CultureInfoExtensions.cs b/ICD.Common.Utils/Extensions/CultureInfoExtensions.cs index 4199c54..20f9053 100644 --- a/ICD.Common.Utils/Extensions/CultureInfoExtensions.cs +++ b/ICD.Common.Utils/Extensions/CultureInfoExtensions.cs @@ -1,4 +1,5 @@ -using System.Globalization; +using System; +using System.Globalization; namespace ICD.Common.Utils.Extensions { @@ -11,7 +12,79 @@ namespace ICD.Common.Utils.Extensions /// public static bool Uses24HourFormat(this CultureInfo extends) { + if (extends == null) + throw new ArgumentNullException("extends"); + return extends.DateTimeFormat.ShortTimePattern.Contains("H"); } + + /// + /// Updates the time patterns for the given culture to use 12 hour time. + /// + /// + public static void ConvertTo12HourCulture(this CultureInfo extends) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (extends.IsReadOnly) + throw new InvalidOperationException("Culture is readonly"); + + DateTimeFormatInfo dateTimeFormat = extends.DateTimeFormat; + + dateTimeFormat.FullDateTimePattern = To12HourPattern(dateTimeFormat.FullDateTimePattern); + dateTimeFormat.LongTimePattern = To12HourPattern(dateTimeFormat.LongTimePattern); + dateTimeFormat.ShortTimePattern = To12HourPattern(dateTimeFormat.ShortTimePattern); + } + + /// + /// Updates the time patterns for the given culture to use 24 hour time. + /// + /// + public static void ConvertTo24HourCulture(this CultureInfo extends) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (extends.IsReadOnly) + throw new InvalidOperationException("Culture is readonly"); + + DateTimeFormatInfo dateTimeFormat = extends.DateTimeFormat; + + dateTimeFormat.FullDateTimePattern = To24HourPattern(dateTimeFormat.FullDateTimePattern); + dateTimeFormat.LongTimePattern = To24HourPattern(dateTimeFormat.LongTimePattern); + dateTimeFormat.ShortTimePattern = To24HourPattern(dateTimeFormat.ShortTimePattern); + } + + /// + /// Converts the given format pattern to use 24 hour time. + /// + /// + /// + private static string To24HourPattern(string pattern) + { + if (pattern == null) + return null; + + pattern = pattern.Replace(" tt", ""); + + return pattern.Replace("h", "H"); + } + + /// + /// Converts the given format pattern to use 12 hour time. + /// + /// + /// + private static string To12HourPattern(string pattern) + { + if (pattern == null) + return null; + + if (!pattern.Contains("t")) + pattern = pattern + " tt"; + + return pattern.Replace("H", "h"); + } } } From e65578584af694a9a927c2e9391858601ff1b438 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 10 Sep 2019 17:19:28 -0400 Subject: [PATCH 24/27] docs: Updating changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 893dec5..7bcb25b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added TimeSpan extension methods for cycling hours and minutes without modifying the day - Added a dictionary extension method for getting or adding a new value via func - Added CultureInfo extensions for converting between 12 hour and 24 hour time formatting + - Added environment methods for setting the current date and time ### Changed - The Root Config path in Net Standard will now be the ICD.Connect folder in the current environments ProgramData directory From aa17f293057039374f52d1741012ee3942658759 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 13 Sep 2019 16:35:38 -0400 Subject: [PATCH 25/27] feat: Adding BinarySearch extension method for ILists --- ICD.Common.Utils/Extensions/ListExtensions.cs | 58 +++++++++++++++---- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/ICD.Common.Utils/Extensions/ListExtensions.cs b/ICD.Common.Utils/Extensions/ListExtensions.cs index 04d32b1..b7d8298 100644 --- a/ICD.Common.Utils/Extensions/ListExtensions.cs +++ b/ICD.Common.Utils/Extensions/ListExtensions.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using ICD.Common.Properties; using ICD.Common.Utils.Comparers; @@ -18,7 +17,7 @@ namespace ICD.Common.Utils.Extensions /// /// [PublicAPI] - public static void AddSorted(this List extends, IEnumerable items) + public static void AddSorted(this IList extends, IEnumerable items) { if (extends == null) throw new ArgumentNullException("extends"); @@ -37,7 +36,7 @@ namespace ICD.Common.Utils.Extensions /// /// [PublicAPI] - public static void AddSorted(this List extends, IEnumerable items, IComparer comparer) + public static void AddSorted(this IList extends, IEnumerable items, IComparer comparer) { if (extends == null) throw new ArgumentNullException("extends"); @@ -60,7 +59,7 @@ namespace ICD.Common.Utils.Extensions /// /// [PublicAPI] - public static void AddSorted(this List extends, IEnumerable items, Func predicate) + public static void AddSorted(this IList extends, IEnumerable items, Func predicate) { if (extends == null) throw new ArgumentNullException("extends"); @@ -82,7 +81,7 @@ namespace ICD.Common.Utils.Extensions /// /// [PublicAPI] - public static int AddSorted(this List extends, T item) + public static int AddSorted(this IList extends, T item) { if (extends == null) throw new ArgumentNullException("extends"); @@ -98,7 +97,7 @@ namespace ICD.Common.Utils.Extensions /// /// [PublicAPI] - public static int AddSorted(this List extends, T item, IComparer comparer) + public static int AddSorted(this IList extends, T item, IComparer comparer) { if (extends == null) throw new ArgumentNullException("extends"); @@ -124,7 +123,7 @@ namespace ICD.Common.Utils.Extensions /// /// [PublicAPI] - public static int AddSorted(this List extends, T item, Func predicate) + public static int AddSorted(this IList extends, T item, Func predicate) { if (extends == null) throw new ArgumentNullException("extends"); @@ -143,7 +142,7 @@ namespace ICD.Common.Utils.Extensions /// /// [PublicAPI] - public static void PadRight(this List extends, int totalLength) + public static void PadRight(this IList extends, int totalLength) { if (extends == null) throw new ArgumentNullException("extends"); @@ -162,7 +161,7 @@ namespace ICD.Common.Utils.Extensions /// /// [PublicAPI] - public static void PadRight(this List extends, int totalLength, T item) + public static void PadRight(this IList extends, int totalLength, T item) { if (extends == null) throw new ArgumentNullException("extends"); @@ -171,10 +170,45 @@ namespace ICD.Common.Utils.Extensions throw new ArgumentOutOfRangeException("totalLength", "totalLength must be greater or equal to 0"); int pad = totalLength - extends.Count; - if (pad <= 0) - return; + for (int index = 0; index < pad; index++) + extends.Add(item); + } - extends.AddRange(Enumerable.Repeat(item, pad)); + /// + /// Returns the index of the item in the list. + /// + /// + /// + /// + /// + /// + [PublicAPI] + public static int BinarySearch(this IList extends, T item, IComparer comparer) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (comparer == null) + throw new ArgumentNullException("comparer"); + + int lo = 0; + int hi = extends.Count - 1; + + while (lo <= hi) + { + int i = lo + ((hi - lo) >> 1); + int order = comparer.Compare(extends[i], item); + + if (order == 0) + return i; + + if (order < 0) + lo = i + 1; + else + hi = i - 1; + } + + return ~lo; } } } From 2273d5b3a13cfd74971b3a4387ef2c3fa0768a3b Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Sat, 14 Sep 2019 11:23:09 -0400 Subject: [PATCH 26/27] refactor: Removing unused code --- .../Extensions/ListExtensionsTest.cs | 77 ------------------- ICD.Common.Utils/Extensions/ListExtensions.cs | 39 ---------- 2 files changed, 116 deletions(-) diff --git a/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs b/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs index 31644df..b96facc 100644 --- a/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs +++ b/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using ICD.Common.Utils.Extensions; using NUnit.Framework; @@ -43,82 +42,6 @@ namespace ICD.Common.Utils.Tests.Extensions Assert.AreEqual(1, testList[3]); } - [Test] - public void PadRightTest() - { - List testList = new List(); - testList.PadRight(10); - - Assert.AreEqual(10, testList.Count); - Assert.AreEqual(0, testList.Sum()); - - testList = new List - { - 1, - 2, - 3, - 4, - 5 - }; - - testList.PadRight(10); - - Assert.AreEqual(10, testList.Count); - Assert.AreEqual(15, testList.Sum()); - - testList = new List - { - 1, - 2, - 3, - 4, - 5 - }; - - testList.PadRight(1); - - Assert.AreEqual(5, testList.Count); - Assert.AreEqual(15, testList.Sum()); - } - - [Test] - public void PadRightDefaultTest() - { - List testList = new List(); - testList.PadRight(10, 1); - - Assert.AreEqual(10, testList.Count); - Assert.AreEqual(10, testList.Sum()); - - testList = new List - { - 1, - 2, - 3, - 4, - 5 - }; - - testList.PadRight(10, 1); - - Assert.AreEqual(10, testList.Count); - Assert.AreEqual(20, testList.Sum()); - - testList = new List - { - 1, - 2, - 3, - 4, - 5 - }; - - testList.PadRight(1, 1); - - Assert.AreEqual(5, testList.Count); - Assert.AreEqual(15, testList.Sum()); - } - private sealed class InverseComparer : IComparer { public int Compare(int x, int y) diff --git a/ICD.Common.Utils/Extensions/ListExtensions.cs b/ICD.Common.Utils/Extensions/ListExtensions.cs index b7d8298..e6e37a3 100644 --- a/ICD.Common.Utils/Extensions/ListExtensions.cs +++ b/ICD.Common.Utils/Extensions/ListExtensions.cs @@ -135,45 +135,6 @@ namespace ICD.Common.Utils.Extensions return extends.AddSorted(item, comparer); } - /// - /// Pads the list to the given total length. - /// - /// - /// - /// - [PublicAPI] - public static void PadRight(this IList extends, int totalLength) - { - if (extends == null) - throw new ArgumentNullException("extends"); - - if (totalLength < 0) - throw new ArgumentOutOfRangeException("totalLength", "totalLength must be greater or equal to 0"); - - extends.PadRight(totalLength, default(T)); - } - - /// - /// Pads the list to the given total length with the given item. - /// - /// - /// - /// - /// - [PublicAPI] - public static void PadRight(this IList extends, int totalLength, T item) - { - if (extends == null) - throw new ArgumentNullException("extends"); - - if (totalLength < 0) - throw new ArgumentOutOfRangeException("totalLength", "totalLength must be greater or equal to 0"); - - int pad = totalLength - extends.Count; - for (int index = 0; index < pad; index++) - extends.Add(item); - } - /// /// Returns the index of the item in the list. /// From 6a7b58f50fd6e9ec7d15384e643dca114f292e82 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Sat, 14 Sep 2019 11:23:19 -0400 Subject: [PATCH 27/27] docs: Updating changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bcb25b..ed2f268 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,10 +14,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added a dictionary extension method for getting or adding a new value via func - Added CultureInfo extensions for converting between 12 hour and 24 hour time formatting - Added environment methods for setting the current date and time + - Added BinarySearch extension method for all IList types ### Changed - The Root Config path in Net Standard will now be the ICD.Connect folder in the current environments ProgramData directory - Fixed a bug where CultureInfo was not being cloned correctly + - List AddSorted extensions now work for all IList types ## [9.8.0] - 2019-09-03 ### Added