diff --git a/src/Microsoft.AspNetCore.OData/Edm/EdmPrimitiveHelper.cs b/src/Microsoft.AspNetCore.OData/Edm/EdmPrimitiveHelper.cs index 33e4cf031..7173891c6 100644 --- a/src/Microsoft.AspNetCore.OData/Edm/EdmPrimitiveHelper.cs +++ b/src/Microsoft.AspNetCore.OData/Edm/EdmPrimitiveHelper.cs @@ -105,8 +105,12 @@ public static object ConvertPrimitiveValue(object value, Type type, TimeZoneInfo { DateTimeOffset dateTimeOffsetValue = (DateTimeOffset)value; TimeZoneInfo timeZone = timeZoneInfo ?? TimeZoneInfo.Local; + dateTimeOffsetValue = TimeZoneInfo.ConvertTime(dateTimeOffsetValue, timeZone); - return dateTimeOffsetValue.DateTime; + + DateTimeKind dateTimeKind = GetTargetDateTimeKind(timeZone); + + return DateTime.SpecifyKind(dateTimeOffsetValue.DateTime, dateTimeKind); } if (value is Date) @@ -183,4 +187,15 @@ public static object ConvertPrimitiveValue(object value, Type type, TimeZoneInfo } } } -} + + private static DateTimeKind GetTargetDateTimeKind(TimeZoneInfo timeZone) + { + if (timeZone.Equals(TimeZoneInfo.Utc)) + return DateTimeKind.Utc; + + if (timeZone.Equals(TimeZoneInfo.Local)) + return DateTimeKind.Local; + + return DateTimeKind.Unspecified; + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.OData.Tests/Edm/EdmPrimitiveHelperTests.cs b/test/Microsoft.AspNetCore.OData.Tests/Edm/EdmPrimitiveHelperTests.cs index a3f6c63d6..745388fbb 100644 --- a/test/Microsoft.AspNetCore.OData.Tests/Edm/EdmPrimitiveHelperTests.cs +++ b/test/Microsoft.AspNetCore.OData.Tests/Edm/EdmPrimitiveHelperTests.cs @@ -94,7 +94,7 @@ public static TheoryDataSet ConvertDateTime_NonStandardPrimitive [Theory] [MemberData(nameof(ConvertPrimitiveValue_NonStandardPrimitives_Data))] - [MemberData(nameof(ConvertPrimitiveValue_NonStandardPrimitives_ExtraData))] + [MemberData(nameof(ConvertPrimitiveValue_NonStandardPrimitives_ExtraData))] public void ConvertPrimitiveValue_NonStandardPrimitives(object valueToConvert, object result, Type conversionType) { // Arrange & Act @@ -124,6 +124,52 @@ public void ConvertDateTimeValue_NonStandardPrimitives_DefaultTimeZoneInfo(DateT Assert.Equal(valueToConvert.LocalDateTime, dt); } + [Theory] + [MemberData(nameof(ConvertDateTime_NonStandardPrimitives_Data))] + public void ConvertDateTimeValue_ImplicitKind(DateTimeOffset valueToConvert) + { + // Arrange & Act + object actual = EdmPrimitiveHelper.ConvertPrimitiveValue(valueToConvert, typeof(DateTime)); + + //if server local time is UTC, then expect Utc Kind + DateTimeKind expectedTimeKind = TimeZoneInfo.Local.Equals(TimeZoneInfo.Utc) + ? DateTimeKind.Utc + : DateTimeKind.Local; + + // Assert + DateTime dt = Assert.IsType(actual); + Assert.Equal(expectedTimeKind, dt.Kind); + } + + [Theory] + [MemberData(nameof(ConvertDateTime_NonStandardPrimitives_Data))] + public void ConvertDateTimeValue_ExplicitLocalKind(DateTimeOffset valueToConvert) + { + // Arrange & Act + object actual = EdmPrimitiveHelper.ConvertPrimitiveValue(valueToConvert, typeof(DateTime), TimeZoneInfo.Local); + + //if server local time is UTC, then expect Utc Kind + DateTimeKind expectedTimeKind = TimeZoneInfo.Local.Equals(TimeZoneInfo.Utc) + ? DateTimeKind.Utc + : DateTimeKind.Local; + + // Assert + DateTime dt = Assert.IsType(actual); + Assert.Equal(expectedTimeKind, dt.Kind); + } + + [Theory] + [MemberData(nameof(ConvertDateTime_NonStandardPrimitives_Data))] + public void ConvertDateTimeValue_ExplicitUtcKind(DateTimeOffset valueToConvert) + { + // Arrange & Act + object actual = EdmPrimitiveHelper.ConvertPrimitiveValue(valueToConvert, typeof(DateTime), TimeZoneInfo.Utc); + + // Assert + DateTime dt = Assert.IsType(actual); + Assert.Equal(DateTimeKind.Utc, dt.Kind); + } + [Theory] [MemberData(nameof(ConvertDateTime_NonStandardPrimitives_Data))] public void ConvertDateTimeValue_NonStandardPrimitives_CustomTimeZoneInfo(DateTimeOffset valueToConvert) @@ -146,4 +192,4 @@ public void ConvertPrimitiveValue_Throws(object valueToConvert, Type conversionT () => EdmPrimitiveHelper.ConvertPrimitiveValue(valueToConvert, conversionType), exception); } -} +} \ No newline at end of file