Merge remote-tracking branch 'origin/dev' into feat/ProgramDataPath

This commit is contained in:
Drew Tingen
2019-09-16 14:05:48 -04:00
28 changed files with 565 additions and 265 deletions

View File

@@ -6,8 +6,30 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [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 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
- 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
- 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
- Improvements to JSON DateTime parsing, particularly in Net Standard
## [9.7.0] - 2019-08-15
### Added

View File

@@ -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 To12HourTest(int hour, int expected)
{
Assert.AreEqual(expected, DateTimeUtils.To12Hour(hour));
}
}
}

View File

@@ -3,16 +3,16 @@
namespace ICD.Common.Utils.Tests.Extensions
{
[TestFixture]
public sealed class DateTimeExtensionsTest
{
[Test]
public static void ToShortTimeStringTest()
{
Assert.Inconclusive();
}
public sealed class DateTimeExtensionsTest
{
[Test]
public void ToShortTimeStringTest()
{
Assert.Inconclusive();
}
[Test]
public static void ToLongTimeStringWithMillisecondsTest()
public void ToLongTimeStringWithMillisecondsTest()
{
Assert.Inconclusive();
}

View File

@@ -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<int> testList = new List<int>();
testList.PadRight(10);
Assert.AreEqual(10, testList.Count);
Assert.AreEqual(0, testList.Sum());
testList = new List<int>
{
1,
2,
3,
4,
5
};
testList.PadRight(10);
Assert.AreEqual(10, testList.Count);
Assert.AreEqual(15, testList.Sum());
testList = new List<int>
{
1,
2,
3,
4,
5
};
testList.PadRight(1);
Assert.AreEqual(5, testList.Count);
Assert.AreEqual(15, testList.Sum());
}
[Test]
public void PadRightDefaultTest()
{
List<int> testList = new List<int>();
testList.PadRight(10, 1);
Assert.AreEqual(10, testList.Count);
Assert.AreEqual(10, testList.Sum());
testList = new List<int>
{
1,
2,
3,
4,
5
};
testList.PadRight(10, 1);
Assert.AreEqual(10, testList.Count);
Assert.AreEqual(20, testList.Sum());
testList = new List<int>
{
1,
2,
3,
4,
5
};
testList.PadRight(1, 1);
Assert.AreEqual(5, testList.Count);
Assert.AreEqual(15, testList.Sum());
}
private sealed class InverseComparer : IComparer<int>
{
public int Compare(int x, int y)

View File

@@ -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);
}
}
}

View File

@@ -22,7 +22,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.14.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
</ItemGroup>
<ItemGroup>

View File

@@ -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();
}

View File

@@ -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<int> 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<int> 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 ModulusTest(int value, int mod, int expected)
{
Assert.AreEqual(expected, MathUtils.Modulus(value, mod));
}
}
}

View File

@@ -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 = @"<A>
<B>1</B>
<B>2</B>
</A>";
using (IcdXmlReader reader = new IcdXmlReader(xml))
{
// Read to the first element
reader.Read();
int[] values = IcdXmlConvert.DeserializeArray<int>(reader).ToArray();
Assert.AreEqual(new[] {1, 2}, values);
}
}
[Test]
public void DeserializeArrayTest()
{
Assert.Inconclusive();
}
}
}

View File

