diff --git a/src/Microsoft.Management.Infrastructure/Internal/ValueHelpers.cs b/src/Microsoft.Management.Infrastructure/Internal/ValueHelpers.cs index dc4236e..92843fb 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/ValueHelpers.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/ValueHelpers.cs @@ -5,6 +5,7 @@ using System; using Microsoft.Management.Infrastructure.Native; +using System.Globalization; namespace Microsoft.Management.Infrastructure.Internal { @@ -137,7 +138,11 @@ internal static object ConvertFromNativeLayer( } return arrayOfInstances; } - else if (type == MI_Type.MI_DATETIME || type == MI_Type.MI_DATETIMEA) + else if (type == MI_Type.MI_DATETIME) + { + return value.Datetime.ConvertToNativeLayer(); + } + else if (type == MI_Type.MI_DATETIMEA) { throw new NotImplementedException(); } diff --git a/src/Microsoft.Management.Infrastructure/Native/Structures/MI_Datetime.cs b/src/Microsoft.Management.Infrastructure/Native/Structures/MI_Datetime.cs index 305fe81..db5119f 100644 --- a/src/Microsoft.Management.Infrastructure/Native/Structures/MI_Datetime.cs +++ b/src/Microsoft.Management.Infrastructure/Native/Structures/MI_Datetime.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; namespace Microsoft.Management.Infrastructure.Native { @@ -16,6 +17,120 @@ internal struct MI_Datetime [FieldOffset(4)] internal MI_Interval interval; + internal object ConvertToNativeLayer() + { + MI_Datetime datetime = this; + if (datetime.isTimestamp) + { + // "Now" value defined in line 1934, page 53 of DSP0004, version 2.6.0 + if ((datetime.timestamp.year == 0) && + (datetime.timestamp.month == 1) && + (datetime.timestamp.day == 1) && + (datetime.timestamp.hour == 0) && + (datetime.timestamp.minute == 0) && + (datetime.timestamp.second == 0) && + (datetime.timestamp.microseconds == 0) && + (datetime.timestamp.utc == 720)) + { + return DateTime.Now; + } + // "Infinite past" value defined in line 1935, page 54 of DSP0004, version 2.6.0 + else if ((datetime.timestamp.year == 0) && + (datetime.timestamp.month == 1) && + (datetime.timestamp.day == 1) && + (datetime.timestamp.hour == 0) && + (datetime.timestamp.minute == 0) && + (datetime.timestamp.second == 0) && + (datetime.timestamp.microseconds == 999999) && + (datetime.timestamp.utc == 720)) + { + return DateTime.MinValue; + } + // "Infinite future" value defined in line 1936, page 54 of DSP0004, version 2.6.0 + else if ((datetime.timestamp.year == 9999) && + (datetime.timestamp.month == 12) && + (datetime.timestamp.day == 31) && + (datetime.timestamp.hour == 11) && + (datetime.timestamp.minute == 59) && + (datetime.timestamp.second == 59) && + (datetime.timestamp.microseconds == 999999) && + (datetime.timestamp.utc == (-720))) + { + return DateTime.MaxValue; + } + else + { +#if !_CORECLR + DateTime managedUtcDateTime = new DateTime( + (int)datetime.timestamp.year, + (int)datetime.timestamp.month, + (int)datetime.timestamp.day, + (int)datetime.timestamp.hour, + (int)datetime.timestamp.minute, + (int)datetime.timestamp.second, + (int)datetime.timestamp.microseconds / 1000, + CultureInfo.InvariantCulture.Calendar, + DateTimeKind.Utc); +#else + Calendar myCalendar = CultureInfo.InvariantCulture.Calendar; + DateTime myDateTime = new DateTime(); + DateTime managedDateTime = myCalendar.ToDateTime( + (int)datetime.timestamp.year, + (int)datetime.timestamp.month, + (int)datetime.timestamp.day, + (int)datetime.timestamp.hour, + (int)datetime.timestamp.minute, + (int)datetime.timestamp.second, + (int)datetime.timestamp.microseconds / 1000); + DateTime managedUtcDateTime = myDateTime.SpecifyKind(managedDateTime, DateTimeKind.Utc); + +#endif + long microsecondsUnaccounted = datetime.timestamp.microseconds % 1000; + managedUtcDateTime = managedUtcDateTime.AddTicks(microsecondsUnaccounted * 10); // since 1 microsecond == 10 ticks + managedUtcDateTime = managedUtcDateTime.AddMinutes(-(datetime.timestamp.utc)); + + +#if !_CORECLR + DateTime managedLocalDateTime = TimeZoneInfo.ConvertTimeFromUtc(managedUtcDateTime, TimeZoneInfo.Local); +#else + // + // TODO: USE THIS FOR BOTH CORECLR AND FULLOS + // + DateTime managedLocalDateTime = TimeZoneInfo::ConvertTime(*managedUtcDateTime, TimeZoneInfo::Local); +#endif + + return managedLocalDateTime; + } + } + else + { +#pragma warning (suppress: 4395) // ok that member function will be invoked on a copy of the initonly data member 'System::TimeSpan::MaxValue' + if (TimeSpan.MaxValue.TotalDays < datetime.interval.days) + { + return TimeSpan.MaxValue; + } + + try + { + TimeSpan managedTimeSpan = new TimeSpan( + (int)datetime.interval.days, + (int)datetime.interval.hours, + (int)datetime.interval.minutes, + (int)datetime.interval.seconds, + (int)datetime.interval.microseconds / 1000); + long microsecondsUnaccounted = datetime.interval.microseconds % 1000; + TimeSpan ticksUnaccountedTimeSpan = new TimeSpan(microsecondsUnaccounted * 10); // since 1 microsecond == 10 ticks + + return managedTimeSpan.Add(ticksUnaccountedTimeSpan); + } + catch (ArgumentOutOfRangeException) + { + return TimeSpan.MaxValue; + } + } + + } + internal MI_Datetime(TimeSpan interval) { this.timestamp.utc = 0; diff --git a/test/Microsoft.Management.Infrastructure.Tests/UnitTests/CimInstanceTest.cs b/test/Microsoft.Management.Infrastructure.Tests/UnitTests/CimInstanceTest.cs index 2e5911b..81e0fbd 100644 --- a/test/Microsoft.Management.Infrastructure.Tests/UnitTests/CimInstanceTest.cs +++ b/test/Microsoft.Management.Infrastructure.Tests/UnitTests/CimInstanceTest.cs @@ -391,7 +391,7 @@ public void Properties_Add_ValueAndType_Char16() Assert.Equal(CimType.Char16, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_DateTime_InTicks() { DateTime myDate = new DateTime(9990, DateTimeKind.Local); @@ -406,7 +406,7 @@ public void Properties_Add_ValueAndType_DateTime_DateTime_InTicks() Assert.Equal(CimType.DateTime, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_DateTime() { DateTime myDate = new DateTime(2010, 09, 22, 7, 30, 0, DateTimeKind.Local); @@ -421,7 +421,7 @@ public void Properties_Add_ValueAndType_DateTime_DateTime() Assert.Equal(CimType.DateTime, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_DateTime_MinValue() { DateTime myDate = DateTime.MinValue; @@ -436,7 +436,7 @@ public void Properties_Add_ValueAndType_DateTime_DateTime_MinValue() Assert.Equal(CimType.DateTime, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_DateTime_AlmostMinValue() { DateTime myDate = DateTime.MinValue.Add(TimeSpan.FromSeconds(1)); @@ -451,7 +451,7 @@ public void Properties_Add_ValueAndType_DateTime_DateTime_AlmostMinValue() Assert.Equal(CimType.DateTime, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_DateTime_MaxValue() { DateTime myDate = DateTime.MaxValue; @@ -466,7 +466,7 @@ public void Properties_Add_ValueAndType_DateTime_DateTime_MaxValue() Assert.Equal(CimType.DateTime, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_DateTime_AlmostMaxValue() { DateTime maxValidCimTimestampUtc = new DateTime(3155378975999999990, DateTimeKind.Utc); @@ -485,7 +485,7 @@ public void Properties_Add_ValueAndType_DateTime_DateTime_AlmostMaxValue() Assert.Equal(CimType.DateTime, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_TimeSpan_InTicks() { TimeSpan myInterval = TimeSpan.FromTicks(9990); @@ -500,7 +500,7 @@ public void Properties_Add_ValueAndType_DateTime_TimeSpan_InTicks() Assert.Equal(CimType.DateTime, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_TimeSpan() { TimeSpan myInterval = TimeSpan.FromSeconds(123); @@ -515,7 +515,7 @@ public void Properties_Add_ValueAndType_DateTime_TimeSpan() Assert.Equal(CimType.DateTime, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_TimeSpan_MaxValue() { TimeSpan myInterval = TimeSpan.MaxValue; @@ -530,7 +530,7 @@ public void Properties_Add_ValueAndType_DateTime_TimeSpan_MaxValue() Assert.Equal(CimType.DateTime, addedProperty.CimType, "addedProperty.CimType is not correct"); } - [TDDFact] + [Fact] public void Properties_Add_ValueAndType_DateTime_TimeSpan_AlmostMaxValue() { TimeSpan almostMaxValue = TimeSpan.MaxValue.Subtract(TimeSpan.FromSeconds(1));