2013-10-30 14 views
16

Tôi có một POCO như thế này:ServiceStack - Có cách nào để buộc tất cả các ngày được tuần tự hóa sử dụng một DateTimeKind cụ thể không?

public class BlogEntry 
{ 
    public string Title { get; set; } 
    public DateTime Date { get; set; } 
} 

Phần lớn thời gian nó đang được ngậm nước từ Entity Framework, nhưng nó có thể và sẽ được sử dụng bên ngoài của Entity Framework.

DateTimeKind cho ngày từ EF không xác định, từ những gì tôi đọc là bình thường.

Khi tôi cache POCO này trong Redis (sử dụng ServiceStack Redis client), nó trở lại với DateTimeKind của Local.

Vì vậy, có một jitter với các đối tượng trả về. Pass đầu tiên (uncached) có ISO-8061 không có offset (DateTimeKind.Unspecified). Pass thứ hai (cache) là ISO-8061 với một offset (từ Redis với DateTimeKind.Local).

Bất kỳ cách nào để buộc trình serializer ServiceStack JSON luôn diễn giải ngày tháng như một DateTimeKind đã cho? (Tôi biết có một thuộc tính "JsConfig.AppendUtcOffset", nhưng cho dù đó là đúng hay sai, các giá trị không bao giờ thay đổi đối với tôi?)

Hoặc một nơi nào đó trong quá trình deserialization từ RedisClient đã nhập của tôi để tạo địa chỉ DateTimeKind?

Tôi có thể thay đổi POCO của mình theo cách thủ công để thực thi DateTimeKind - và điều đó có hiệu quả - nhưng tôi đã hy vọng sẽ có ít lỗi hơn.

Trả lời

16

Nếu bạn cần một cái gì đó có thể cấu hình nhiều hơn câu trả lời @ mythz, bạn có thể buộc các serialization hoặc deserialization của DateTimes để có một số DateTimeKind bằng cách ghi đè các DateTime và DateTime tùy chọn? serialization và/hoặc phương pháp deserialization.

Force tất cả DateTimes serialized để được hiểu là UTC

JsConfig<DateTime>.SerializeFn = time => new DateTime(time.Ticks, DateTimeKind.Local).ToString(); 

Sau đó bạn có thể thực hiện việc này một bước xa hơn và lỗi trên deserialization nếu DateTime không phải là trong một định dạng cụ thể. Tôi bắt đầu sử dụng điều này khi tôi muốn buộc khách hàng chỉ định múi giờ trong tất cả các yêu cầu, nhưng không nhất thiết yêu cầu rằng nó luôn là Utc.

JsConfig<DateTime>.DeSerializeFn = time => 
{ 
    if (!IsInCorrectDateFormat(time)) 
    throw new System.Runtime.Serialization.SerializationException(BadDateTime); 

    return ServiceStack.Text.Common.DateTimeSerializer.ParseDateTime(time); 
}; 
+0

Bất kỳ ý tưởng nào về lý do tại sao đại biểu 'JsConfig .SerializeFn' không được gọi trên thiết lập của tôi? – ygormutti

+1

Bạn có đang gọi tuần tự hóa bằng DateTime không có giá trị không? –

+0

Đối với những người như tôi, những người không tìm thấy giải pháp ygormutti ngay lập tức ... tất cả những gì bạn cần làm là: 'JsConfig .SerializeFn' –

6

Giá trị bù trừ DateTimeKind không được lưu trữ với ngày nên theo mặc định ServiceStack serializers làm cho giả định ngày tháng là địa phương, được sắp xếp theo dạng UTC và deserialized trở lại làm Local.

Bạn có thể nhận DateTimeKind.Unspecified được giả định là UTC với:

JsConfig.AssumeUtc = true; 
+0

Cắm đề xuất của bạn và nó đã rất gần với làm việc cho tôi. Ví dụ cuộc gọi đầu tiên: "2013-07-19T12: 49: 52.5570000", ví dụ cuộc gọi thứ hai: "2013-07-19T19: 49: 52.5570000Z". Về mặt kỹ thuật, cả hai đều có thể phân tích cú pháp bằng bất kỳ ngôn ngữ nào và tôi giả định là giống nhau, nhưng tôi có một mong muốn mạnh mẽ để làm cho chúng khớp hoàn hảo. – ryan1234

+0

Nếu tôi muốn chúng được giả định là 'DateTimeKind.Local' thì sao?Bộ nối tiếp DateTime trả về giờ địa phương như thể nó là UTC. 'JsConfig.AssumeUtc = false;' không hoạt động. – ygormutti

+1

Điều này làm việc cho JSON - có tương đương với JSV không? – Cocowalla

5

Tinh chỉnh giải pháp bpruitt-goddard. Tất cả tín dụng đều đến với anh ta.

JsConfig<DateTime>.SerializeFn = time => new DateTime(time.Ticks, DateTimeKind.Local).ToString("o"); 
     JsConfig<DateTime?>.SerializeFn = 
      time => time != null ? new DateTime(time.Value.Ticks, DateTimeKind.Local).ToString("o") : null; 
     JsConfig.DateHandler = DateHandler.ISO8601; 

Vì vậy, bất kỳ ngày đi ra ngoài từ dịch vụ ngăn xếp sẽ bị buộc vào một định dạng ngày ISO8601 và bất kỳ ngày sắp tới trong sẽ được chuyển đổi tự động để C# ngày từ chuỗi ISO8601.

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