diff --git a/demo/Primify.Demo/Primify.Demo.csproj b/demo/Primify.Demo/Primify.Demo.csproj
index 344c013..bd86cc4 100644
--- a/demo/Primify.Demo/Primify.Demo.csproj
+++ b/demo/Primify.Demo/Primify.Demo.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Primify.Generators/PrimifyGenerator.cs b/src/Primify.Generators/PrimifyGenerator.cs
index b83c1e9..b8020f0 100644
--- a/src/Primify.Generators/PrimifyGenerator.cs
+++ b/src/Primify.Generators/PrimifyGenerator.cs
@@ -323,36 +323,134 @@ private static string GenerateExplicitCasting(string name, string argument) =>
public static explicit operator {argument}({name} value) => value.Value;
""";
- private static string GenerateImplicitCasting(string name, string argument) =>
- $"""
- // Casting for BSON
- public static implicit operator LiteDB.BsonValue({name} value) =>
- new LiteDB.BsonValue(value.Value);
- public static implicit operator {name}(LiteDB.BsonValue value) =>
- From(({argument})System.Convert.ChangeType(value.RawValue, typeof({argument})));
- """;
+ private static string GenerateImplicitCasting(string name, string argument)
+ {
+ string toBson;
+ // We will generate the "from BsonValue" part differently based on complexity.
+ string fromBsonImplementation;
+
+ switch (argument)
+ {
+ case "System.DateOnly":
+ toBson = "new LiteDB.BsonValue(value.Value.ToDateTime(System.TimeOnly.MinValue))";
+ fromBsonImplementation = $"=> {name}.From(System.DateOnly.FromDateTime(value.AsDateTime));";
+ break;
+
+ case "System.TimeOnly":
+ toBson = "new LiteDB.BsonValue(value.Value.Ticks)";
+ fromBsonImplementation = $"=> {name}.From(new System.TimeOnly(value.AsInt64));";
+ break;
+
+ case "System.DateTimeOffset":
+ // Create a BsonDocument for serialization
+ toBson = """
+ new LiteDB.BsonDocument
+ {
+ ["DateTime"] = value.Value.UtcDateTime,
+ ["Offset"] = value.Value.Offset.Ticks
+ }
+ """;
+
+ // Generate a full method body for deserialization
+ fromBsonImplementation = $$"""
+ {
+ var doc = value.AsDocument;
+ var utcDateTime = doc["DateTime"].AsDateTime;
+ var offset = new System.TimeSpan(doc["Offset"].AsInt64);
+
+ // Create a UTC DateTimeOffset first, then convert to the original offset
+ var utcTime = new System.DateTimeOffset(utcDateTime);
+ var originalTime = utcTime.ToOffset(offset);
+
+ return {{name}}.From(originalTime);
+ }
+ """;
+ break;
+
+ default:
+ toBson = "new LiteDB.BsonValue(value.Value)";
+ fromBsonImplementation =
+ $"=> {name}.From(({argument})System.Convert.ChangeType(value.RawValue, typeof({argument})));";
+ break;
+ }
+
+ return $"""
+ // Casting for BSON
+ public static implicit operator LiteDB.BsonValue({name} value) =>
+ {toBson};
- private static string GenerateLiteDbInitializer(string name, string argument) =>
- $$"""
- ///
- /// Automatically registers the LiteDB BSON mapper for the {{name}} type.
- ///
- file static class {{name}}LiteDbInitializer
- {
- [ModuleInitializer]
- internal static void Register()
- {
- BsonMapper.Global.RegisterType<{{name}}>(
- serialize: wrapper => new LiteDB.BsonValue(wrapper.Value),
- deserialize: bson =>
- {
- var rawValue = bson.RawValue;
- var typedValue = ({{argument}})System.Convert.ChangeType(rawValue, typeof({{argument}}));
-
- return {{name}}.From(typedValue);
- }
- );
- }
- }
- """;
+ public static implicit operator {name}(LiteDB.BsonValue value)
+ {fromBsonImplementation}
+ """;
+ }
+
+ private static string GenerateLiteDbInitializer(string name, string argument)
+ {
+ string serializeCode;
+ string deserializeCode;
+
+ switch (argument)
+ {
+ case "System.DateOnly":
+ serializeCode = "wrapper => new LiteDB.BsonValue(wrapper.Value.ToDateTime(System.TimeOnly.MinValue))";
+ deserializeCode = $"bson => {name}.From(System.DateOnly.FromDateTime(bson.AsDateTime))";
+ break;
+
+ case "System.TimeOnly":
+ serializeCode = "wrapper => new LiteDB.BsonValue(wrapper.Value.Ticks)";
+ deserializeCode = $"bson => {name}.From(new System.TimeOnly(bson.AsInt64))";
+ break;
+
+ case "System.DateTimeOffset":
+ serializeCode = """
+ wrapper =>
+ new LiteDB.BsonDocument
+ {
+ ["DateTime"] = wrapper.Value.UtcDateTime,
+ ["Offset"] = wrapper.Value.Offset.Ticks
+ }
+ """;
+
+ deserializeCode = $$"""
+ bson =>
+ {
+ var doc = bson.AsDocument;
+ var utcDateTime = doc["DateTime"].AsDateTime;
+ var offset = new System.TimeSpan(doc["Offset"].AsInt64);
+
+ // 1. Create a DateTimeOffset from the UTC time (its offset will be zero).
+ var utcTime = new System.DateTimeOffset(utcDateTime);
+
+ // 2. Convert it to the original offset.
+ var originalTime = utcTime.ToOffset(offset);
+
+ return {{name}}.From(originalTime);
+ }
+ """;
+ break;
+
+ default:
+ serializeCode = "wrapper => new LiteDB.BsonValue(wrapper.Value)";
+ deserializeCode =
+ $"bson => {name}.From(({argument})System.Convert.ChangeType(bson.RawValue, typeof({argument})))";
+ break;
+ }
+
+ return $$"""
+ ///
+ /// Automatically registers the LiteDB BSON mapper for the {{name}} type.
+ ///
+ file static class {{name}}LiteDbInitializer
+ {
+ [System.Runtime.CompilerServices.ModuleInitializer]
+ internal static void Register()
+ {
+ LiteDB.BsonMapper.Global.RegisterType<{{name}}>(
+ serialize: {{serializeCode}},
+ deserialize: {{deserializeCode}}
+ );
+ }
+ }
+ """;
+ }
}
diff --git a/src/Primify/Primify.csproj b/src/Primify/Primify.csproj
index 278c69a..ad1f416 100644
--- a/src/Primify/Primify.csproj
+++ b/src/Primify/Primify.csproj
@@ -3,7 +3,7 @@
net9.0
Primify
- 1.4.22
+ 1.4.23
true
true
diff --git a/tests/Primify.Tests/DateOnlyWrapperClassTests.cs b/tests/Primify.Tests/DateOnlyWrapperClassTests.cs
index 4bab1c8..1b64ba3 100644
--- a/tests/Primify.Tests/DateOnlyWrapperClassTests.cs
+++ b/tests/Primify.Tests/DateOnlyWrapperClassTests.cs
@@ -15,8 +15,34 @@ public partial class DateOnlyPrimowrapClassWithPredefinedProperty
public static DateOnlyPrimowrapClassWithPredefinedProperty Empty => new(DateOnly.MinValue);
}
+[Primify]
+public partial record struct DateOnlyId;
+
+public class Foo
+{
+ public DateOnlyId Id { get; set; }
+}
+
public class DateOnlyWrapperClassTests(ITestOutputHelper testOutputHelper)
{
+ [Fact]
+ public void DateOnly_ReadWrite_ForLiteDb()
+ {
+ using var db = new LiteDatabase(":memory:");
+ var collection = db.GetCollection();
+
+ var foo = new Foo()
+ {
+ Id = DateOnlyId.From(DateOnly.MaxValue)
+ };
+
+ var insert = collection.Insert(foo);
+
+ var result = collection.FindById(foo.Id);
+
+ Assert.Equal(foo.Id, result.Id);
+ }
+
[Fact]
public void DateOnlyWrapperClass_CreatesType_WhenFromIsCalled()
{
diff --git a/tests/Primify.Tests/DateTimeOffsetWrapperClassTests.cs b/tests/Primify.Tests/DateTimeOffsetWrapperClassTests.cs
index 7bfddf6..be4dac4 100644
--- a/tests/Primify.Tests/DateTimeOffsetWrapperClassTests.cs
+++ b/tests/Primify.Tests/DateTimeOffsetWrapperClassTests.cs
@@ -15,8 +15,34 @@ public partial class DateTimeOffsetPrimowrapClassWithPredefinedProperty
public static DateTimeOffsetPrimowrapClassWithPredefinedProperty Empty => new(DateTimeOffset.MinValue);
}
+[Primify]
+public partial record struct DateTimeOffsetId;
+
+public class DateTimeOffsetFoo
+{
+ public DateTimeOffsetId Id { get; set; }
+}
+
public class DateTimeOffsetWrapperClassTests(ITestOutputHelper testOutputHelper)
{
+ [Fact]
+ public void DateTimeOffset_ReadWrite_ForLiteDb()
+ {
+ using var db = new LiteDatabase(":memory:");
+ var collection = db.GetCollection();
+
+ var foo = new DateTimeOffsetFoo()
+ {
+ Id = DateTimeOffsetId.From(DateTimeOffset.UtcNow)
+ };
+
+ var insert = collection.Insert(foo);
+
+ var result = collection.FindById(foo.Id);
+
+ Assert.Equal(foo.Id.ToString(), result.Id.ToString());
+ }
+
[Fact]
public void DateTimeOffsetWrapperClass_CreatesType_WhenFromIsCalled()
{
diff --git a/tests/Primify.Tests/TimeOnlyWrapperTests.cs b/tests/Primify.Tests/TimeOnlyWrapperTests.cs
new file mode 100644
index 0000000..96b1d37
--- /dev/null
+++ b/tests/Primify.Tests/TimeOnlyWrapperTests.cs
@@ -0,0 +1,366 @@
+namespace Primify.Generator.Tests;
+
+[Primify]
+public partial class TimeOnlyPrimowrapClass;
+
+// [Primify]
+// public partial class TimeOnlyWrapperClassWithNormalize
+// {
+// private static TimeOnly Normalize(TimeOnly value) => value < 1 ? -1 : value;
+// }
+
+[Primify]
+public partial class TimeOnlyPrimowrapClassWithPredefinedProperty
+{
+ public static TimeOnlyPrimowrapClassWithPredefinedProperty Empty => new(TimeOnly.MinValue);
+}
+
+[Primify]
+public partial record struct TimeOnlyId;
+
+public class TimeOnlyFoo
+{
+ public TimeOnlyId Id { get; set; }
+}
+
+public class TimeOnlyWrapperTests(ITestOutputHelper testOutputHelper)
+{
+ [Fact]
+ public void TimeOnly_ReadWrite_ForLiteDb()
+ {
+ using var db = new LiteDatabase(":memory:");
+ var collection = db.GetCollection();
+
+ var foo = new TimeOnlyFoo()
+ {
+ Id = TimeOnlyId.From(TimeOnly.MaxValue)
+ };
+
+ var insert = collection.Insert(foo);
+
+ var result = collection.FindById(foo.Id);
+
+ Assert.Equal(foo.Id, result.Id);
+ }
+
+ [Fact]
+ public void TimeOnlyWrapperClass_CreatesType_WhenFromIsCalled()
+ {
+ // Arrange
+ var expectedValue = TimeOnly.MinValue;
+
+ // Act
+ var result = TimeOnlyPrimowrapClass.From(expectedValue);
+ testOutputHelper.WriteLine(result.ToString());
+
+ // Assert
+ Assert.Equal(expectedValue, result.Value);
+ Assert.Equal(expectedValue, result.Value);
+ }
+
+ [Fact]
+ public void TimeOnlyWrapperClass_CreatesType_WhenExplicitlyCastToFromType()
+ {
+ var expectedValue = TimeOnly.MinValue;
+
+ var result1 = (TimeOnlyPrimowrapClass)expectedValue;
+ var result2 = (TimeOnly)result1;
+ testOutputHelper.WriteLine(result1.ToString());
+
+ Assert.Equal(expectedValue, result1.Value);
+ Assert.Equal(expectedValue, result1.Value);
+ Assert.Equal(expectedValue, result2);
+ }
+
+ // [Theory]
+ // [InlineData(1, 1)]
+ // [InlineData(10, 10)]
+ // [InlineData(0, -1)]
+ // [InlineData(-1, -1)]
+ // [InlineData(-100, -1)]
+ // public void TimeOnlyWrapperClassWithNormalize_ReturnsNormalizedValue_WhenCalledWithNonNormalizedValue(int value, int expected)
+ // {
+ // var result = TimeOnlyWrapperClassWithNormalize.From(value);
+ // testOutputHelper.WriteLine(result.ToString());
+ //
+ // Assert.Equal(expected, result.Value);
+ // }
+
+ [Fact]
+ public void TimeOnlyWrapperClassWithPredefinedProperty_IgnoresReadonly_WhenSerializedWithSystemTextJsonV1()
+ {
+ var expectedValue = TimeOnly.MaxValue;
+ var result = TimeOnlyPrimowrapClassWithPredefinedProperty.From(expectedValue);
+
+ // Default value to string
+ testOutputHelper.WriteLine("result.Value:");
+ testOutputHelper.WriteLine(result.Value.ToString());
+
+ Assert.Equal(expectedValue, result.Value);
+
+ // System.Text.Json serialization
+ var json = System.Text.Json.JsonSerializer.Serialize(result);
+ testOutputHelper.WriteLine("\nSystem.Text.Json serialization:");
+ testOutputHelper.WriteLine(json);
+
+ // System.Text.Json deserialization
+ var stjDeserialized =
+ System.Text.Json.JsonSerializer.Deserialize(json);
+ testOutputHelper.WriteLine("\nSystem.Text.Json deserialized value:");
+ testOutputHelper.WriteLine(stjDeserialized?.ToString() ?? "null");
+ Assert.Equal(expectedValue, stjDeserialized?.Value);
+ }
+
+ [Fact]
+ public void TimeOnlyWrapperClassWithPredefinedProperty_IgnoresReadonly_WhenSerializedWithSystemTextJson()
+ {
+ var expectedValue = TimeOnly.MinValue;
+ var result = TimeOnlyPrimowrapClassWithPredefinedProperty.Empty;
+
+ // Default value to string
+ testOutputHelper.WriteLine("result.Value:");
+ testOutputHelper.WriteLine(result.Value.ToString());
+
+ Assert.Equal(expectedValue, result.Value);
+
+ // System.Text.Json serialization
+ var json = System.Text.Json.JsonSerializer.Serialize(result);
+ testOutputHelper.WriteLine("\nSystem.Text.Json serialization:");
+ testOutputHelper.WriteLine(json);
+
+ // System.Text.Json deserialization
+ var stjDeserialized =
+ System.Text.Json.JsonSerializer.Deserialize(json);
+ testOutputHelper.WriteLine("\nSystem.Text.Json deserialized value:");
+ testOutputHelper.WriteLine(stjDeserialized?.ToString() ?? "null");
+ Assert.Equal(expectedValue, stjDeserialized?.Value);
+ }
+
+ [Fact]
+ public void TimeOnlyWrapperClassWithPredefinedProperty_IgnoresReadonly_WhenSerializedNewtonsoftJsonV1()
+ {
+ var expectedValue = TimeOnly.MaxValue;
+ var result = TimeOnlyPrimowrapClassWithPredefinedProperty.From(expectedValue);
+
+ // Default value to string
+ testOutputHelper.WriteLine("result.Value:");
+ testOutputHelper.WriteLine(result.Value.ToString());
+
+ Assert.Equal(expectedValue, result.Value);
+
+ // Newtonsoft.Json serialization
+ var newtonsoftJson = Newtonsoft.Json.JsonConvert.SerializeObject(result);
+ testOutputHelper.WriteLine("\nNewtonsoft.Json serialization:");
+ testOutputHelper.WriteLine(newtonsoftJson);
+
+ // Newtonsoft.Json deserialization
+ var njsDeserialized =
+ Newtonsoft.Json.JsonConvert.DeserializeObject(
+ newtonsoftJson);
+ testOutputHelper.WriteLine("\nNewtonsoft.Json deserialized value:");
+ testOutputHelper.WriteLine(njsDeserialized?.ToString() ?? "null");
+ Assert.Equal(expectedValue, njsDeserialized?.Value);
+ }
+
+ [Fact]
+ public void TimeOnlyWrapperClassWithPredefinedProperty_IgnoresReadonly_WhenSerializedNewtonsoftJson()
+ {
+ var expectedValue = TimeOnly.MinValue;
+ var result = TimeOnlyPrimowrapClassWithPredefinedProperty.From(expectedValue);
+
+ // Default value to string
+ testOutputHelper.WriteLine("result.Value:");
+ testOutputHelper.WriteLine(result.Value.ToString());
+
+ Assert.Equal(expectedValue, result.Value);
+
+ // Newtonsoft.Json serialization
+ var newtonsoftJson = Newtonsoft.Json.JsonConvert.SerializeObject(result);
+ testOutputHelper.WriteLine("\nNewtonsoft.Json serialization:");
+ testOutputHelper.WriteLine(newtonsoftJson);
+
+ // Newtonsoft.Json deserialization
+ var njsDeserialized =
+ Newtonsoft.Json.JsonConvert.DeserializeObject(
+ newtonsoftJson);
+ testOutputHelper.WriteLine("\nNewtonsoft.Json deserialized value:");
+ testOutputHelper.WriteLine(njsDeserialized?.ToString() ?? "null");
+ Assert.Equal(expectedValue, njsDeserialized?.Value);
+ }
+
+ [Fact]
+ public void TimeOnlyWrapperClassWithPredefinedProperty_IgnoresReadonly_WhenSerializedNewtonsoftBsonV1()
+ {
+ var expectedValue = TimeOnly.MaxValue;
+ var result = TimeOnlyPrimowrapClassWithPredefinedProperty.From(expectedValue);
+
+ // Default value to string
+ testOutputHelper.WriteLine("result.Value:");
+ testOutputHelper.WriteLine(result.Value.ToString());
+
+ Assert.Equal(expectedValue, result.Value);
+
+ // BSON serialization
+ using var ms = new MemoryStream();
+ using (var writer = new Newtonsoft.Json.Bson.BsonDataWriter(ms))
+ {
+ var serializer = new Newtonsoft.Json.JsonSerializer();
+ serializer.Serialize(writer, result);
+ }
+
+ var bsonBytes = ms.ToArray();
+ var bsonBase64 = Convert.ToBase64String(bsonBytes);
+ testOutputHelper.WriteLine("\nBSON serialization (Base64):");
+ testOutputHelper.WriteLine(bsonBase64);
+
+ // BSON deserialization
+ using var ms2 = new MemoryStream(bsonBytes);
+ using (var reader = new Newtonsoft.Json.Bson.BsonDataReader(ms2))
+ {
+ var serializer = new Newtonsoft.Json.JsonSerializer();
+ var bsonDeserialized = serializer.Deserialize(reader);
+ testOutputHelper.WriteLine("\nBSON deserialized value:");
+ testOutputHelper.WriteLine(bsonDeserialized?.ToString() ?? "null");
+
+ // Compare the underlying DateTime values directly to avoid timezone/offset issues
+ var expectedDateTime = expectedValue;
+ var actualDateTime = bsonDeserialized?.Value;
+ Assert.Equal(expectedDateTime.ToString(), actualDateTime.Value.ToString());
+ }
+ }
+
+ [Fact]
+ public void TimeOnlyWrapperClassWithPredefinedProperty_IgnoresReadonly_WhenSerializedNewtonsoftBsonV3()
+ {
+ var expectedValue = TimeOnly.MaxValue;
+ var result = TimeOnlyPrimowrapClassWithPredefinedProperty.From(expectedValue);
+
+ testOutputHelper.WriteLine($"Original Expected: {expectedValue:o}");
+ Assert.Equal(expectedValue, result.Value);
+
+ // BSON serialization
+ using var ms = new MemoryStream();
+ using (var writer = new Newtonsoft.Json.Bson.BsonDataWriter(ms))
+ {
+ var serializer = new Newtonsoft.Json.JsonSerializer();
+ serializer.Serialize(writer, result);
+ }
+
+ var bsonBytes = ms.ToArray();
+
+ // BSON deserialization
+ using var ms2 = new MemoryStream(bsonBytes);
+ using (var reader = new Newtonsoft.Json.Bson.BsonDataReader(ms2))
+ {
+ var serializer = new Newtonsoft.Json.JsonSerializer();
+ var bsonDeserialized = serializer.Deserialize(reader);
+
+ testOutputHelper.WriteLine($"Deserialized Actual: {bsonDeserialized?.Value:o}");
+
+ // *** FIX FOR THE TEST ***
+ // BSON loses sub-millisecond precision. We must truncate the expected value
+ // to match the precision of the actual value before comparing.
+
+ // 1. Get the Ticks of the original UTC DateTime
+ long originalTicks = expectedValue.Ticks;
+
+ // 2. Truncate the ticks to the nearest millisecond
+ long truncatedTicks = originalTicks - (originalTicks % TimeSpan.TicksPerMillisecond);
+
+ // 3. Create a new TimeOnly with the truncated value for comparison
+ var expectedValueTruncated = TimeOnly.FromDateTime(new DateTime(truncatedTicks));
+
+ testOutputHelper.WriteLine($"Truncated Expected: {expectedValueTruncated}");
+
+ Assert.Equal(expectedValueTruncated.ToString(), bsonDeserialized?.Value.ToString());
+ }
+ }
+
+ [Fact]
+ public void TimeOnlyWrapperClassWithPredefinedProperty_IgnoresReadonly_WhenSerializedNewtonsoftBson()
+ {
+ var expectedValue = TimeOnly.MinValue;
+ var result = TimeOnlyPrimowrapClassWithPredefinedProperty.From(expectedValue);
+
+ // Default value to string
+ testOutputHelper.WriteLine("result.Value:");
+ testOutputHelper.WriteLine(result.Value.ToString());
+
+ Assert.Equal(expectedValue, result.Value);
+
+ // BSON serialization
+ using var ms = new MemoryStream();
+ using (var writer = new Newtonsoft.Json.Bson.BsonDataWriter(ms))
+ {
+ var serializer = new Newtonsoft.Json.JsonSerializer();
+ serializer.Serialize(writer, result);
+ }
+
+ var bsonBytes = ms.ToArray();
+ var bsonBase64 = Convert.ToBase64String(bsonBytes);
+ testOutputHelper.WriteLine("\nBSON serialization (Base64):");
+ testOutputHelper.WriteLine(bsonBase64);
+
+ // BSON deserialization
+ using var ms2 = new MemoryStream(bsonBytes);
+ using (var reader = new Newtonsoft.Json.Bson.BsonDataReader(ms2))
+ {
+ var serializer = new Newtonsoft.Json.JsonSerializer();
+ var bsonDeserialized = serializer.Deserialize(reader);
+ testOutputHelper.WriteLine("\nBSON deserialized value:");
+ testOutputHelper.WriteLine(bsonDeserialized?.ToString() ?? "null");
+
+ // Compare the underlying DateTime values directly to avoid timezone/offset issues
+ var expectedDateTime = expectedValue;
+ var actualDateTime = bsonDeserialized?.Value;
+ Assert.Equal(expectedDateTime, actualDateTime);
+ }
+ }
+
+ [Fact]
+ public void TimeOnlyWrapperClassWithPredefinedProperty_IgnoresReadonly_WhenSerializedNewtonsoftBsonV2()
+ {
+ var expectedValue = TimeOnly.MinValue;
+ var result = TimeOnlyPrimowrapClassWithPredefinedProperty.From(expectedValue);
+
+ // Default value to string
+ testOutputHelper.WriteLine("result.Value:");
+ testOutputHelper.WriteLine(result.Value.ToString("o")); // Use ISO 8601 for clarity
+
+ Assert.Equal(expectedValue, result.Value);
+
+ // **SOLUTION: Configure the serializer to handle dates as UTC.**
+ var serializerSettings = new Newtonsoft.Json.JsonSerializerSettings
+ {
+ DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc
+ };
+ var serializer = Newtonsoft.Json.JsonSerializer.Create(serializerSettings);
+
+ // BSON serialization
+ using var ms = new MemoryStream();
+ using (var writer = new Newtonsoft.Json.Bson.BsonDataWriter(ms))
+ {
+ serializer.Serialize(writer, result);
+ }
+
+ var bsonBytes = ms.ToArray();
+ var bsonBase64 = Convert.ToBase64String(bsonBytes);
+ testOutputHelper.WriteLine("\nBSON serialization (Base64):");
+ testOutputHelper.WriteLine(bsonBase64);
+
+ // BSON deserialization
+ using var ms2 = new MemoryStream(bsonBytes);
+ using (var reader = new Newtonsoft.Json.Bson.BsonDataReader(ms2))
+ {
+ // Ensure the reader also respects the UTC setting
+ reader.DateTimeKindHandling = System.DateTimeKind.Utc;
+
+ var bsonDeserialized = serializer.Deserialize(reader);
+ testOutputHelper.WriteLine("\nBSON deserialized value:");
+ testOutputHelper.WriteLine(bsonDeserialized?.Value.ToString("o") ?? "null");
+
+ // The assertion should now pass without any special handling.
+ Assert.Equal(expectedValue, bsonDeserialized?.Value);
+ }
+ }
+}