JSON到.Net Epoch日期转换

时间:2017-02-01 13:20:25

标签: c# json asp.net-web-api

我有一个简单的WebAPI项目。我以Epoch格式传递JSON日期 “pickupBefore”: “/日期(1485360480-0800)/”。当.Net捕获它时,DateTime显示1970年。 假设是2017年1月25日。 我该怎么做才能实时获得它?

在我的.Net应用程序中,我将日期记为DateTime。在场景后面,DateTime结构充满了1970年的日期。我正在寻找那个结构中的东西,它将帮助我将它转换为实时DateTime。

在询问问题之前,我确实看过并试过了How do you convert epoch time in C#?,但这对解决我的问题没有帮助。 谢谢

1 个答案:

答案 0 :(得分:2)

基本问题是您的日期字符串位于 Unix纪录时间 中,但Microsoft的JSON日期格式位于 Unix纪元时间毫秒 ,如the documentation中所述。 Json.NET自动识别Microsoft格式的日期字符串,这样做可以将偏移量解释为ms而不是秒,这解释了为什么 DateTime显示1970年,因为1970年是Unix纪元的开始年份

您应该修复您的JSON,以便日期格式与Microsoft的格式完全一致,即"/Date(1485360480000-0800)/"。更好的是,您可以切换到ISO 8601 format,这是目前日期和时间的首选JSON格式。

如果由于某种原因您无法更正JSON格式,则需要禁用Json.NET的自动DateTime识别和解析,并创建自己的custom JsonConverter继承自{{3} }}

要禁用Json.NET的自动日期识别功能,请在DateTimeConverterBase中设置DateParseHandling = DateParseHandling.None。但是,如果您无法修改整个序列化设置,则只能通过将转换器从JsonSerializerSettings应用到其中来禁用包含类型的日期识别,例如:

[JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)] // Disable Json.NET's built-in date time parsing function.
public class RootObject
{
    public DateTime pickupBefore { get; set; }
}

接下来,您需要编写自定义JsonConverter。一种选择是复制Newtonsoft的Question 40632820DateTimeUtils.TryParseDateTime()的所有逻辑,在重写DateTimeUtils.TryParseDateTimeOffset()DateTimeUtils.TryParseDateTimeMicrosoft()的过程中以秒为单位解析纪元数而不是毫秒。我开始这样做,但意识到涉及到相当多的代码 - 超过了适合stackoverflow的答案。作为替代方案,快速而肮脏的黑客将在JSON中插入额外的000子字符串,以便从秒转换为毫秒,如下所示:

public class MicrosoftSecondsDateTimeConverter : DateTimeConverterBase
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var token = JToken.Load(reader);
        if (token.Type == JTokenType.String)
        {
            var s = ((string)token).Trim();
            if (s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal))
            {
                // MS datetime format is in milliseconds as is shown here:
                // https://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_sidebarb
                // But our times are offsets in seconds.
                // Convert.
                var sb = new StringBuilder("\"\\/Date(");
                var insert = "000"; // Seconds to MS
                for (int i = 6; i < s.Length - 2; i++)
                {
                    if (s[i] == '-' || s[i] == '+') // Time zone marker
                    {
                        sb.Append(insert);
                        insert = string.Empty;
                    }
                    sb.Append(s[i]);
                }
                sb.Append(insert);
                sb.Append(")\\/\"");
                s = sb.ToString();
                var dt = new JsonSerializer().Deserialize(new StringReader(s), objectType);
                return dt;
            }
        }

        // Not a Microsoft date.
        return new JsonSerializer().Deserialize(token.CreateReader(), objectType);
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

它并不漂亮,但确实完成了工作。然后将转换器应用于您的类型,如下所示:

[JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)] // Disable Json.NET's built-in date time parsing function.
public class RootObject
{
    [JsonConverter(typeof(MicrosoftSecondsDateTimeConverter))]
    public DateTime pickupBefore { get; set; }
}

或者将其添加到DateTimeUtils.TryParseDateTimeOffsetMicrosoft()以更改整个数据模型的DateTime字符串的反序列化。

示例JsonSerializerSettings.Converters