From 16dcad11fd28cad216d2c9f52f5a68dec7201139 Mon Sep 17 00:00:00 2001 From: Iskren Chernev Date: Thu, 26 Jun 2014 00:17:35 -0700 Subject: [PATCH] Fix local to utc/zone switching with keepLocalTime option --- moment.js | 37 +++++++---- test/moment/zone_switching.js | 115 ++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 test/moment/zone_switching.js diff --git a/moment.js b/moment.js index ba5a6de8b..bcdf4ac8e 100644 --- a/moment.js +++ b/moment.js @@ -2043,13 +2043,19 @@ return this._pf.overflow; }, - utc : function () { - return this.zone(0); + utc : function (keepLocalTime) { + return this.zone(0, keepLocalTime); }, - local : function () { - this.zone(0); - this._isUTC = false; + local : function (keepLocalTime) { + if (this._isUTC) { + this.zone(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.add(this._d.getTimezoneOffset(), 'm'); + } + } return this; }, @@ -2243,18 +2249,19 @@ } ), - // keepTime = true means only change the timezone, without affecting - // the local hour. So 5:31:26 +0300 --[zone(2, true)]--> 5:31:26 +0200 - // It is possible that 5:31:26 doesn't exist int zone +0200, so we - // adjust the time as needed, to be valid. + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[zone(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist int zone + // +0200, so we adjust the time as needed, to be valid. // // Keeping the time actually adds/subtracts (one hour) // from the actual represented time. That is why we call updateOffset // a second time. In case it wants us to change the offset again // _changeInProgress == true case, then we have to adjust, because // there is no such time in the given timezone. - zone : function (input, keepTime) { - var offset = this._offset || 0; + zone : function (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; if (input != null) { if (typeof input === "string") { input = timezoneMinutesFromString(input); @@ -2262,10 +2269,16 @@ if (Math.abs(input) < 16) { input = input * 60; } + if (!this._isUTC && keepLocalTime) { + localAdjust = this._d.getTimezoneOffset(); + } this._offset = input; this._isUTC = true; + if (localAdjust != null) { + this.subtract(localAdjust, 'm'); + } if (offset !== input) { - if (!keepTime || this._changeInProgress) { + if (!keepLocalTime || this._changeInProgress) { addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, false); } else if (!this._changeInProgress) { diff --git a/test/moment/zone_switching.js b/test/moment/zone_switching.js new file mode 100644 index 000000000..f72cf8c56 --- /dev/null +++ b/test/moment/zone_switching.js @@ -0,0 +1,115 @@ +var moment = require('../../moment'); + +exports.zoneSwitching = { + setUp : function (done) { + moment.lang('en'); + moment.createFromInputFallback = function () { + throw new Error("input not handled by moment"); + }; + + done(); + }, + + "local to utc, keepLocalTime = true" : function (test) { + var m = moment(), + fmt = "YYYY-DD-MM HH:mm:ss"; + test.equal(m.clone().utc(true).format(fmt), m.format(fmt), "local to utc failed to keep local time"); + + test.done(); + }, + + "local to utc, keepLocalTime = false" : function (test) { + var m = moment(); + test.equal(m.clone().utc().valueOf(), m.valueOf(), "local to utc failed to keep utc time (implicit)"); + test.equal(m.clone().utc(false).valueOf(), m.valueOf(), "local to utc failed to keep utc time (explicit)"); + + test.done(); + }, + + "local to zone, keepLocalTime = true" : function (test) { + var m = moment(), + fmt = "YYYY-DD-MM HH:mm:ss", + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + test.equal(m.clone().zone(z * 60, true).format(fmt), m.format(fmt), + "local to zone(" + z + ":00) failed to keep local time"); + } + + test.done(); + }, + + "local to zone, keepLocalTime = false" : function (test) { + var m = moment(), + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + test.equal(m.clone().zone(z * 60).valueOf(), m.valueOf(), + "local to zone(" + z + ":00) failed to keep utc time (implicit)"); + test.equal(m.clone().zone(z * 60, false).valueOf(), m.valueOf(), + "local to zone(" + z + ":00) failed to keep utc time (explicit)"); + } + + test.done(); + }, + + "utc to local, keepLocalTime = true" : function (test) { + var um = moment.utc(), + fmt = "YYYY-DD-MM HH:mm:ss"; + + test.equal(um.clone().local(true).format(fmt), um.format(fmt), "utc to local failed to keep local time"); + + test.done(); + }, + + "utc to local, keepLocalTime = false" : function (test) { + var um = moment.utc(); + test.equal(um.clone().local().valueOf(), um.valueOf(), "utc to local failed to keep utc time (implicit)"); + test.equal(um.clone().local(false).valueOf(), um.valueOf(), "utc to local failed to keep utc time (explicit)"); + + test.done(); + }, + + "zone to local, keepLocalTime = true" : function (test) { + var m = moment(), + fmt = "YYYY-DD-MM HH:mm:ss", + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + m.zone(z * 60); + + test.equal(m.clone().local(true).format(fmt), m.format(fmt), + "zone(" + z + ":00) to local failed to keep the local time"); + } + + test.done(); + }, + + "zone to local, keepLocalTime = false" : function (test) { + var m = moment(), + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + m.zone(z * 60); + + test.equal(m.clone().local(false).valueOf(), m.valueOf(), + "zone(" + z + ":00) to local failed to keep the local time (explicit)"); + test.equal(m.clone().local().valueOf(), m.valueOf(), + "zone(" + z + ":00) to local failed to keep the local time (implicit)"); + } + + test.done(); + } +}; -- 2.47.2