diff --git a/Tests/NFUnitTestSystemLib/UnitTestDateTime.cs b/Tests/NFUnitTestSystemLib/UnitTestDateTime.cs index 7aa8fa60..f4c6b75f 100644 --- a/Tests/NFUnitTestSystemLib/UnitTestDateTime.cs +++ b/Tests/NFUnitTestSystemLib/UnitTestDateTime.cs @@ -2287,6 +2287,68 @@ public void DateTime_AboveMaxDatTime_ArgumentOutOfRangeExceptionTest59() Assert.Throws(typeof(ArgumentOutOfRangeException), () => { DateTime dt2 = new DateTime(10000, 1, 1, 0, 0, 0, 0); }); } + [TestMethod] + public void DateTime_ParseTest00() + { + // perform 10 random conversions + for (int i = 0; i < 10; i++) + { + DateTime dt = GetRandomDateTime(); + + // UniversalSortableDateTimePattern + var specifier1 = "u"; + + string dtOutput1 = dt.ToString(specifier1); + + Assert.Equal(DateTime.Parse(dtOutput1).ToString(specifier1), dt.ToString(specifier1), $"DateTime.Parse '{dt}' failed"); + + Assert.True(DateTime.TryParse(dtOutput1, out DateTime result), $"DateTime.TryParse '{dt}' failed"); + Assert.Equal(result.ToString(specifier1), dt.ToString(specifier1), $"DateTime.TryParse '{dt}' returning wrong value: '{result}'"); + } + } + + [TestMethod] + public void DateTime_ParseTest01() + { + // perform 10 random conversions + for (int i = 0; i < 10; i++) + { + DateTime dt = GetRandomDateTime(); + + // Round Trip ISO 8601 compatible + var specifier1 = "o"; + + string dtOutput1 = dt.ToString(specifier1); + + // expected format is yyyy-MM-ddTHH:mm:ss.fffffffK + Assert.Equal(DateTime.Parse(dtOutput1).ToString(specifier1), dt.ToString(specifier1), $"Parsing DateTime '{dt}' failed"); + + Assert.True(DateTime.TryParse(dtOutput1, out DateTime result), $"DateTime.TryParse '{dt}' failed"); + Assert.Equal(result.ToString(specifier1), dt.ToString(specifier1), $"DateTime.TryParse '{dt}' returning wrong value: '{result}'"); + } + } + + [TestMethod] + public void DateTime_ParseTest02() + { + // perform 10 random conversions + for (int i = 0; i < 10; i++) + { + DateTime dt = GetRandomDateTime(); + + // RFC 1123 date + var specifier1 = "r"; + + string dtOutput1 = dt.ToString(specifier1); + + // expected format is ddd, dd MMM yyyy HH':'mm':'ss 'GMT' + Assert.Equal(DateTime.Parse(dtOutput1).ToString(specifier1), dt.ToString(specifier1), $"Parsing DateTime '{dt}' failed"); + + Assert.True(DateTime.TryParse(dtOutput1, out DateTime result), $"DateTime.TryParse '{dt}' failed"); + Assert.Equal(result.ToString(specifier1), dt.ToString(specifier1), $"DateTime.TryParse '{dt}' returning wrong value: '{result}'"); + } + } + static double[] rdmFraction = new double[] { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 }; static int year, month, day, hour, minute, second, millisec; diff --git a/nanoFramework.CoreLibrary/System/Convert.cs b/nanoFramework.CoreLibrary/System/Convert.cs index fdb223c2..a8ff1a4f 100644 --- a/nanoFramework.CoreLibrary/System/Convert.cs +++ b/nanoFramework.CoreLibrary/System/Convert.cs @@ -37,6 +37,9 @@ public static class Convert [MethodImpl(MethodImplOptions.InternalCall)] internal static extern double NativeToDouble(string value, bool throwException, out bool success); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern DateTime NativeToDateTime(string value, bool throwException, out bool success); + /// /// Converts the value of the specified 8-bit unsigned integer to an equivalent Boolean value. /// @@ -121,6 +124,31 @@ public static byte ToByte(bool value) return value ? (byte)1 : (byte)0; } + /// + /// Converts the specified string representation of a date and time to an equivalent date and time value. + /// + /// The string representation of a date and time. + /// The date and time equivalent of the value of , or the date and time equivalent of if value is null. + /// is not a properly formatted date and time string. + /// + /// + /// If is not null, the return value is the result of invoking the method on value using the formatting information of the Invariant Culture. The argument must contain the representation of a date and time in one of the formats described in the DateTimeFormatInfo topic. If is , the method returns . + /// + /// + /// This method tries to parse completely and avoid throwing a . It completes missing month, day, and year information with the current date. If value contains only a date and no time, this method assumes a time of midnight. Any leading, inner, or trailing white-space characters in value are ignored. + /// + /// + /// If you prefer not to handle an exception if the conversion fails, you can call the method instead. It returns a value that indicates whether the conversion succeeded or failed. + /// + /// + public static DateTime ToDateTime(string value) + { + return NativeToDateTime( + value, + true, + out _); + } + /// /// Converts the specified string representation of a number to an equivalent 16-bit signed integer. /// diff --git a/nanoFramework.CoreLibrary/System/DateTime.cs b/nanoFramework.CoreLibrary/System/DateTime.cs index 65dd4c74..b6b21567 100644 --- a/nanoFramework.CoreLibrary/System/DateTime.cs +++ b/nanoFramework.CoreLibrary/System/DateTime.cs @@ -787,6 +787,53 @@ public override int GetHashCode() } + /// + /// Converts the string representation of a date and time to its equivalent by using the conventions of the current culture. + /// + /// A string that contains a date and time to convert. See The string to parse for more information. + /// An object that is equivalent to the date and time contained in . + /// is . + /// Failed to parse . + /// + /// + /// .NET nanoFramework doesn't support local times so converted values will always have set to . + /// + /// + /// This attempts to parse by using the formatting conventions of Invariant Culture. + /// + /// + public static DateTime Parse(string s) + { + // check for null string is carried out in native code + return Convert.ToDateTime(s); + } + + /// + /// Converts the specified string representation of a date and time to its equivalent and returns a value that indicates whether the conversion succeeded. + /// + /// A string containing a date and time to convert. + /// When this method returns, contains the value equivalent to the date and time contained in , if the conversion succeeded, or if the conversion failed. The conversion fails if the parameter is , is an , or does not contain a valid string representation of a date and time. This parameter is passed uninitialized. + /// if the parameter was converted successfully; otherwise, . + /// + /// + /// The method is similar to the method, except that the method does not throw an exception if the conversion fails. + /// + /// + /// The string is parsed using formatting information of the Invariant Culture. + /// + /// + public static bool TryParse( + string s, + out DateTime result) + { + result = Convert.NativeToDateTime( + s, + false, + out bool success); + + return success; + } + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DateTimeDisplay => $"{{{new DateTime(Ticks).ToString()}}}"; diff --git a/nanoFramework.CoreLibrary/System/Double.cs b/nanoFramework.CoreLibrary/System/Double.cs index 4802588d..de4f234c 100644 --- a/nanoFramework.CoreLibrary/System/Double.cs +++ b/nanoFramework.CoreLibrary/System/Double.cs @@ -181,7 +181,7 @@ public static bool TryParse( { result = Convert.NativeToDouble( s, - true, + false, out bool success); return success;