我将从我的C#winform应用程序发送的UTC日期时间发送到MongoDb 3.4.5,但它在MongoDb中存储为本地时间。当我从Mongo获取数据时,它返回UTC时间。
我的问题是,为什么日期时间存储在MongoDb的本地,尽管从UI发送UTC日期时间。我希望UTC时间存储在MongoDb中。 以下是代码段:
public void InsertInMongo()
{
var client = new MongoClient("mongodb://localhost:27017");
var db = client.GetDatabase("Test");
var col = db.GetCollection<TestData>("TestData");
var data = new TestData(123,DateTime.UtcNow);
col.InsertOne(data);
var fromMongo = col.Find(Builders<TestData>.Filter.Empty).ToList();
}
}
class TestData
{
public TestData(int num, DateTime date)
{
TestNumber = num;
TestDate = date;
}
[BsonId]
[BsonElement("_id")]
[BsonRepresentation(BsonType.ObjectId)]
[BsonIgnoreIfDefault]
public string Id { get; private set; }
public int TestNumber { get; set; }
public DateTime TestDate { get; set; }
}
}
我该如何解决这个问题?我是使用C#在Mongo的新手。
答案 0 :(得分:2)
您需要像这样声明自定义DateTimeSerializer
:
public class BsonUtcDateTimeSerializer : DateTimeSerializer
{
public override DateTime Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return new DateTime(base.Deserialize(context, args).Ticks, DateTimeKind.Unspecified);
}
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DateTime value)
{
var utcValue = new DateTime(value.Ticks, DateTimeKind.Utc);
base.Serialize(context, args, utcValue);
}
}
然后你需要在创建连接后注册;像这样的东西:
var server = new MongoClient("mongodb://127.0.0.1");
var database = server.GetDatabase("Test");
var collection = database.GetCollection<MyObject>("MyObject");
BsonSerializer.RegisterSerializer(typeof(DateTime), new BsonUtcDateTimeSerializer());
编辑:
BSON Date是 64位整数,表示自Unix纪元(1970年1月1日)以来的毫秒数。这导致过去和未来的可表示日期范围约为2.9亿年 官方BSON规范将BSON日期类型称为UTC
datetime
。
因此,MongoDB中的日期是UTC毫秒,那么从MongoDB中获取数据的应用程序会以本地化格式显示它们。
MongoDB默认以UTC格式存储时间,并将任何本地时间表示转换为此形式。必须运行或报告某些未修改的本地时间值的应用程序可以将时区与UTC时间戳一起存储,并在其应用程序逻辑中计算原始本地时间。
答案 1 :(得分:0)
我认为你将不得不转换回特定的时区。您需要确定UTC时间与从mongo获得的时间之间的偏差。如果没有偏移,那么Mongo也将它存储为UTC,我打赌这种情况正在发生。我怀疑,例如,你会发现它是区域性的,如EST。建立时区信息后,您可以使用TimeZoneInfo
对象或类似的对象从一个区域转换为另一个区域,但是,您需要知道要转换为的时区。
答案 2 :(得分:0)
因此,这是mongo DB UI的情况,Compass始终以用户的本地日期格式显示存储的数据,但Robo3T或mongoDB shell则不是这种情况。 除非明确指定将日期存储在本地,否则MongoDB始终以UTC格式存储日期。
答案 3 :(得分:0)
MongoDB提供了一个自动完成技巧的属性。
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
所以您只需要在TestDate属性上添加此属性