Skip to content

Instantly share code, notes, and snippets.

@rodion-m
Last active April 3, 2019 16:23
Show Gist options
  • Save rodion-m/4b321a69cd7858ca7aeaef4e05357742 to your computer and use it in GitHub Desktop.
Save rodion-m/4b321a69cd7858ca7aeaef4e05357742 to your computer and use it in GitHub Desktop.
using System;
using System.Globalization;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace Main
{
public class DateTimeOffsetBsonSerializer : StructSerializerBase<DateTimeOffset>,
IRepresentationConfigurable<DateTimeOffsetBsonSerializer>
{
public TimeSpan _defaultOffset;
private BsonType _representation;
private string StringSerializationFormat = "YYYY-MM-ddTHH:mm:ss.FFFFFFK";
public DateTimeOffsetBsonSerializer(TimeSpan? offset = null) : this(BsonType.DateTime)
{
_defaultOffset = offset ?? TimeZoneInfo.Local.BaseUtcOffset;
}
public DateTimeOffsetBsonSerializer(BsonType representation)
{
switch (representation)
{
case BsonType.String:
case BsonType.DateTime:
break;
default:
throw new ArgumentException(
$"{representation} is not a valid representation for {this.GetType().Name}");
}
_representation = representation;
}
public BsonType Representation => _representation;
public override DateTimeOffset Deserialize(BsonDeserializationContext context,
BsonDeserializationArgs args)
{
var bsonReader = context.Reader;
BsonType bsonType = bsonReader.GetCurrentBsonType();
switch (bsonType)
{
case BsonType.String:
var stringValue = bsonReader.ReadString();
return DateTimeOffset.ParseExact
(stringValue, StringSerializationFormat, DateTimeFormatInfo.InvariantInfo);
case BsonType.DateTime:
var unitTimeMs = bsonReader.ReadDateTime();
return DateTimeOffset.FromUnixTimeMilliseconds(unitTimeMs).ToOffset(_defaultOffset);
default:
throw CreateCannotDeserializeFromBsonTypeException(bsonType);
}
}
public override void Serialize
(BsonSerializationContext context, BsonSerializationArgs args, DateTimeOffset value)
{
var bsonWriter = context.Writer;
switch (_representation)
{
case BsonType.String:
bsonWriter.WriteString(value.ToString
(StringSerializationFormat, DateTimeFormatInfo.InvariantInfo));
break;
case BsonType.DateTime:
bsonWriter.WriteDateTime(value.ToUnixTimeMilliseconds());
break;
default:
var message = $"'{_representation}' is not a valid DateTimeOffset representation.";
throw new BsonSerializationException(message);
}
}
public DateTimeOffsetBsonSerializer WithRepresentation(BsonType representation)
{
if(representation == _representation)
{
return this;
}
return new DateTimeOffsetBsonSerializer(representation);
}
IBsonSerializer IRepresentationConfigurable.WithRepresentation(BsonType representation)
{
return WithRepresentation(representation);
}
protected new Exception CreateCannotDeserializeFromBsonTypeException(BsonType bsonType)
{
var message = $"Cannot deserialize a '{BsonUtils.GetFriendlyTypeName(ValueType)}' from BsonType '{bsonType}'.";
return new FormatException(message);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment