ServiceStack - Is there a way to force all serialized Dates to use a specific DateTimeKind?

ryan1234 picture ryan1234 · Oct 30, 2013 · Viewed 8.8k times · Source

I have a POCO like this:

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

Most of the time it's being hydrated from Entity Framework, but it can and will be used outside of Entity Framework.

The DateTimeKind for the Date from EF is Unspecified, which from what I read is normal.

When I cache this POCO in Redis (using the ServiceStack Redis client), it comes back with a DateTimeKind of Local.

So there is a jitter with the returned objects. The first pass (uncached) has ISO-8601 with no offset (DateTimeKind.Unspecified). The second pass (cached) is ISO-8601 with an offset (from Redis with DateTimeKind.Local).

Any way to force the ServiceStack JSON serializer to always interpret dates as a given DateTimeKind? (I know there is a "JsConfig.AppendUtcOffset" property, but whether it's true or false, the values never change for me?)

Or somewhere in the deserialization process from my typed RedisClient to make the DateTimeKind local?

I can manually change my POCO's to enforce the DateTimeKind - and that works - but I was hoping for something less error prone.

Answer

bpruitt-goddard picture bpruitt-goddard · Oct 31, 2013

If you need something more configurable than @mythz's answer, you can force the serialization or deserialization of DateTimes to have a certain DateTimeKind by overriding the DateTime and optionally DateTime? serialization and/or deserialization methods.

Force all serialized DateTimes to be interpreted as UTC

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

You can then take this one step farther and error on deserialization if the DateTime isn't in a specified format. I started using this when I wanted to force clients to specify the timezone in all requests, but not necessarily require that it always be Utc.

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

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