@@ -0,0 +1,15 @@
namespace ICD.Common.Utils
{
public static class DateTimeUtils
{
/// <summary>
/// Converts the hour in 24 hour format to 12 hour format (1 through 12).
/// </summary>
/// <param name="hour"></param>
/// <returns></returns>
public static int To12Hour(int hour)
{
return MathUtils.Modulus(hour + 11, 12) + 1;
}
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Globalization;
namespace ICD.Common.Utils.Extensions
{
public static class CultureInfoExtensions
{
/// <summary>
/// Returns true if the given culture uses a 24 hour time format.
/// </summary>
/// <param name="extends"></param>
/// <returns></returns>
public static bool Uses24HourFormat(this CultureInfo extends)
{
if (extends == null)
throw new ArgumentNullException("extends");
return extends.DateTimeFormat.ShortTimePattern.Contains("H");
}
/// <summary>
/// Updates the time patterns for the given culture to use 12 hour time.
/// </summary>
/// <param name="extends"></param>
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);
}
/// <summary>
/// Updates the time patterns for the given culture to use 24 hour time.
/// </summary>
/// <param name="extends"></param>
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);
}
/// <summary>
/// Converts the given format pattern to use 24 hour time.
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
private static string To24HourPattern(string pattern)
{
if (pattern == null)
return null;
pattern = pattern.Replace(" tt", "");
return pattern.Replace("h", "H");
}
/// <summary>
/// Converts the given format pattern to use 12 hour time.
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
private static string To12HourPattern(string pattern)
{
if (pattern == null)
return null;
if (!pattern.Contains("t"))
pattern = pattern + " tt";
return pattern.Replace("H", "h");
}
}
}

View File

@@ -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<TValue>());
}
/// <summary>
/// If the key is present in the dictionary return the value, otherwise add a new value to the dictionary and return it.
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
/// <param name="extends"></param>
/// <param name="key"></param>
/// <param name="valueFunc"></param>
/// <returns></returns>
[PublicAPI]
public static TValue GetOrAddNew<TKey, TValue>(this IDictionary<TKey, TValue> extends, TKey key, Func<TValue> 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<TValue>();
value = valueFunc();
extends.Add(key, value);
}

View File

@@ -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<T>(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);
}
/// <summary>
/// Gets the current value as a date.
/// </summary>
/// <param name="extends"></param>
/// <param name="format"></param>
/// <param name="provider"></param>
/// <returns></returns>
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);
}
}
}

View File

