[CSHARP-2997] DateTimeSerializer with different Tick count when deserializing Created: 06/Mar/20 Updated: 27/Oct/23 Resolved: 09/Mar/20 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | Serialization |
| Affects Version/s: | 2.10.2 |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Samir Kharchi | Assignee: | Robert Stam |
| Resolution: | Works as Designed | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Win10 |
||
| Description |
|
Using the DateTimeSerializer the tick count differs when deserializing a DateTime object: DateTimeSerializer.LocalInstance.Serialize(context, args, aDateTime); The deserialized DateTime object is equal to the original except for the Tick count which differs by some nanoseconds (this is reproducable and it's always the last 4 digits of the tick count that differ). Here is one Xunit exception message: Xunit.Sdk.EqualException: "Assert.Equal() Failure
|
| Comments |
| Comment by Robert Stam [ 10/Mar/20 ] | |||||||||||||||||||||||||||||||||
|
Also, you can change the default representation for a .NET DateTime in your application by executing the following lines at startup:
But keep in mind that the serializer registry is only used when serializing POCOs (classes), so registering that serializer will have no effect on any code that use the BsonDocument object model, such as:
| |||||||||||||||||||||||||||||||||
| Comment by Robert Stam [ 10/Mar/20 ] | |||||||||||||||||||||||||||||||||
|
You make a good point that it is unfortunate that the default representation for a .NET DateTime in a binary BSON document results in truncation to millisecond precision. In hindsight, since there is no exact match between a .NET DateTime and a BSON binary type, it might have been better to require applications to explicitly specify how they want a .NET DateTime to be represented in BSON. The default we chose is probably the one most applications would make (unless they need more than millisecond precision of course). For most applications the default is convenient. Sorry this caused you an issue. | |||||||||||||||||||||||||||||||||
| Comment by Samir Kharchi [ 10/Mar/20 ] | |||||||||||||||||||||||||||||||||
|
First of all thanks Robert for investigating and explaining. Also thanks for the alternative representations in order to workaround this, I'll definetly take that route (though I have already switched to storing the tick count itself and parse the datetime back from that). However, what you are saying is that the default serialization (due to the according bson representation) is not symmetric and that this is accepted by design? This doesn't seem right imo from an API perspective. How is it a non-working process is the accepted default behavior for such a core data type in a language specific driver? It might be expected and If it was an alternative representation, ok, but as a default? It renders any default serialization bogus without the user knowing (there is no such info in the driver documentation) it's hard to embrace this as not being an issue. But that's just my 2 cents.. Cheers in any case | |||||||||||||||||||||||||||||||||
| Comment by Robert Stam [ 09/Mar/20 ] | |||||||||||||||||||||||||||||||||
|
While it might be a bit surprising, this is the expected behavior. The reason is that by default a .NET DateTime value is serialized as a BSON datetime (converted to UTC), and in BSON the resolution of a datetime is in milliseconds. See: So when a .NET DateTime is converted to a BSON datetime and back again the result is truncated to millisecond precision. If you need to store a DateTime value with the same precision as the native .NET precision you can specify an alternative representation. The following code shows some examples using the 4 possible representations:
Where the ToJson helper function is:
Note that the Int64 and String representations, while providing round trip capability with no loss of precision, cannot be queried with datetime semantics because they are not represented as BSON datetimes. To the server these representations are just a 64-bit integer or a string, and it has no way of knowing that these actually represent datetime values.
| |||||||||||||||||||||||||||||||||
| Comment by Samir Kharchi [ 06/Mar/20 ] | |||||||||||||||||||||||||||||||||
|
Btw. I am using and testing with a local MongoDB Server v4.2 |