我有一个简单的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#?,但这对解决我的问题没有帮助。 谢谢
答案 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 40632820和DateTimeUtils.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
字符串的反序列化。