2013-10-30 10 views
16

Ich habe eine POCO wie folgt aus:ServiceStack - Gibt es eine Möglichkeit, alle serialisierten Daten zu einem bestimmten DateTimeKind zu zwingen?

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

Die meiste Zeit von Entity Framework hydratisiert es ist, aber es kann und wird außerhalb des Entity Framework verwendet werden.

Das DateTimeKind für das Datum aus EF ist nicht angegeben, was von dem, was ich lese, ist normal.

Wenn ich dieses POCO in Redis (mit dem ServiceStack Redis Client) zwischenspeichern, kommt es mit einem DateTimeKind von Local zurück.

Es gibt also einen Jitter mit den zurückgegebenen Objekten. Der erste Durchlauf (nicht zwischengespeichert) hat ISO-8061 ohne Offset (DateTimeKind.Unspecified). Der zweite Durchlauf (zwischengespeichert) ist ISO-8061 mit einem Offset (von Redis mit DateTimeKind.Local).

Gibt es eine Möglichkeit, den ServiceStack JSON-Serializer dazu zu zwingen, Daten immer als gegebenes DateTimeKind zu interpretieren? (Ich weiß, es gibt eine "JsConfig.AppendUtcOffset" -Eigenschaft, aber ob es wahr oder falsch ist, ändern sich die Werte für mich nie?)

Oder irgendwo in der Deserialisierung von meinem RedisClient eingegeben, um das DateTimeKind lokal zu machen?

Ich kann meine POCOs manuell ändern, um das DateTimeKind zu erzwingen - und das funktioniert - aber ich hoffte auf etwas weniger fehleranfällig.

Antwort

16

Wenn Sie etwas mehr konfigurierbar benötigen als @ mythz Antwort, können Sie die Serialisierung oder Deserialisierung von Datetime erzwingen, indem eine bestimmte DateTimeKind haben die zwingende DateTime und optional DateTime? Serialisierungs- und/oder Deserialisierungsmethoden.

Force Alle serialisierten Datetime als UTC

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

Anschließend können Sie diesen weiter und Fehler einen verbesserten Schritt auf Deserialisierung interpretiert werden, wenn die Datetime nicht in einem bestimmten Format sind. Ich begann damit, wenn ich Kunden zwingen wollte, die Zeitzone in allen Anfragen zu spezifizieren, aber nicht unbedingt, dass es immer Utc ist.

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

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

Irgendwelche Ideen, warum der 'JsConfig .SerializeFn' Delegat nicht auf meinem Setup aufgerufen wird? – ygormutti

+1

Rufen Sie Serialisierung mit einer Nullable DateTime auf? –

+0

Für diejenigen wie mich, die die ygormutti Lösung nicht sofort gefunden haben ... alles, was Sie nur tun müssen, ist: 'JsConfig .SerializeFn' –

6

Der DateTimeKind Offset wird nicht mit Datum gespeichert, daher nehmen ServiceStack-Serializer standardmäßig die Annahme vor, dass das Datum lokal ist, das als UTC serialisiert und als Lokal deserialisiert wird.

Sie können DateTimeKind.Unspecified erhalten werden als UTC angenommen mit:

JsConfig.AssumeUtc = true; 
+0

Plugged in Ihrem Vorschlag und es war sehr nah an mir zu arbeiten. Erstes Aufrufbeispiel: "2013-07-19T12: 49: 52.5570000", zweites Aufrufbeispiel: "2013-07-19T19: 49: 52.5570000Z". Technisch sollten beide von jeder Sprache analysiert werden können und ich gehe davon aus, dass sie gleich sind, aber ich habe den starken Wunsch, sie perfekt aufeinander abzustimmen. – ryan1234

+0

Was, wenn ich möchte, dass sie als 'DateTimeKind.Local' angenommen werden?Der DateTime-Serializer gibt die lokale Zeit zurück, als wäre es UTC. 'JsConfig.AssumeUtc = false;' hat nicht funktioniert. – ygormutti

+1

Dies funktioniert für JSON - gibt es ein Äquivalent für JSV? – Cocowalla

5

Ein Tweak zu Bpruitt-Goddard-Lösung. Der ganze Kredit geht an ihn.

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; 

So irgendein Datum aus dem Dienst Stapel Ausgehen wird in ein ISO8601 Datumsformat und irgendein Datum automatisch auf C# Datum aus dem ISO8601 String gezwungen wird umgewandelt kommt in wird.

Verwandte Themen