0

I'm developing a Web API using the ASP.NET Core 2 and I have a Model class as following.

public class Model
{
   int id { get; set; }
   DateTime date { get; set; }
}

I am using JSON in the Request Body. Request Json is like

{
  "id" : 1,
  "date" : 1525261719 
}

Binding this JSON data to the Model class like this in Controller

[HttpPost]
public async Task<IActionResult> PostEvent([FromBody] Model model)
{ 
    // Some code here
}

I was not able to parse Unix timestamp into the DateTime type. I saw some examples like JSON Converter, IModelBinder nothing helps. As I was new to .NET world I don't know how to proceed for this issue.

Any help is much appreciated.

Mdumanoj
  • 517
  • 3
  • 9
  • 27
  • See [How to deserialize a unix timestamp to a DateTime](https://stackoverflow.com/questions/19971494/how-to-deserialize-a-unix-timestamp-%CE%BCs-to-a-datetime). – Mark G May 02 '18 at 17:02
  • I tried this. But my json converter class is not getting called. I added data annotation for property and added converter in startup file. – Mdumanoj May 02 '18 at 17:45
  • You should probably tag json.net as well then. The converter class not getting called is another question - maybe edit your question and include the code you used. – Mark G May 02 '18 at 18:01

2 Answers2

2

I had the same issue. I wrote this JsonConverter. Keep in mind that this is tailor-made for my specific situation.

public class UnixEpochTimeToDateTimeConverter: JsonConverter
{
    public override bool CanWrite => false;

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
        JsonSerializer serializer)
    {

        if (reader.TokenType == JsonToken.Null) return null;
        if (reader.TokenType != JsonToken.Integer) return null;
        if (!reader.Path.Contains("time")) return null;

        return long.TryParse(reader.Value.ToString(), out var epoch)
            ? DateTimeOffset.FromUnixTimeMilliseconds(epoch).DateTime
            : DateTime.Now;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }
}
Pepito Fernandez
  • 2,352
  • 6
  • 32
  • 47
  • 2
    Nice and useful. While it may be obvious to some, to make this answer more useful I'd like to add to this answer that this code extends the JsonConverter class in NewtonSoft.Json (NOT System.Text.Json.Serialization), so make sure you add the NewtonSoft.Json Nuget Package to your solution. Also, to use this serializer, you should decorate the property you want to serialize like `[JsonConverter(typeof(UnixEpochTimeToDateTimeConverter))]` and it will automatically run when calling `JsonConvert.DeserializeObject(json)` – Céryl Wiltink Sep 13 '21 at 09:15
1

I found solution for this. I used ITypeConverter

// Converts timestamp to DateTime
public class DateTimeConverter : ITypeConverter<long?, DateTime?>
{
    private readonly DateTime _epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    public DateTime? Convert(long? source, DateTime? destination, ResolutionContext context)
    {
        if (!source.HasValue) return null;
        return _epoch.AddSeconds(source.Value);
    }
}

// Converts DateTime to Timestamp
public class TimeStampConverter : ITypeConverter<DateTime?, long?>
{
    private readonly DateTime _epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    public long? Convert(DateTime? source, long? destination, ResolutionContext context)
    {
        if (source == null) return null;
        var result = (long)(source - _epoch).Value.TotalSeconds;
        return result;
    }
}

And I created a Map like this in startup.cs

AutoMapper.Mapper.Initialize(x =>
            {
                x.CreateMap<long?, DateTime?>().ConvertUsing<DateTimeConverter>();
                x.CreateMap<DateTime?, long?>().ConvertUsing<TimeStampConverter>();
            });

I used this couple of classes in my project and it is working fine. This may help anyone who is trying to achieve the same thing.

Mdumanoj
  • 517
  • 3
  • 9
  • 27