@@ -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
/// <param name="extends"></param>
/// <param name="items"></param>
[PublicAPI]
public static void AddSorted<T>(this List<T> extends, IEnumerable<T> items)
public static void AddSorted<T>(this IList<T> extends, IEnumerable<T> items)
{
if (extends == null)
throw new ArgumentNullException("extends");
@@ -37,7 +36,7 @@ namespace ICD.Common.Utils.Extensions
/// <param name="items"></param>
/// <param name="comparer"></param>
[PublicAPI]
public static void AddSorted<T>(this List<T> extends, IEnumerable<T> items, IComparer<T> comparer)
public static void AddSorted<T>(this IList<T> extends, IEnumerable<T> items, IComparer<T> comparer)
{
if (extends == null)
throw new ArgumentNullException("extends");
@@ -60,7 +59,7 @@ namespace ICD.Common.Utils.Extensions
/// <param name="items"></param>
/// <param name="predicate"></param>
[PublicAPI]
public static void AddSorted<T, TProp>(this List<T> extends, IEnumerable<T> items, Func<T, TProp> predicate)
public static void AddSorted<T, TProp>(this IList<T> extends, IEnumerable<T> items, Func<T, TProp> predicate)
{
if (extends == null)
throw new ArgumentNullException("extends");
@@ -82,7 +81,7 @@ namespace ICD.Common.Utils.Extensions
/// <param name="extends"></param>
/// <param name="item"></param>
[PublicAPI]
public static int AddSorted<T>(this List<T> extends, T item)
public static int AddSorted<T>(this IList<T> extends, T item)
{
if (extends == null)
throw new ArgumentNullException("extends");
@@ -98,7 +97,7 @@ namespace ICD.Common.Utils.Extensions
/// <param name="item"></param>
/// <param name="comparer"></param>
[PublicAPI]
public static int AddSorted<T>(this List<T> extends, T item, IComparer<T> comparer)
public static int AddSorted<T>(this IList<T> extends, T item, IComparer<T> comparer)
{
if (extends == null)
throw new ArgumentNullException("extends");
@@ -124,7 +123,7 @@ namespace ICD.Common.Utils.Extensions
/// <param name="item"></param>
/// <param name="predicate"></param>
[PublicAPI]
public static int AddSorted<T, TProp>(this List<T> extends, T item, Func<T, TProp> predicate)
public static int AddSorted<T, TProp>(this IList<T> extends, T item, Func<T, TProp> predicate)
{
if (extends == null)
throw new ArgumentNullException("extends");
@@ -137,44 +136,40 @@ namespace ICD.Common.Utils.Extensions
}
/// <summary>
/// Pads the list to the given total length.
/// Returns the index of the item in the list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="extends"></param>
/// <param name="totalLength"></param>
[PublicAPI]
public static void PadRight<T>(this List<T> 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));
}
/// <summary>
/// Pads the list to the given total length with the given item.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="extends"></param>
/// <param name="totalLength"></param>
/// <param name="item"></param>
/// <param name="comparer"></param>
/// <returns></returns>
[PublicAPI]
public static void PadRight<T>(this List<T> extends, int totalLength, T item)
public static int BinarySearch<T>(this IList<T> extends, T item, IComparer<T> comparer)
{
if (extends == null)
throw new ArgumentNullException("extends");
if (totalLength < 0)
throw new ArgumentOutOfRangeException("totalLength", "totalLength must be greater or equal to 0");
if (comparer == null)
throw new ArgumentNullException("comparer");
int pad = totalLength - extends.Count;
if (pad <= 0)
return;
int lo = 0;
int hi = extends.Count - 1;
extends.AddRange(Enumerable.Repeat(item, pad));
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;
}
}
}

View File

@@ -25,5 +25,48 @@ namespace ICD.Common.Utils.Extensions
return builder.ToString();
}
/// <summary>
/// Adds the given number of hours to the time, wrapping every 24 hours without modifying the day.
/// </summary>
/// <param name="extends"></param>
/// <param name="hours"></param>
/// <returns></returns>
public static TimeSpan AddHoursAndWrap(this TimeSpan extends, int hours)
{
hours = MathUtils.Modulus(hours + extends.Hours, 24);
return new TimeSpan(extends.Days, hours, extends.Minutes, extends.Seconds, extends.Milliseconds);
}
/// <summary>
/// Adds the given number of hours to the time, wrapping within the current 12 hour span, without modifying the day.
/// </summary>
/// <param name="extends"></param>
/// <param name="hours"></param>
/// <returns></returns>
public static TimeSpan AddHoursAndWrap12Hour(this TimeSpan extends, int hours)
{
int currentHour = extends.Hours;
bool am = extends.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)
: new TimeSpan(extends.Days, new12Hour + 12, extends.Minutes, extends.Seconds, extends.Milliseconds);
}
/// <summary>
/// Adds the given number of minutes to the time, wrapping every 60 minutes without modifying the hour.
/// </summary>
/// <param name="extends"></param>
/// <param name="minutes"></param>
/// <returns></returns>
public static TimeSpan AddMinutesAndWrap(this TimeSpan extends, int minutes)
{
minutes = MathUtils.Modulus(minutes + extends.Minutes, 60);
return new TimeSpan(extends.Days, extends.Hours, minutes, extends.Seconds, extends.Milliseconds);
}
}
}

View File

@@ -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

View File

@@ -86,6 +86,7 @@
<Compile Include="Comparers\PredicateComparer.cs" />
<Compile Include="Comparers\SequenceComparer.cs" />
<Compile Include="ConsoleColor.cs" />
<Compile Include="DateTimeUtils.cs" />
<Compile Include="Email\EmailClient.cs" />
<Compile Include="Email\eMailErrorCode.cs" />
<Compile Include="Email\EmailStringCollection.cs" />
@@ -109,6 +110,7 @@
<None Include="ObfuscationSettings.cs" />
<Compile Include="Extensions\BoolExtensions.cs" />
<Compile Include="Extensions\ByteExtensions.cs" />
<Compile Include="Extensions\CultureInfoExtensions.cs" />
<Compile Include="Extensions\DayOfWeekExtensions.cs" />
<Compile Include="Extensions\JsonSerializerExtensions.cs" />
<Compile Include="Extensions\JsonTokenExtensions.cs" />

