You 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();
This 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. 🙂