public override object Deserialize(
BsonReader bsonReader,
Type nominalType,
Type actualType,
IBsonSerializationOptions options)
{
VerifyTypes(nominalType, actualType, typeof(DateTime));
var dateTimeSerializationOptions = EnsureSerializationOptions<DateTimeSerializationOptions>(options);
var bsonType = bsonReader.GetCurrentBsonType();
DateTime value;
switch (bsonType)
{
case BsonType.DateTime:
// use an intermediate BsonDateTime so MinValue and MaxValue are handled correctly
value = new BsonDateTime(bsonReader.ReadDateTime()).ToUniversalTime();
break;
case BsonType.Document:
bsonReader.ReadStartDocument();
bsonReader.ReadDateTime("DateTime"); // ignore value (use Ticks instead)
value = new DateTime(bsonReader.ReadInt64("Ticks"), DateTimeKind.Utc);
bsonReader.ReadEndDocument();
break;
case BsonType.Int64:
value = DateTime.SpecifyKind(new DateTime(bsonReader.ReadInt64()), DateTimeKind.Utc);
break;
case BsonType.String:
// note: we're not using XmlConvert because of bugs in Mono
if (dateTimeSerializationOptions.DateOnly)
{
value = DateTime.SpecifyKind(DateTime.ParseExact(bsonReader.ReadString(), "yyyy-MM-dd", null), DateTimeKind.Utc);
}
else
{
var formats = new string[] { "yyyy-MM-ddK", "yyyy-MM-ddTHH:mm:ssK", "yyyy-MM-ddTHH:mm:ss.FFFFFFFK" };
value = DateTime.ParseExact(bsonReader.ReadString(), formats, null, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
}
break;
default:
var message = string.Format("Cannot deserialize DateTime from BsonType {0}.", bsonType);
throw new Exception(message);
}
if (dateTimeSerializationOptions.DateOnly)
{
if (value.TimeOfDay != TimeSpan.Zero)
{
throw new Exception("TimeOfDay component for DateOnly DateTime value is not zero.");
}
value = DateTime.SpecifyKind(value, dateTimeSerializationOptions.Kind); // not ToLocalTime or ToUniversalTime!
}
else
{
switch (dateTimeSerializationOptions.Kind)
{
case DateTimeKind.Local:
case DateTimeKind.Unspecified:
value = DateTime.SpecifyKind(BsonUtils.ToLocalTime(value), dateTimeSerializationOptions.Kind);
break;
case DateTimeKind.Utc:
value = BsonUtils.ToUniversalTime(value);
break;
}
}
return value;
}