Litedb: Can I override default Bson datetime reader to read datetime as utc?

Created on 25 Sep 2017  路  6Comments  路  Source: mbdavid/LiteDB

This solution doesn't work for me.

            BsonMapper.Global.RegisterType<DateTime>(
                dateTime => new BsonValue(dateTime.ToMillisUnixTimestamp()),
                bsonValue => DateTimeExtensions.MillisUnixTimestampToDateTime(bsonValue.AsInt64)
            );

Most helpful comment

It麓s better use Serialize/Deserialize method in this case:

Deserialize Func is Func<BsonValue, BsonMapper, object>
Serialize Func is Func<BsonValue, BsonMapper, object>

C# BsonMapper.Global.ResolveMember((type, memberInfo, member) => { if(member.DataType == typeof(DateTime)) { member.Deserialize = (v, m) => v.AsDateTime.ToMillisUnixTimestamp(); member.Setter = (o, m) => DateTimeExtensions.MillisUnixTimestampToDateTime(Convert.ToInt64(o)); } });

This will override all DateTime types to convert to Int64 before serialize into Bson.

All 6 comments

Hi @Try4W, custom data type are not supported in basic already implemented internal types. But you can write your own mapper getter/setter function (implement ResolveMember method).

BsonMapper.Global.ResolveMember((type, memberInfo, member) =>
{
    if(member.DataType == typeof(DateTime))
    {
        member.Getter = ...
        member.Setter = ...
    } 
});

I will try it, thanks!

I can't find any documentation about how to implement MemberMapper.Getter and MemberMapper.Setter delegates. Can you provide a short example?

It麓s better use Serialize/Deserialize method in this case:

Deserialize Func is Func<BsonValue, BsonMapper, object>
Serialize Func is Func<BsonValue, BsonMapper, object>

C# BsonMapper.Global.ResolveMember((type, memberInfo, member) => { if(member.DataType == typeof(DateTime)) { member.Deserialize = (v, m) => v.AsDateTime.ToMillisUnixTimestamp(); member.Setter = (o, m) => DateTimeExtensions.MillisUnixTimestampToDateTime(Convert.ToInt64(o)); } });

This will override all DateTime types to convert to Int64 before serialize into Bson.

mbdavid's solution with some fixes:

            BsonMapper.Global.ResolveMember += (type, memberInfo, member) =>
            {
                if (member.DataType == typeof(DateTime))
                {
                    member.Deserialize = (v, m) => DateTimeExtensions.MillisUnixTimestampFromDateTime(v.AsInt64);
                    member.Serialize = (o, m) => new BsonValue(((DateTime) o).ToMillisUnixTimestamp());
                }
            };

And some extensions:

    public static class DateTimeExtensions
    {

        public static long ToMillisUnixTimestamp(this DateTime dateTime)
        {
            return (long)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
        }

        public static DateTime MillisUnixTimestampFromDateTime(long unixTimeStamp)
        {
            // Unix timestamp is seconds past epoch
            var dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            dateTime = dateTime.AddMilliseconds(unixTimeStamp);
            return dateTime.ToLocalTime();
        }
    }

Hi @Try4W, current master branch already support UTC dates in connection string. Will be available in v4.1

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dangershony picture dangershony  路  3Comments

GW-FUB picture GW-FUB  路  3Comments

rstat1 picture rstat1  路  3Comments

lidanger picture lidanger  路  3Comments

MoamenMohamed picture MoamenMohamed  路  4Comments