diff --git a/core/server/api/settings.js b/core/server/api/settings.js
index 8ce7740361..9cf411e5d7 100644
--- a/core/server/api/settings.js
+++ b/core/server/api/settings.js
@@ -60,7 +60,8 @@ updateConfigCache = function () {
             postsPerPage: (settingsCache.postsPerPage && settingsCache.postsPerPage.value) || 5,
             permalinks: (settingsCache.permalinks && settingsCache.permalinks.value) || '/:slug/',
             twitter: (settingsCache.twitter && settingsCache.twitter.value) || '',
-            facebook: (settingsCache.facebook && settingsCache.facebook.value) || ''
+            facebook: (settingsCache.facebook && settingsCache.facebook.value) || '',
+            timezone: (settingsCache.activeTimezone && settingsCache.activeTimezone.value) || 'Europe/Dublin'
         },
         labs: labsValue
     });
diff --git a/core/server/config/url.js b/core/server/config/url.js
index ccc1b08580..73f7d97235 100644
--- a/core/server/config/url.js
+++ b/core/server/config/url.js
@@ -1,7 +1,7 @@
 // Contains all path information to be used throughout
 // the codebase.
 
-var moment            = require('moment'),
+var moment            = require('moment-timezone'),
     _                 = require('lodash'),
     ghostConfig = '',
     // @TODO: unify this with routes.apiBaseUrl
@@ -95,18 +95,20 @@ function createUrl(urlPath, absolute, secure) {
     return urlJoin(base, urlPath);
 }
 
-// ## urlPathForPost
-// Always sync
-// Creates the url path for a post, given a post and a permalink
-// Parameters:
-// - post - a json object representing a post
+/**
+ * creates the url path for a post based on blog timezone and permalink pattern
+ *
+ * @param {JSON} post
+ * @returns {string}
+ */
 function urlPathForPost(post) {
     var output = '',
         permalinks = ghostConfig.theme.permalinks,
+        publishedAtMoment = moment.tz(post.published_at, ghostConfig.theme.timezone),
         tags = {
-            year:   function () { return moment(post.published_at).format('YYYY'); },
-            month:  function () { return moment(post.published_at).format('MM'); },
-            day:    function () { return moment(post.published_at).format('DD'); },
+            year:   function () { return publishedAtMoment.format('YYYY'); },
+            month:  function () { return publishedAtMoment.format('MM'); },
+            day:    function () { return publishedAtMoment.format('DD'); },
             author: function () { return post.author.slug; },
             slug:   function () { return post.slug; },
             id:     function () { return post.id; }
diff --git a/core/server/controllers/frontend/index.js b/core/server/controllers/frontend/index.js
index 87f5cd42a5..ffffd9a8a4 100644
--- a/core/server/controllers/frontend/index.js
+++ b/core/server/controllers/frontend/index.js
@@ -66,11 +66,21 @@ frontendControllers = {
                 return next();
             }
 
-            // If we're ready to render the page but the last param is 'edit' then we'll send you to the edit page.
+            // CASE: we only support /:slug format for pages
+            if (post.page && post.url !== req.path) {
+                return next();
+            }
+
+            // CASE: last param is of url is /edit, redirect to admin
             if (lookup.isEditURL) {
                 return res.redirect(config.paths.subdir + '/ghost/editor/' + post.id + '/');
             }
 
+            // CASE: permalink is not valid anymore, we redirect him permanently to the correct one
+            if (post.url !== req.path) {
+                return res.redirect(301, post.url);
+            }
+
             setRequestIsSecure(req, post);
 
             filters.doFilter('prePostsRender', post, res.locals)
diff --git a/core/server/controllers/frontend/post-lookup.js b/core/server/controllers/frontend/post-lookup.js
index 788c4188ee..c9925fc161 100644
--- a/core/server/controllers/frontend/post-lookup.js
+++ b/core/server/controllers/frontend/post-lookup.js
@@ -16,28 +16,32 @@ function postLookup(postUrl) {
         postPermalink = config.theme.permalinks,
         pagePermalink = '/:slug/',
         isEditURL = false,
-        matchFunc,
+        matchFuncPost,
+        matchFuncPage,
+        postParams,
+        pageParams,
         params;
 
     // Convert saved permalink into a path-match function
-    matchFunc = routeMatch(getEditFormat(postPermalink));
-    params = matchFunc(postPath);
+    matchFuncPost = routeMatch(getEditFormat(postPermalink));
+    postParams = matchFuncPost(postPath);
 
     // Check if the path matches the permalink structure.
     // If there are no matches found, test to see if this is a page instead
-    if (params === false) {
-        matchFunc = routeMatch(getEditFormat(pagePermalink));
-        params = matchFunc(postPath);
+    if (postParams === false) {
+        matchFuncPage = routeMatch(getEditFormat(pagePermalink));
+        pageParams = matchFuncPage(postPath);
     }
 
     // If there are still no matches then return empty.
-    if (params === false) {
+    if (pageParams === false) {
         return Promise.resolve();
     }
 
+    params = postParams || pageParams;
+
     // If params contains edit, and it is equal to 'edit' this is an edit URL
     if (params.edit && params.edit.toLowerCase() === 'edit') {
-        postPath = postPath.replace(params.edit + '/', '');
         isEditURL = true;
     } else if (params.edit !== undefined) {
         // Unknown string in URL, return empty
@@ -53,9 +57,12 @@ function postLookup(postUrl) {
     return api.posts.read(params).then(function then(result) {
         var post = result.posts[0];
 
-        // If there is no post, or the post has no URL, or it isn't a match for our original lookup, return empty
-        // This also catches the case where we use the pagePermalink but the post is not a page
-        if (!post || !post.url || post.url !== postPath) {
+        if (!post) {
+            return Promise.resolve();
+        }
+
+        // CASE: we originally couldn't match the post based on date permalink and we tried to check if its a page
+        if (!post.page && !postParams) {
             return Promise.resolve();
         }
 
diff --git a/core/server/data/schema/default-settings.json b/core/server/data/schema/default-settings.json
index 7e7de56bae..832e11bd4d 100644
--- a/core/server/data/schema/default-settings.json
+++ b/core/server/data/schema/default-settings.json
@@ -40,6 +40,12 @@
                 "isLength": [1, 1000]
             }
         },
+        "activeTimezone": {
+            "defaultValue": "Europe/Dublin",
+            "validations": {
+                "isNull": false
+            }
+        },
         "forceI18n": {
             "defaultValue": "true",
             "validations": {
diff --git a/core/server/data/timezones.json b/core/server/data/timezones.json
index 76df1959ed..03c93a4129 100644
--- a/core/server/data/timezones.json
+++ b/core/server/data/timezones.json
@@ -1,7 +1,7 @@
 {
 	"timezones": [
 		{
-			"name": "Pacific/Samoa",
+			"name": "Pacific/Pago_Pago",
 			"label": "(GMT -11:00) Midway Island, Samoa",
 			"offset": -660
 		},
@@ -11,27 +11,27 @@
 			"offset": -600
 		},
 		{
-			"name": "US/Alaska",
+			"name": "America/Anchorage",
 			"label": "(GMT -9:00) Alaska",
 			"offset": -540
 		},
 		{
-			"name": "Mexico/BajaNorte",
+			"name": "America/Tijuana",
 			"label": "(GMT -8:00) Chihuahua, La Paz, Mazatlan",
 			"offset": -480
 		},
 		{
-			"name": "US/Pacific",
+			"name": "America/Los_Angeles",
 			"label": "(GMT -8:00) Pacific Time (US & Canada); Tijuana",
 			"offset": -480
 		},
 		{
-			"name": "US/Arizona",
+			"name": "America/Phoenix",
 			"label": "(GMT -7:00) Arizona",
 			"offset": -420
 		},
 		{
-			"name": "US/Mountain",
+			"name": "America/Denver",
 			"label": "(GMT -7:00) Mountain Time (US & Canada)",
 			"offset": -420
 		},
@@ -41,17 +41,17 @@
 			"offset": -360
 		},
 		{
-			"name": "US/Central",
+			"name": "America/Chicago",
 			"label": "(GMT -6:00) Central Time (US & Canada)",
 			"offset": -360
 		},
 		{
-			"name": "Mexico/General",
+			"name": "America/Mexico_City",
 			"label": "(GMT -6:00) Guadalajara, Mexico City, Monterrey",
 			"offset": -360
 		},
 		{
-			"name": "Canada/Saskatchewan",
+			"name": "America/Regina",
 			"label": "(GMT -6:00) Saskatchewan",
 			"offset": -360
 		},
@@ -61,12 +61,12 @@
 			"offset": -300
 		},
 		{
-			"name": "US/Eastern",
+			"name": "America/New_York",
 			"label": "(GMT -5:00) Eastern Time (US & Canada)",
 			"offset": -300
 		},
 		{
-			"name": "US/East-Indiana",
+			"name": "America/Fort_Wayne",
 			"label": "(GMT -5:00) Indiana (East)",
 			"offset": -300
 		},
@@ -76,17 +76,17 @@
 			"offset": -270
 		},
 		{
-			"name": "Canada/Atlantic",
+			"name": "America/Halifax",
 			"label": "(GMT -4:00) Atlantic Time (Canada); Brasilia, Greenland",
 			"offset": -240
 		},
 		{
-			"name": "Canada/Newfoundland",
+			"name": "America/St_Johns",
 			"label": "(GMT -3:30) Newfoundland",
 			"offset": -210
 		},
 		{
-			"name": "America/Buenos_Aires",
+			"name": "America/Argentina/Buenos_Aires",
 			"label": "(GMT -3:00) Buenos Aires, Georgetown",
 			"offset": -180
 		},
@@ -141,7 +141,7 @@
 			"offset": 60
 		},
 		{
-			"name": "Africa/Bangui",
+			"name": "Africa/Lagos",
 			"label": "(GMT +1:00) West Central Africa",
 			"offset": 60
 		},
@@ -156,7 +156,7 @@
 			"offset": 120
 		},
 		{
-			"name": "Africa/Harare",
+			"name": "Africa/Maputo",
 			"label": "(GMT +2:00) Harare",
 			"offset": 120
 		},
@@ -191,7 +191,7 @@
 			"offset": 210
 		},
 		{
-			"name": "Asia/Muscat",
+			"name": "Asia/Dubai",
 			"label": "(GMT +4:00) Abu Dhabi, Muscat",
 			"offset": 240
 		},
@@ -216,12 +216,12 @@
 			"offset": 300
 		},
 		{
-			"name": "Asia/Calcutta",
+			"name": "Asia/Kolkata",
 			"label": "(GMT +5:30) Chennai, Calcutta, Mumbai, New Delhi",
 			"offset": 330
 		},
 		{
-			"name": "Asia/Katmandu",
+			"name": "Asia/Kathmandu",
 			"label": "(GMT +5:45) Katmandu",
 			"offset": 345
 		},
@@ -301,7 +301,7 @@
 			"offset": 630
 		},
 		{
-			"name": "Australia/Canberra",
+			"name": "Australia/Sydney",
 			"label": "(GMT +11:00) Canberra, Hobart, Melbourne, Sydney, Vladivostok",
 			"offset": 660
 		},
diff --git a/core/server/helpers/date.js b/core/server/helpers/date.js
index bf39f0874d..17327c41c2 100644
--- a/core/server/helpers/date.js
+++ b/core/server/helpers/date.js
@@ -1,34 +1,38 @@
 // # Date Helper
 // Usage: `{{date format="DD MM, YYYY"}}`, `{{date updated_at format="DD MM, YYYY"}}`
 //
-// Formats a date using moment.js. Formats published_at by default but will also take a date as a parameter
+// Formats a date using moment-timezone.js. Formats published_at by default but will also take a date as a parameter
 
-var moment          = require('moment'),
-    date;
+var moment          = require('moment-timezone'),
+    date,
+    timezone;
 
 date = function (date, options) {
     if (!options && date.hasOwnProperty('hash')) {
         options = date;
         date = undefined;
+        timezone = options.data.blog.timezone;
 
         // set to published_at by default, if it's available
         // otherwise, this will print the current date
         if (this.published_at) {
-            date = this.published_at;
+            date = moment(this.published_at).tz(timezone).format();
         }
     }
 
     // ensure that context is undefined, not null, as that can cause errors
     date = date === null ? undefined : date;
 
-    var f = options.hash.format || 'MMM Do, YYYY',
-        timeago = options.hash.timeago;
+    var f = options.hash.format || 'MMM DD, YYYY',
+        timeago = options.hash.timeago,
+        timeNow = moment().tz(timezone);
 
     if (timeago) {
-        date = moment(date).fromNow();
+        date = timezone ?  moment(date).tz(timezone).from(timeNow) : moment(date).fromNow();
     } else {
-        date = moment(date).format(f);
+        date = timezone ? moment(date).tz(timezone).format(f) : moment(date).format(f);
     }
+
     return date;
 };
 
diff --git a/core/test/functional/routes/frontend_spec.js b/core/test/functional/routes/frontend_spec.js
index 221bdefec1..4ed2b209f3 100644
--- a/core/test/functional/routes/frontend_spec.js
+++ b/core/test/functional/routes/frontend_spec.js
@@ -516,7 +516,6 @@ describe('Frontend Routing', function () {
         });
 
         it('should load a post with date permalink', function (done) {
-            // get today's date
             var date  = moment().format('YYYY/MM/DD');
 
             request.get('/' + date + '/welcome-to-ghost/')
@@ -525,6 +524,20 @@ describe('Frontend Routing', function () {
                 .end(doEnd(done));
         });
 
+        it('expect redirect because of wrong/old permalink prefix', function (done) {
+            var date  = moment().format('YYYY/MM/DD');
+
+            request.get('/2016/04/01/welcome-to-ghost/')
+                .expect('Content-Type', /html/)
+                .end(function (err, res) {
+                    res.status.should.eql(301);
+                    request.get('/' + date + '/welcome-to-ghost/')
+                        .expect(200)
+                        .expect('Content-Type', /html/)
+                        .end(doEnd(done));
+                });
+        });
+
         it('should serve RSS with date permalink', function (done) {
             request.get('/rss/')
                 .expect('Content-Type', 'text/xml; charset=utf-8')
diff --git a/core/test/unit/config_spec.js b/core/test/unit/config_spec.js
index 107cc94cb0..3e96c16301 100644
--- a/core/test/unit/config_spec.js
+++ b/core/test/unit/config_spec.js
@@ -384,8 +384,8 @@ describe('Config', function () {
         });
 
         describe('urlPathForPost', function () {
-            it('should output correct url for post', function () {
-                configUtils.set({theme: {permalinks: '/:slug/'}});
+            it('permalink is /:slug/', function () {
+                configUtils.set({theme: {permalinks: '/:slug/', timezone: 'Europe/Dublin'}});
 
                 var testData = testUtils.DataGenerator.Content.posts[2],
                     postLink = '/short-and-sweet/';
@@ -393,20 +393,17 @@ describe('Config', function () {
                 config.urlPathForPost(testData).should.equal(postLink);
             });
 
-            it('should output correct url for post with date permalink', function () {
-                configUtils.set({theme: {permalinks: '/:year/:month/:day/:slug/'}});
+            it('permalink is /:year/:month/:day/:slug, blog timezone is Los Angeles', function () {
+                configUtils.set({theme: {permalinks: '/:year/:month/:day/:slug/', timezone: 'America/Los_Angeles'}});
                 var testData = testUtils.DataGenerator.Content.posts[2],
-                    today = testData.published_at,
-                    dd = ('0' + today.getDate()).slice(-2),
-                    mm = ('0' + (today.getMonth() + 1)).slice(-2),
-                    yyyy = today.getFullYear(),
-                    postLink = '/' + yyyy + '/' + mm + '/' + dd + '/short-and-sweet/';
+                    postLink = '/2016/05/17/short-and-sweet/';
 
+                testData.published_at = new Date('2016-05-18T06:30:00.000Z');
                 config.urlPathForPost(testData).should.equal(postLink);
             });
 
-            it('should output correct url for page with date permalink', function () {
-                configUtils.set({theme: {permalinks: '/:year/:month/:day/:slug/'}});
+            it('post is page, no permalink usage allowed at all', function () {
+                configUtils.set({theme: {permalinks: '/:year/:month/:day/:slug/', timezone: 'America/Los_Angeles'}});
 
                 var testData = testUtils.DataGenerator.Content.posts[5],
                     postLink = '/static-page-test/';
@@ -414,16 +411,23 @@ describe('Config', function () {
                 config.urlPathForPost(testData).should.equal(postLink);
             });
 
-            it('should output correct url for post with complex permalink', function () {
-                configUtils.set({theme: {permalinks: '/:year/:id/:author/'}});
+            it('permalink is /:year/:id:/:author', function () {
+                configUtils.set({theme: {permalinks: '/:year/:id/:author/', timezone: 'America/Los_Angeles'}});
 
-                var testData = _.extend(
-                        {}, testUtils.DataGenerator.Content.posts[2], {id: 3}, {author: {slug: 'joe-bloggs'}}
-                    ),
-                    today = testData.published_at,
-                    yyyy = today.getFullYear(),
-                    postLink = '/' + yyyy + '/3/joe-bloggs/';
+                var testData = _.merge(testUtils.DataGenerator.Content.posts[2], {id: 3}, {author: {slug: 'joe-blog'}}),
+                    postLink = '/2015/3/joe-blog/';
 
+                testData.published_at = new Date('2016-01-01T00:00:00.000Z');
+                config.urlPathForPost(testData).should.equal(postLink);
+            });
+
+            it('permalink is /:year/:id:/:author', function () {
+                configUtils.set({theme: {permalinks: '/:year/:id/:author/', timezone: 'Europe/Berlin'}});
+
+                var testData = _.merge(testUtils.DataGenerator.Content.posts[2], {id: 3}, {author: {slug: 'joe-blog'}}),
+                    postLink = '/2016/3/joe-blog/';
+
+                testData.published_at = new Date('2016-01-01T00:00:00.000Z');
                 config.urlPathForPost(testData).should.equal(postLink);
             });
         });
diff --git a/core/test/unit/controllers/frontend/index_spec.js b/core/test/unit/controllers/frontend/index_spec.js
index 1ec42f48ae..9e05fbf779 100644
--- a/core/test/unit/controllers/frontend/index_spec.js
+++ b/core/test/unit/controllers/frontend/index_spec.js
@@ -426,16 +426,6 @@ describe('Frontend Controller', function () {
                     frontend.single(req, res, failTest(done));
                 });
 
-                it('will NOT render post via /YYYY/MM/DD/:slug/ with non-matching date in url', function (done) {
-                    var date = moment(mockPosts[1].published_at).subtract(1, 'days').format('YYYY/MM/DD');
-                    req.path = '/' + [date, mockPosts[1].posts[0].slug].join('/') + '/';
-
-                    frontend.single(req, res, function () {
-                        res.render.called.should.be.false();
-                        done();
-                    });
-                });
-
                 it('will NOT render post via /:slug/', function (done) {
                     req.path = '/' + mockPosts[1].posts[0].slug + '/';
 
diff --git a/core/test/unit/server_helpers/date_spec.js b/core/test/unit/server_helpers/date_spec.js
index b62f31cd68..6671f8a33f 100644
--- a/core/test/unit/server_helpers/date_spec.js
+++ b/core/test/unit/server_helpers/date_spec.js
@@ -6,7 +6,7 @@ var should         = require('should'),
 // Stuff we are testing
     handlebars     = hbs.handlebars,
     helpers        = require('../../../server/helpers'),
-    moment         = require('moment');
+    moment         = require('moment-timezone');
 
 describe('{{date}} helper', function () {
     before(function () {
@@ -17,22 +17,23 @@ describe('{{date}} helper', function () {
         should.exist(handlebars.helpers.date);
     });
 
-    // TODO: When timezone support is added these tests should be updated
-    //       to test the output of the helper against static strings instead
-    //       of calling moment().  Without timezone support the output of this
-    //       helper may differ depending on what timezone the tests are run in.
-
     it('creates properly formatted date strings', function () {
         var testDates = [
-                '2013-12-31T11:28:58.593Z',
-                '2014-01-01T01:28:58.593Z',
-                '2014-02-20T01:28:58.593Z',
-                '2014-03-01T01:28:58.593Z'
+                '2013-12-31T11:28:58.593+02:00',
+                '2014-01-01T01:28:58.593+11:00',
+                '2014-02-20T01:28:58.593-04:00',
+                '2014-03-01T01:28:58.593+00:00'
             ],
+            timezones = 'Europe/Dublin',
             format = 'MMM Do, YYYY',
             context = {
                 hash: {
                     format: format
+                },
+                data: {
+                    blog: {
+                        timezone: 'Europe/Dublin'
+                    }
                 }
             };
 
@@ -40,20 +41,27 @@ describe('{{date}} helper', function () {
             var rendered = helpers.date.call({published_at: d}, context);
 
             should.exist(rendered);
-            rendered.should.equal(moment(d).format(format));
+            rendered.should.equal(moment(d).tz(timezones).format(format));
         });
     });
 
     it('creates properly formatted time ago date strings', function () {
         var testDates = [
-                '2013-12-31T23:58:58.593Z',
-                '2014-01-01T00:28:58.593Z',
-                '2014-11-20T01:28:58.593Z',
-                '2014-03-01T01:28:58.593Z'
+                '2013-12-31T23:58:58.593+02:00',
+                '2014-01-01T00:28:58.593+11:00',
+                '2014-11-20T01:28:58.593-04:00',
+                '2014-03-01T01:28:58.593+00:00'
             ],
+            timezones = 'Europe/Dublin',
+            timeNow = moment().tz('Europe/Dublin'),
             context = {
                 hash: {
                     timeago: true
+                },
+                data: {
+                    blog: {
+                        timezone: 'Europe/Dublin'
+                    }
                 }
             };
 
@@ -61,7 +69,7 @@ describe('{{date}} helper', function () {
             var rendered = helpers.date.call({published_at: d}, context);
 
             should.exist(rendered);
-            rendered.should.equal(moment(d).fromNow());
+            rendered.should.equal(moment(d).tz(timezones).from(timeNow));
         });
     });
 });
diff --git a/package.json b/package.json
index 4ea33c446f..6cb04e16ff 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,7 @@
     "morgan": "1.7.0",
     "multer": "1.1.0",
     "netjet": "1.1.0",
+    "moment-timezone": "0.5.1",
     "node-uuid": "1.4.7",
     "nodemailer": "0.7.1",
     "oauth2orize": "1.3.0",