View File

@@ -1,4 +1,5 @@
#if SIMPLSHARP
using ICD.Common.Utils.Extensions;
#if SIMPLSHARP
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
@@ -190,6 +191,18 @@ 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);
OnSystemDateTimeChanged.Raise(null);
}
public static eEthernetEventType GetEthernetEventType(Crestron.SimplSharp.eEthernetEventType type)
{
switch (type)

View File

@@ -79,6 +79,18 @@ 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();
OnSystemDateTimeChanged.Raise(null);
#endif
}
/// <summary>
/// Converts 12 digit address to XX:XX:XX... format
/// </summary>

View File

@@ -62,6 +62,11 @@ namespace ICD.Common.Utils
/// </summary>
public static event EventHandler OnProgramInitializationComplete;
/// <summary>
/// Raised when the system date/time has been set.
/// </summary>
public static event EventHandler OnSystemDateTimeChanged;
private static readonly SafeCriticalSection s_ProgramInitializationSection = new SafeCriticalSection();
private static bool s_ProgramInitializationComplete;

View File

@@ -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";
/// <summary>
/// Gets the data as a DateTime value.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static DateTime ParseDateTime(string data)
{
return DateTime.Parse(data);
}
/// <summary>
/// Gets the token as a DateTime value.
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
[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
}
/// <summary>
/// Gets the token as a DateTime value.
/// </summary>
/// <param name="token"></param>
/// <param name="output"></param>
/// <returns></returns>
[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;
}
}
/// <summary>
/// Serializes the given item and formats the JSON into a human-readable form.
/// </summary>

View File

@@ -209,5 +209,18 @@ namespace ICD.Common.Utils
return nearest.Aggregate((x, y) => Math.Abs(x - number) < Math.Abs(y - number) ? x : y);
}
/// <summary>
/// Calculates the modulus of the given number.
/// </summary>
/// <param name="number"></param>
/// <param name="mod"></param>
/// <returns></returns>
/// <remarks>method name can't be "Mod", due to S+ compatability issues</remarks>
public static int Modulus(int number, int mod)
{
int remainder = number % mod;
return remainder < 0 ? remainder + mod : remainder;
}
}
}

View File

@@ -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
}
}

View File

@@ -142,8 +142,7 @@ namespace ICD.Common.Utils
[PublicAPI]
public static TimeSpan GetSystemUptime()
{
// TODO
return default(TimeSpan);
return TimeSpan.FromMilliseconds(Environment.TickCount);
}
/// <summary>
@@ -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

View File

@@ -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
}
}
/// <summary>
/// Returns the date and time the program was installed.
/// </summary>
/// <returns></returns>
[PublicAPI]
public static DateTime ProgramInstallDate
{
get { return IcdFile.GetCreationTime(PathUtils.Join(PathUtils.ProgramPath, ProgramFile)); }
}
/// <summary>
/// Parses the prog comments and pulls program information.
/// </summary>

View File

@@ -55,6 +55,15 @@ namespace ICD.Common.Utils
return Assembly.GetEntryAssembly().GetName().Name;
}
}
}
/// <summary>
/// Gets the date and time the program was installed.
/// </summary>
[PublicAPI]
public static DateTime ProgramInstallDate
{
get { return IcdFile.GetCreationTime(PathUtils.Join(PathUtils.ProgramPath, ProgramFile)); }
}
}
}
#endif

View File

@@ -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")]

View File

@@ -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);
}
/// <summary>
/// Deserializes the child elements as items in an array.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="reader"></param>
/// <returns></returns>
public static IEnumerable<T> DeserializeArray<T>(IcdXmlReader reader)
{
if (reader == null)
throw new ArgumentNullException("reader");
return DeserializeArray(typeof(T), reader).Cast<T>();
}
/// <summary>
/// Deserializes the child elements as items in an array.
/// </summary>
/// <param name="type"></param>
/// <param name="reader"></param>
/// <returns></returns>
public static IEnumerable<object> 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);