web-dev-qa-db-ja.com

協定世界時と現地の日時をMongoに保存する

日時をUTCとして保存するMongoC#実装があります。

MongoDB.Bson.Serialization.Options.DateTimeSerializationOptions options = 
    MongoDB.Bson.Serialization.Options.DateTimeSerializationOptions.UtcInstance;

var serializer = 
    new MongoDB.Bson.Serialization.Serializers.DateTimeSerializer(options);

MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(
    typeof(DateTime),
    serializer);

また、UTCとともにユーザーのローカルタイムゾーンを保存する必要があります。説明するために、私は次のような2つのプロパティがあります

DateTime WorkItemToCompleteBy{get; set;}
[BsonDateTimeOptions(Kind = DateTimeKind.Unspecified)]
DateTime WorkItemToCompleteByLocal{get; set;}

オーストラリア/アメリカ/インディアン/その他の時間をローカルプロパティに保存し、それぞれのUTC値をもう一方のプロパティに保存したいと思います。数十のタイムゾーンを扱っているので、UTCを目的のタイムゾーンに変換してWorkItemToCompleteByLocalプロパティに格納するコードがあります。 Mongoにこの値を「現状のまま」保存して返してもらいたいのですが。問題は、Mongoが常にそれをISODateとして保存し、値をUTCバージョンに変換することです。説明する。 UTCが0730時間で、ブリスベン時間を1730時間に計算し、それをWorkitemToCompleteByLocalに設定すると、次のように保存されます。

"WorkItemToCompleteBy" : ISODate("2013-06-05T07:30:00Z"),
"WorkItemToCompleteByLocal" : ISODate("2013-06-05T12:00:00Z"),

Mongoは、提供された時間をローカルとして解釈しますサーバーはインドにありますそしてそれを1200時間の同等のUTCに変換します。値を1730として取得しますが(ISTですが)、目的が果たせず、Mongoで現地時間ベースのクエリを実行できなくなります。アイデアが足りません。 WorkItemToCompleteByLocalの日付を変更せずに「現状のまま」保存するのに役立つヘルプをいただければ幸いです。

13
LIFE REFACTORED

C#ドライバーの新しいバージョン=>

    public class MyMongoDBDateTimeSerializer : DateTimeSerializer
{
    //  MongoDB returns datetime as DateTimeKind.Utc, which cann't be used in our timezone conversion logic
    //  We overwrite it to be DateTimeKind.Unspecified
    public override DateTime Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var obj = base.Deserialize(context, args);
        return new DateTime(obj.Ticks, DateTimeKind.Unspecified);
    }

    //  MongoDB stores all datetime as Utc, any datetime value DateTimeKind is not DateTimeKind.Utc, will be converted to Utc first
    //  We overwrite it to be DateTimeKind.Utc, becasue we want to preserve the raw value
    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DateTime value)
    {
        var utcValue = new DateTime(value.Ticks, DateTimeKind.Utc);
        base.Serialize(context, args, utcValue);
    }
}
8
Boler

これは、MongoDBに生の値を保存させ、DateTimeオブジェクトのDateTimeKind属性を無視する方法です。

これはお客様のビジネスロジックには当てはまらない場合がありますが、特定の理由から私たちにとっては理にかなっています。

BsonSerializer.RegisterSerializer(typeof(DateTime), new MyMongoDBDateTimeSerializer());


public class MyMongoDBDateTimeSerializer : DateTimeSerializer
{
    //  MongoDB returns datetime as DateTimeKind.Utc, which cann't be used in our timezone conversion logic
    //  We overwrite it to be DateTimeKind.Unspecified
    public override object Deserialize(MongoDB.Bson.IO.BsonReader bsonReader, System.Type nominalType, MongoDB.Bson.Serialization.IBsonSerializationOptions options)
    {
        var obj = base.Deserialize(bsonReader, nominalType, options);
        var dt = (DateTime) obj;
        return new DateTime(dt.Ticks, DateTimeKind.Unspecified);
    }

    //  MongoDB returns datetime as DateTimeKind.Utc, which cann't be used in our timezone conversion logic
    //  We overwrite it to be DateTimeKind.Unspecified
    public override object Deserialize(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType, Type actualType, MongoDB.Bson.Serialization.IBsonSerializationOptions options)
    {
        var obj = base.Deserialize(bsonReader, nominalType, actualType, options);
        var dt = (DateTime)obj;
        return new DateTime(dt.Ticks, DateTimeKind.Unspecified);
    }

    //  MongoDB stores all datetime as Utc, any datetime value DateTimeKind is not DateTimeKind.Utc, will be converted to Utc first
    //  We overwrite it to be DateTimeKind.Utc, becasue we want to preserve the raw value
    public override void Serialize(MongoDB.Bson.IO.BsonWriter bsonWriter, System.Type nominalType, object value, MongoDB.Bson.Serialization.IBsonSerializationOptions options)
    {
        var dt = (DateTime) value;
        var utcValue = new DateTime(dt.Ticks, DateTimeKind.Utc);
        base.Serialize(bsonWriter, nominalType, utcValue, options);
    }
}
23
user2247475

.netドライバーバージョン2.4では、次を使用します。

using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;

BsonSerializer.RegisterSerializer(DateTimeSerializer.LocalInstance);

このようにして、日時値はkind = utcでdbに格納されますが、ローカルの種類で逆シリアル化されます。

3
user2583458