Skip to content

Conversation

papafe
Copy link
Contributor

@papafe papafe commented Sep 30, 2025

No description provided.

@papafe papafe requested a review from rstam September 30, 2025 16:54
@papafe papafe requested a review from a team as a code owner September 30, 2025 16:54
@papafe papafe added the feature label Sep 30, 2025
bsonWriter.WriteInt32("Minute", value.Minute);
bsonWriter.WriteInt32("Second", value.Second);
bsonWriter.WriteInt32("Millisecond", value.Millisecond);
#if NET7_0_OR_GREATER
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Microsecond and Nanosecond were introduced in .NET 7.0

Copy link
Contributor

@rstam rstam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good. Let me know what you think of the comments.


_helper = new SerializerHelper
(
new SerializerHelper.Member("Hour", Flags.Hour, isOptional: true),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a little weird that these are optional.

In understand that we ignore them during deserialization (we only use Ticks). But that doesn't necessarily mean they are optional.

We also might want to validate during deserialization that the Hour, Minutes, Second etc.. fields are consistent with the Ticks value. If WE wrote the values they should be consistent, but if the data came from outside the C# driver they might not be.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider the following change:

_helper = new SerializerHelper
(
    new SerializerHelper.Member("Hour", Flags.Hour, isOptional: false),
    new SerializerHelper.Member("Minute", Flags.Minute, isOptional: false),
    new SerializerHelper.Member("Second", Flags.Second, isOptional: false),
    new SerializerHelper.Member("Millisecond", Flags.Millisecond, isOptional: false),
    new SerializerHelper.Member("Microsecond", Flags.Microsecond, isOptional: true), // not serialized by older versions of the driver
    new SerializerHelper.Member("Nanosecond", Flags.Nanosecond, isOptional: true), // not serialized by older versions of the driver  
    new SerializerHelper.Member("Ticks", Flags.Ticks, isOptional: false)                                                              
);                                                                                                                                    

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, that probably those should not be optional, I'll answer the question about validation in the other comment.

bsonWriter.WriteString(value.ToString("o"));
break;

case BsonType.Document:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put case BsonType.Document first in the switch statement (alphabetical order).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider the following refactoring so that we consistently write the Microsecond and Nanosecond properties even on older versions of .NET:

                case BsonType.Document:
#if NET7_0_OR_GREATER
                    var microsecond = value.Microsecond;
                    var nanosecond = value.Nanosecond;
#else
                    var microsecond = ComputeMicrosecondFromTicks(value.Ticks);
                    var nanosecond = ComputeNanosecondFromTicks(value.Ticks);
#endif
                    bsonWriter.WriteStartDocument();
                    bsonWriter.WriteInt32("Hour", value.Hour);
                    bsonWriter.WriteInt32("Minute", value.Minute);
                    bsonWriter.WriteInt32("Second", value.Second);
                    bsonWriter.WriteInt32("Millisecond", value.Millisecond);
                    bsonWriter.WriteInt32("Microsecond", microsecond);
                    bsonWriter.WriteInt32("Nanosecond", nanosecond);
                    bsonWriter.WriteInt64("Ticks", value.Ticks);
                    bsonWriter.WriteEndDocument();
                    break;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ComputeMicrosecondFromTicks and ComputeNanosecondFromTicks helper methods can be something like:

private int ComputeMicrosecondFromTicks(long ticks)
{
    return (int)(ticks / (TimeSpan.TicksPerMillisecond * 1_000)) % 1000;
}
 
private int ComputeNanosecondFromTicks(long ticks)
{
    return (int)(ticks / (TimeSpan.TicksPerMillisecond * 1_000_000)) % 1000;
}                                                                           

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the use of the preprocessor directives, that was my first implementation but I thought that given that the implementation is the same, we would not need to necessarily make a differentiation.

case Flags.Millisecond:
case Flags.Microsecond:
case Flags.Nanosecond:
bsonReader.SkipValue(); break; // ignore value (use Ticks instead)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want to ignore these values?

Should we check that they are in agreement with the Ticks value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is similar to what we do with DateTimeSerializer and DateOnlySerializer, where we ignore the DateTime value when the representation is BsonType.Document and use only the ticks.
The difference is that here we have many more fields that we ignoring. I was trying to be the most permissive here, but I understand if want to be more strict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants