Lance Larsen - .NET Architect Madison Wisconsin

momentjs + UTC date/time = browser local time

imageYou should almost always store your date/times in your database as UTC – you may think it’s not important now, but as soon as your application needs to display times to users in different time zones ( to paraphrase Yoda ) …it will be, it will be… 

But do you need to know and store your user’s timezone to display it correctly? 

Nope, JavaScript and momentjs to the rescue…! :)

JavaScript has some not too often used built in features – the fist is getTimezoneOffset()
 

var minutesOffset = new Date().getTimezoneOffset();

This is pretty sweet – it returns the time difference between UTC time and local time, in minutes.  For example, if your time zone is CST+6, -360 will be returned.  You could get this, do some calculations on the current time and show what you calculated… 

But it get’s better – see toLocaleTimeString()
 

var localTime = new Date().toLocaleTimeString();

imageThis returns the time portion of a Date object as a string, using locale conventions – AND – if you pass in the date object as UTC, it also converts the time to the local time!  Awesome…

Using these core methods – and a few tricks – I’ve created a suite of JavaScript methods – and have them up on the very cool jsFiddle – so if you use the F12 tools and run the code – you’ll see the code in action!  All the code is up on http://jsfiddle.net/lancelarsen/EsEYm/ !

Note, UTC can be stored in ISO 8601 format – and while new browser’s JavaScript date parsing handles the 8601 format, some older browers’ JavaScript versions do not – so found a awesome time centric JavaScript library – momentjs – and that makes our date parsing consistent across all browsers.

Input dates can be as simple as ’8/24/2013 8:00:00 AM’ or in the ISO 8601 formats, such as, ’2013-08-24T08:00:00-00:00′ or ’2013-08-24T08:00:00Z’.

So the code is as follows – play with it…

var L2date = function () { };

// RegEx ISO 8601 Formatted Date, e.g. 2013-08-24T08:00:00-00:00
var regexMatchForIso8601Date = /[0-9]T[0-9]/;
var invalidDateMessage = 'Invalid Date';
var dateFormat = 'M/D/YYYY h:mm:ss A';
var date = new L2date();

L2date.prototype.convertUtcToLocalDisplay = function (value) {
    // Check that the date is not in ISO 8601 format, if not 
    //   then add postfix so can be converted to UTC
    if (!regexMatchForIso8601Date.test(value)) value = value + ' UTC';
    if (!moment(value).isValid()) return invalidDateMessage;
    return moment(value).format(dateFormat).toLocaleString();
};

L2date.prototype.convertUtcToLocalDateDisplay = function (value) {
    return date.convertUtcToLocal(value).toLocaleDateString();
};

L2date.prototype.convertUtcToLocalTimeDisplay = function (value) {
    return date.convertUtcToLocal(value).toLocaleTimeString();
};

L2date.prototype.convertUtcToLocal = function (value) {
    return new Date(date.convertUtcToLocalDisplay(value));
};

L2date.prototype.getOffsetHours = function() {
    return date.getOffsetMins() / 60;
};

L2date.prototype.getOffsetMins = function() {
    return -1 * new Date().getTimezoneOffset();
};

Another cool feature of having it up on jsFiddle – is that anyone can fork the code – add functionality and add value that we can all take advantage of more ideas.  Already have a couple additional methods utilizing and building “timeago” method – take a look – tons of great potential. :)

 
Comments

No comments yet.

Leave a Reply