Question41980863 json-to-net-epoch-date-conversion

CSharp · Console

/Program.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Collections.ObjectModel;
using System.Reflection;
using System.ComponentModel;
using System.Globalization;
using System.Web.Routing;
using System.Net.Mail;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Net;
using System.Numerics;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;

// https://stackoverflow.com/questions/41980863/json-to-net-epoch-date-conversion


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

    public class DateParseHandlingConverter : JsonConverter
    {
        // Taken from https://stackoverflow.com/questions/40632820/how-to-prevent-a-single-object-property-from-being-converted-to-a-datetime-when
        readonly DateParseHandling dateParseHandling;

        public DateParseHandlingConverter(DateParseHandling dateParseHandling)
        {
            this.dateParseHandling = dateParseHandling;
        }

        public override bool CanConvert(Type objectType)
        {
            throw new NotImplementedException();
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
                return null;
            var old = reader.DateParseHandling;
            try
            {
                reader.DateParseHandling = dateParseHandling;
                existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
                serializer.Populate(reader, existingValue);
                return existingValue;
            }
            finally
            {
                reader.DateParseHandling = old;
            }
        }

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


    public class TestClass
    {
        public static void Test()
        {
            Test(@"{""pickupBefore"":""/Date(1485360480-0800)/""}");
            Console.WriteLine("");
            // Ensure ISO dates still work.
            Test(@"{""pickupBefore"":""2017-01-25T11:08:00-05:00""}");
        }

        private static void Test(string json)
        {
            Console.WriteLine("Testing JSON: " + json);

            var root = JsonConvert.DeserializeObject<RootObject>(json);

            Assert.IsTrue(root.pickupBefore.Year == 2017);
            Console.WriteLine("root.pickupBefore.Year == 2017");
            Console.WriteLine("Reserialized JSON: ");

            Console.WriteLine(JsonConvert.SerializeObject(root));
            Console.WriteLine(JsonConvert.SerializeObject(root, new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat }));
        }
	}
					
	public class Program
	{
		public static void Main()
		{
            Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
            Console.WriteLine("");

			TestClass.Test();
		}
	}

    public class AssertionFailedException : System.Exception
    {
        public AssertionFailedException() : base() { }

        public AssertionFailedException(string s) : base(s) { }
    }

    public static class Assert
    {
        public static void IsTrue(bool value)
        {
            if (value == false)
                throw new AssertionFailedException("failed");
        }
    }
;