Sending DateTime Instances From a .NET Server to a JavaScript Client and vice-versa

by Oliver 20. September 2014 21:47

At teamaton we're currently developing our own Time Tracking tool that we'll be using instead of KeepTempo as soon as it's good enough. We even plan on making it accessible to the public later but that's a different story. We chose Angular.js to develop the frontend and now want to synchronize our time tracking records with our ASP.NET WebAPI backend. One property of such a record is the date and time it was created at, createdUtc. Let's look at how we can send those date-time values to the server and back again. Some Background on Date and DateTime JavaScript Date instances are seeded at 01/01/1970 00:00:00 and can be instantiated by passing to the Date() constructor the number of milliseconds that have passed since that moment in time. will directly output this number, at the moment of writing these words it returned the value 1 411 240 284 042. This value is what all other representations of a given Date instance will be based on. In .NET we have the DateTime type and its seed value is 01/01/0001 00:00:00. Internally, DateTime instances count time in Ticks, where one tick equals 100 nanoseconds, i.e. 0.000 000 1 seconds, thus delivering a theoretical precision of 10000 times that of the JavaScript equivalent. When writing these words, the current number of Ticks of DateTime.Now was 635 468 449 058 588 764 (I use LINQPad to execute C# code snippets). How to Convert JavaScript Date to .NET DateTime So how do we convert those values into each other? If we decide to send the number of milliseconds in a given JavaScript Date instance to our .NET server we can reconstruct an equivalent DateTime instance by seeding it with 01/01/1970 and just adding the milliseconds we got from the client to it: Record.CreatedUtc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(milliseconds); Going the other way, we actually need to get hold of a TimeSpan instance which has the property TotalMilliseconds that gives us what we want. We'll do that by substracting a DateTime instance representing the 01/01/1970 from the DateTime instance we want to send to the client: (Record.CreatedUtc - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds The code looks a bit ugly because we take care to work with UTC dates so that our code will run the same for clients and servers around the world. It's a very good idea to work with UTC dates internally and only convert them to local dates when you want to display them somewhere. … or Just Use Date Strings There's another way to transfer date objects between JavaScript and your server: using a standardized string representation that both sides will be able to generate and parse. In JavaScript you would use Date.toISOString() and in .NET DateTime.ToString("O") (see the MSDN for the O format string). Happy coding!

JSON Import In .NET

by Anton 22. July 2011 13:37

Bantam Is Quitting Services We as teamaton were using bantam for all of our todos. At the beginning of this year bantam was bought by ConstantContact, and they announced that bantam will cease services as of July 1. Since we are developing our own todo management tool (see our blog), we decided to push the development and use it instead of bantam. Of course we wanted to take all of our todos with us. We used bantams export feature which gave us a JSON-file with all our tasks (closed and open ones). So I took on the task to write an JSON import feature into our tool. Json.NET After a bit of researching, I found that the library Json.NET would suit our import needs perfectly. Applying the deserialization was pretty straightforward – the documentation helped a lot. Here is the code from the Import controller: [HttpPost] public ActionResult Import(HttpPostedFileBase file) { var todos = new List<Todo>(); if (file != null && file.ContentLength > 0) { var streamReader = new StreamReader(file.InputStream); string text = streamReader.ReadToEnd(); streamReader.Close(); var bantamTodos = JsonConvert.DeserializeObject<IList<BantamTodo>>(text) as List<BantamTodo>; todos = bantamTodos.Select(bantamTodo => bantamTodo.ConvertToTodo()).ToList(); _todoRepository.SaveImport(todos); } return RedirectToAction("List"); } It just opens the file, extracts the content as a string, deserializes the string into a list of bantam todos, and then converts these bantam todos into our “normal” todos. Indirection Via BantamTodo-Class As you can see, I did not convert the JSON directly into our Todo-class. You can use attributes and the converter class to deserialize JSON into a class of your liking. There are two reasons, why I did not choose to do so: I did not want to load the Todo-class with attributes and converters, and I thought it would be easier to introduce a middle class (BantamTodo), which poses as a container and converter. I used a nice tool, to take a good look into the original JSON-file: JSON Viewer. With the information about the structure of the JSON file I started implementing via the TDD pattern. Here is my test class, which tests the deserialization of the the bantam todos and the conversion from the class BantamTodo to Todo: [Test] public void Should_Import_BantamToDo_FromJson() { var jsonToDo = ArrangeTaskAsJson(); var bantamToDo = JsonConvert.DeserializeObject<BantamTodo>(jsonToDo); bantamToDo.Categoy.Should().Be.EqualTo("Organisation"); bantamToDo.Complete.Should().Be.EqualTo(true); bantamToDo.Created_At.Should().Be.EqualTo(new DateTime(2011, 6, 30, 0, 41, 57)); bantamToDo.Due.Should().Be.EqualTo(new DateTime(2011, 7, 1)); bantamToDo.Author.Name.Should().Be.EqualTo("Anton"); bantamToDo.Assigned_To.Name.Should().Be.EqualTo("Oliver"); bantamToDo.Related_To[0].Name.Should().Be.EqualTo("ToDo-Management Tool"); bantamToDo.Name.Should().Be.EqualTo("Entwicklung nach Gebieten Personen zuordnen - Verantwortliche, Blogs, etc."); bantamToDo.Description.Should().Be.EqualTo("some good description"); bantamToDo.Flagged.Should().Be.EqualTo(true); } [Test] public void Should_Convert_BantamToDo_ToTodo() { var jsonToDo = ArrangeTaskAsJson(); var bantamToDo = JsonConvert.DeserializeObject<BantamTodo>(jsonToDo); var todo = bantamToDo.ConvertToTodo(); todo.Status.Should().Be.EqualTo(bantamToDo.Complete ? Status.Closed : Status.Open); todo.Description.Should().Contain(bantamToDo.Name); todo.Description.Should().Contain(bantamToDo.Description); todo.Tags.Select(t => t.Name).Should().Contain(bantamToDo.Categoy); foreach (var bantamProject in bantamToDo.Related_To) todo.Tags.Select(t => t.Name).Should().Contain(bantamProject.Name); todo.DateCreated.Should().Be.EqualTo(bantamToDo.Created_At); todo.DateCompleted.Value.Date.Should().Be.EqualTo(bantamToDo.Due); todo.DateDue.Should().Be.EqualTo(bantamToDo.Due); todo.Creator.Name.Should().Be.EqualTo(bantamToDo.Author.Name); todo.Assignee.Name.Should().Be.EqualTo(bantamToDo.Assigned_To.Name); todo.Priority.Value.Should().Be.EqualTo(bantamToDo.Flagged ? 2 : 0); } The implementation was pretty straightforward. Since it was my first time working with MVC, and also my first time working with JSON, it took me some time. All in all – research, export and meetings included – it took me about 12 hours. If you have any suggestions as to improvement I would appreciate them. If you are trying to import JSON into .NET yourself, I hope that this article helps.

About Oliver code blog logo I build web applications using ASP.NET and have a passion for jQuery. Enjoy MVC 4 and Orchard CMS, and I do TDD whenever I can. I like clean code. Love to spend time with my wife and our daughter. My profile on Stack Exchange, a network of free, community-driven Q&A sites

About Anton code blog logo I'm a software developer at teamaton. I code in C# and work with MVC, Orchard, SpecFlow, Coypu and NHibernate. I enjoy beach volleyball, board games and Coke.