Fixing That Date/Time Globalization Issue

Right after I created a new blog post in this new version of my site, I immediately noticed that the time of post is incorrect and reads around 2PM instead of 10PM. I, then, knew that I have one of those date/time globalization issue again. I used to solve this issue by changing the database and web server timezones to be in sync with client's timezones since I have always been in control with the servers. But as I am hosting my website using Azure while my database in ClearDB, I totally don't have any control with their timezones. I am, then, compelled to fix this.

First up is to synchronize all the times for all of the server code. Normally, UTC times are being used in storing date/time data.

For databases, each SQL version should have their own UTC-related functions. In MySQL, you have UTC_DATE(), UTC_TIME(), and UTC_TIMESTAMP(). In MSSQL, there's the GETUTCDATE().

For web servers, if you have any date/time input taken from the user, convert them to UTC. In C#, make use of the ToUniversalTime() method as follows:

[HttpPost]
public ActionResult DoSomething(DateTime start)
{
DateTime startUTC = start.ToUniversalTime();
// More code here...
}

Now, for the client, the date must be converted back to the local times. We'll handle the conversion in our JavaScript code. As a pre-requisite, we'll convert the date/time in our server side code to milliseconds. If you take a look at the JavaScript documentation, the Date constructor that accepts milliseconds expects that this is the number of milliseconds since Jan 1, 1970. Let's create an extension method for the DateTime to do this conversion:

public static class DateTimeExtensions
{
private static readonly long StartDateTimeJSTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks;

public static long ToJSTicks(this DateTime value)
{
return (value.Ticks - StartDateTimeJSTicks) / 10000;
}
}

Next up, I've adopted a method of processing the date/time conversion on the JavaScript code from Jonas Gauffin which here wrote here. Just to save you the time, put all your date/time values on an attribute called data-date as in:

<li data-date="@item.DateCreated.ToJSTicks()"></li>

The element could be anything such as span, p, li, etc. Then on your JavaScript code, instantiate a Date using the value in the data-date attribute and call the toLocaleString(), toLocaleDateString() or toLocaleTimeString(), whichever is appropriate:

$("[data-date]").each(function () {
var localDate = new Date(parseInt($(this).attr("data-date")));
$(this).html(localDate.toLocaleString());
});

So, there you have it! No more date/time globalization issues.