2013-06-03 48 views
9

Tôi có một triển khai C# Mongo C lưu trữ datetime là UTC.Lưu trữ Utc và giờ địa phương ở Mongo

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); 

Tôi cũng cần lưu trữ múi giờ địa phương của người dùng cùng với UTC. Để giải thích, tôi có hai thuộc tính mà đi như

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

Tôi muốn để lưu trữ lần Ấn Độ/Khác Úc/Mỹ/trong bất động sản địa phương và giá trị tính theo giờ UTC tương ứng trong một trong những khác. Kể từ khi giao dịch với hàng chục múi giờ, tôi có mã chuyển đổi UTC thành múi giờ mong muốn và lưu nó trong thuộc tính WorkItemToCompleteByLocal. Tôi muốn Mongo lưu trữ giá trị này 'as-is' và trả lại cho tôi. Vấn đề là Mongo luôn lưu trữ nó như là ISODate và chuyển đổi giá trị thành phiên bản Utc. Để giải thích. Nếu UTC là 0730 giờ và tôi tính Brisbane Thời gian để 1730Hours và đặt nó vào WorkitemToCompleteByLocal, họ nhận được lưu lại dưới dạng

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

Mongo giải thích thời gian cung cấp như địa phương, server là ở Ấn Độ và lông nó để UTC tương đương 1200 giờ. Trong khi nó lấy các giá trị trở lại là 1730 (IST Albeit) Nó đánh bại mục đích của tôi và ngăn tôi chạy bất kỳ truy vấn dựa trên thời gian cục bộ nào trên Mongo. Ra khỏi ý tưởng. Bất kỳ trợ giúp nào được đánh giá cao để giúp lưu trữ ngày WorkItemToCompleteByLocal 'As-Is' mà không sửa đổi

+1

Tôi tìm thấy một công việc xung quanh bằng cách lừa hệ thống bằng cách tính lại múi giờ 'Địa phương' thành UTC bằng cách hydrating DateTime mới (Local.Year, Local.Month ......., Kind.Utc) và sau đó sử dụng giá trị đó. Bây giờ, các dữ liệu được lưu trữ như là và logic của tôi biết cột địa phương lưu trữ giá trị địa phương bất kể những gì loại nói (nó nói UTC vì công việc xung quanh thông qua). Tôi sẽ sử dụng điều này cho đến khi tôi tìm thấy một câu trả lời tốt hơn. –

+0

Tôi đã thêm một mục vào JIRA của MongoDB để xử lý thời gian địa phương, cũng đề cập đến mục nhập SO này (cần đăng ký): https://jira.mongodb.org/browse/DOCS-4086 – akauppi

+0

Xem http: //stackoverflow.com/a/38934986/194717 – Tony

Trả lời

2

Phiên bản mới của C lái xe # =>

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); 
    } 
} 
21

Đây là cách tôi buộc MongoDB lưu trữ giá trị thô và bỏ qua thuộc tính DateTimeKind trong đối tượng DateTime.

Điều này có thể không áp dụng cho logic nghiệp vụ của bạn, nhưng có ý nghĩa đối với chúng tôi vì lý do cụ thể của chúng tôi.

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); 
    } 
} 
+3

Dường như không tìm thấy MongoDB.Bson.Serialization.IBsonSerializationOptions trong 2.0.1 – Vaibhav

+1

Cách tiếp cận tuyệt vời. Ngay cả khi trình điều khiển C# sẽ tôn trọng [BsonDateTimeOptions (Kind = DateTimeKind.Utc)], giải pháp này sẽ tốt hơn trong hầu hết các trường hợp sử dụng phát triển vì nó sẽ áp dụng toàn cầu và tự động cho tất cả các thuộc tính DateTime, thay vì phải chỉ định từng thuộc tính và sau đó lỗi khi bạn chắc chắn quên một. –

0

Trong phiên bản driver .net 2.4, sử dụng này: giá trị datetime

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

BsonSerializer.RegisterSerializer(DateTimeSerializer.LocalInstance); 

Bằng cách này sẽ được lưu trữ với loại = utc trong db, nhưng deserialized trong loại địa phương.

Các vấn đề liên quan