public override void Serialize(
BsonWriter bsonWriter,
Type nominalType,
object value,
IBsonSerializationOptions options)
{
var dateTime = (DateTime)value;
var dateTimeSerializationOptions = EnsureSerializationOptions<DateTimeSerializationOptions>(options);
DateTime utcDateTime;
if (dateTimeSerializationOptions.DateOnly)
{
if (dateTime.TimeOfDay != TimeSpan.Zero)
{
throw new BsonSerializationException("TimeOfDay component is not zero.");
}
utcDateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); // not ToLocalTime
}
else
{
utcDateTime = BsonUtils.ToUniversalTime(dateTime);
}
var millisecondsSinceEpoch = BsonUtils.ToMillisecondsSinceEpoch(utcDateTime);
switch (dateTimeSerializationOptions.Representation)
{
case BsonType.DateTime:
bsonWriter.WriteDateTime(millisecondsSinceEpoch);
break;
case BsonType.Document:
bsonWriter.WriteStartDocument();
bsonWriter.WriteDateTime("DateTime", millisecondsSinceEpoch);
bsonWriter.WriteInt64("Ticks", utcDateTime.Ticks);
bsonWriter.WriteEndDocument();
break;
case BsonType.Int64:
bsonWriter.WriteInt64(utcDateTime.Ticks);
break;
case BsonType.String:
if (dateTimeSerializationOptions.DateOnly)
{
bsonWriter.WriteString(dateTime.ToString("yyyy-MM-dd"));
}
else
{
// we're not using XmlConvert.ToString because of bugs in Mono
if (dateTime == DateTime.MinValue || dateTime == DateTime.MaxValue)
{
// serialize MinValue and MaxValue as Unspecified so we do NOT get the time zone offset
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified);
}
else if (dateTime.Kind == DateTimeKind.Unspecified)
{
// serialize Unspecified as Local se we get the time zone offset
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
}
bsonWriter.WriteString(dateTime.ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFFK"));
}
break;
default:
var message = string.Format("'{0}' is not a valid DateTime representation.", dateTimeSerializationOptions.Representation);
throw new BsonSerializationException(message);
}
}
}