如何从UNIX中将unix时间戳(μs)反序列化为DateTime?

mpe*_*pen 44 c# json.net

JSON

{
   "title":"Mozilla Firefox",
   "id":24,
   "parent":2,
   "dateAdded":1356753810000000,
   "lastModified":1356753810000000,
   "type":"text/x-moz-place-container",
   "children":[]
}
Run Code Online (Sandbox Code Playgroud)

C#

class Bookmark
{
    public string title;
    public string id;
    [JsonProperty(ItemConverterType = typeof(JavaScriptDateTimeConverter))]
    public DateTime dateAdded;
    [JsonProperty(ItemConverterType = typeof(JavaScriptDateTimeConverter))]
    public DateTime lastModified;
    public string type;
    public string root;
    public long parent;
    public List<Bookmark> children;
}

private static void Main(string[] args)
{
    var json = File.ReadAllText(@"T:/bookmarks-2013-11-13.json");
    var bookmarks = JsonConvert.DeserializeObject<Bookmark>(json);
}
Run Code Online (Sandbox Code Playgroud)

我尝试运行时遇到异常,

附加信息:阅读日期时出错.意外的令牌:整数.路径'dateAdded'

我想通过使用JavaScriptDateTimeConverter,JSON.NET可以弄清楚如何反序列化那些unix时间戳(女士从epoch开始的μs).最简单的方法是什么?

无法在转换器上查找文档......如果有必要,自己编写文档可能不会太难.

编辑:这些实际上是微秒,而不是毫秒.

mpe*_*pen 56

我清理了Cris的解决方案并实施了WriteJson:

class Bookmark
{
    public string title;
    public long id;
    [JsonConverter(typeof(MicrosecondEpochConverter))]
    public DateTime dateAdded;
    [JsonConverter(typeof(MicrosecondEpochConverter))]
    public DateTime lastModified;
    public string type;
    public string root;
    public long parent;
    public List<Bookmark> children;
    public string uri;

    public override string ToString()
    {
        return string.Format("{0} - {1}", title, uri);
    }
}

public class MicrosecondEpochConverter : DateTimeConverterBase
{
    private static readonly DateTime _epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(((DateTime)value - _epoch).TotalMilliseconds + "000");
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.Value == null) { return null; }
        return _epoch.AddMilliseconds((long)reader.Value / 1000d);
    }
}

internal class Program
{

    private static void Main(string[] args)
    {
        var jsonString = File.ReadAllText(@"T:/bookmarks-2013-11-13.json");
        var rootMark = JsonConvert.DeserializeObject<Bookmark>(jsonString);
        var ret = JsonConvert.SerializeObject(rootMark);
    }
}
Run Code Online (Sandbox Code Playgroud)


Cri*_*ris 38

您可以创建自定义DateTime转换器

  var bookmarks = JsonConvert.DeserializeObject<Bookmark>(json,
                                                      new MyDateTimeConverter());
Run Code Online (Sandbox Code Playgroud)
public class MyDateTimeConverter : Newtonsoft.Json.JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var t = long.Parse((string)reader.Value);
        return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(t);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是双重注释类成员,

[JsonProperty(PropertyName="dateAdded")] 
[JsonConverter(typeof(JavaScriptDateTimeConverter))]
public DateTime dateAdded;
Run Code Online (Sandbox Code Playgroud)

  • 双重注释不是必需的; `[JsonConverter]`是我要找的属性.谢谢!(但是`[JsonProperty]`也很好,因为现在我可以重命名我的属性) (2认同)

小智 24

有一种内置的方法可以将unix时间戳转换为DateTime,而无需编写自己的类:

[JsonConverter(typeof(UnixDateTimeConverter))]
public DateTime lastModified;
Run Code Online (Sandbox Code Playgroud)

https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Converters_UnixDateTimeConverter.htm

在注释克里斯的回答是不正确的,因为JavaScriptDateTimeConverterDate(52231943)格式,而不是从OP Unix时间戳.

我意识到这个问题现在已经有几年了,所以很有可能这个课程已被添加,因为这个问题已被提出,但这可能会帮助任何遇到同一问题的人.

  • 我的问题是关于自纪元以来的微秒,而不是通常的秒数。不要认为 `UnixDateTimeConverter` 可以解决这个问题,是吗? (6认同)

Bry*_*man 5

我想为 .Net 核心添加一个解决方案,并System.Text.Json基于接受的答案。 在撰写本文时已在 3.1 中验证。

public class UnixDateTimeConverter : JsonConverter<DateTime>
{
   public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
   {
       return DateTime.UnixEpoch.AddSeconds(reader.GetInt64());
   }

   public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
   {
       writer.WriteStringValue((value - DateTime.UnixEpoch).TotalMilliseconds + "000");
   }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以使用数据注释来应用它

[JsonConverter(typeof(UnixDateTimeConverter))]
public DateTime MyDateTime {get;set;}
Run Code Online (Sandbox Code Playgroud)