C# 如何将 unix 时间戳 (μs) 从 JSON 反序列化为 DateTime?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19971494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 16:16:23  来源:igfitidea点击:

How to deserialize a unix timestamp (μs) to a DateTime from JSON?

c#json.net

提问by mpen

JSON

JSON

{
   "title":"Mozilla Firefox",
   "id":24,
   "parent":2,
   "dateAdded":1356753810000000,
   "lastModified":1356753810000000,
   "type":"text/x-moz-place-container",
   "children":[]
}

C#

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);
}

I get an exception when I try running this,

当我尝试运行它时出现异常,

Additional information: Error reading date. Unexpected token: Integer. Path 'dateAdded'

附加信息:错误读取日期。意外标记:整数。路径“添加日期”

I thought by using the JavaScriptDateTimeConverter, JSON.NET could figure out how to deserialize those unix timestamps (msμs since epoch). What's the easiest way to do this?

我认为通过使用JavaScriptDateTimeConverterJSON.NET 可以弄清楚如何反序列化这些 un​​ix 时间戳(多发性硬化症自纪元以来的 μs)。什么是最简单的方法来做到这一点?

Having trouble finding documentation on the converters... it probably wouldn't be too hard to write one myself if necessary.

很难找到有关转换器的文档……如果有必要,自己编写一份可能不会太难。

Edit:Those are actually microseconds, not milliseconds.

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

采纳答案by mpen

I cleaned up Cris's solutiona tad and implemented WriteJson:

我稍微清理了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);
    }
}

回答by Cris

You can create a custom DateTime converter

您可以创建自定义日期时间转换器

  var bookmarks = JsonConvert.DeserializeObject<Bookmark>(json,
                                                      new MyDateTimeConverter());


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();
    }
}

another approach is to double annotate the class member,

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

[JsonProperty(PropertyName="dateAdded")] 
[JsonConverter(typeof(JavaScriptDateTimeConverter))]
public DateTime dateAdded;

回答by Noctis

Hmmm ...the tricky bit is that DateTime constructor doesn't accept a timestamp as an argument.

嗯……棘手的一点是 DateTime 构造函数不接受时间戳作为参数。

Here's a solution from this article: How to convert a Unix timestamp to DateTime and vice versa?

这是本文的解决方案:如何将 Unix 时间戳转换为 DateTime,反之亦然?

public static DateTime UnixTimeStampToDateTime( double unixTimeStamp )
{
    // Unix timestamp is seconds past epoch
    System.DateTime dtDateTime = new DateTime(1970,1,1,0,0,0,0);
    dtDateTime = dtDateTime.AddSeconds( unixTimeStamp ).ToLocalTime();
    return dtDateTime;
}

You'll have to call this, probably best by using default constructor in your class, or having another property that will return this in it's getmethod.

你必须调用它,最好是在你的类中使用默认构造函数,或者有另一个属性可以在它的get方法中返回 this 。

回答by Aoki Metal

There's a built-in way to convert from unix timestamp to DateTime without having to write your own class:

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

[JsonConverter(typeof(UnixDateTimeConverter))]
public DateTime lastModified;

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

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

The annotation in Cris' answeris not correct, as JavaScriptDateTimeConverteris for Date(52231943)format rather than the Unix timestamp from the OP.

Cris 的答案中的注释不正确,JavaScriptDateTimeConverter对于Date(52231943)格式而不是来自 OP 的 Unix 时间戳也是如此。

I realize this question is a few years old now so it's highly likely this class has been added since this question has been asked, but this may help anyone who comes across the same issue.

我意识到这个问题已经有几年了,所以很可能自从提出这个问题以来已经添加了这个类,但这可能会帮助遇到相同问题的任何人。

回答by redar ismail

That is how I did it and it worked

我就是这样做的,而且效果很好

In my ViewModel I have a Public property of Type DateTime

在我的 ViewModel 中,我有一个 DateTime 类型的公共属性

Public DateTime TimeToBeShown {get; set;}

In My Model, I have the public property of type Long which gets the date from API as a JSON Format.

在我的模型中,我有 Long 类型的公共属性,它从 API 获取日期作为 JSON 格式。

Public long DateThatIsComingAsJsonFormat {get; set;}
     var dateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
     TimeToBeShown=dateTime.AddSeconds(somethingfromloop.CreatedTime).ToLocalTime();
Bind to TimeToBeShown in Xaml