-export function createDate (y, m, d, h, M, s, ms) {
- //can't just apply() to create a date:
- //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
- var date = new Date(y, m, d, h, M, s, ms);
-
- //the date constructor remaps years 0-99 to 1900-1999
- if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
- date.setFullYear(y);
- }
- return date;
-}
-
export function createUTCDate (y) {
var date = new Date(Date.UTC.apply(null, arguments));
configFromStringAndArray(config);
} else if (format) {
configFromStringAndFormat(config);
- } else if (isDate(input)) {
- config._d = input;
} else {
configFromInput(config);
}
}
function configFromInput(config) {
- var input = config._i;
+ var input = config._i,
+ type = typeof input;
if (input === undefined) {
config._d = new Date(hooks.now());
+ config._offset = 0;
} else if (isDate(input)) {
config._d = new Date(input.valueOf());
- } else if (typeof input === 'string') {
+ config._offset = 0;
+ } else if (type === 'string') {
configFromString(config);
} else if (isArray(input)) {
config._a = map(input.slice(0), function (obj) {
return parseInt(obj, 10);
});
configFromArray(config);
- } else if (typeof(input) === 'object') {
+ } else if (type === 'object') {
configFromObject(config);
- } else if (typeof(input) === 'number') {
+ } else if (type === 'number') {
// from milliseconds
config._d = new Date(input);
+ config._offset = 0;
} else {
hooks.createFromInputFallback(config);
}
}
-export function createLocalOrUTC (input, format, locale, strict, isUTC) {
- var c = {};
+export function createWithTimeZone (timeZone) {
+ return function (input, format, locale, strict) {
+ var c = {};
- if (typeof(locale) === 'boolean') {
- strict = locale;
- locale = undefined;
- }
- // object construction must be done this way.
- // https://github.com/moment/moment/issues/1423
- c._isAMomentObject = true;
- c._useUTC = c._isUTC = isUTC;
- c._l = locale;
- c._i = input;
- c._f = format;
- c._strict = strict;
+ if (typeof(locale) === 'boolean') {
+ strict = locale;
+ locale = undefined;
+ }
+ // object construction must be done this way.
+ // https://github.com/moment/moment/issues/1423
+ c._isAMomentObject = true;
+ c._z = timeZone;
+ c._l = locale;
+ c._i = input;
+ c._f = format;
+ c._strict = strict;
- return createFromConfig(c);
+ return createFromConfig(c);
+ };
}
import { hooks } from '../utils/hooks';
-import { createDate, createUTCDate } from './date-from-array';
+import { createUTCDate } from './date-from-array';
import { daysInYear } from '../units/year';
import { weekOfYear, weeksInYear, dayOfYearFromWeeks } from '../units/week-calendar-utils';
import { YEAR, MONTH, DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants';
function currentDateArray(config) {
// hooks is actually the exported moment object
var nowValue = new Date(hooks.now());
- if (config._useUTC) {
- return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
- }
- return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
+ return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
}
// convert an array to a date.
config._a[HOUR] = 0;
}
- config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
- // Apply timezone offset from input. The actual utcOffset can be changed
- // with parseZone.
- if (config._tzm != null) {
- config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
- }
+ config._d = createUTCDate.apply(null, input);
if (config._nextDay) {
config._a[HOUR] = 24;
for (i = 0; i < config._f.length; i++) {
currentScore = 0;
tempConfig = copyConfig({}, config);
- if (config._useUTC != null) {
- tempConfig._useUTC = config._useUTC;
- }
tempConfig._f = config._f[i];
configFromStringAndFormat(tempConfig);
if (matched !== null) {
config._d = new Date(+matched[1]);
+ config._offset = 0;
return;
}
'release. Please refer to ' +
'https://github.com/moment/moment/issues/1407 for more info.',
function (config) {
- config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
+ config._d = new Date(config._i);
}
);
-import { createLocalOrUTC } from './from-anything';
+import LocalTimeZone from '../timezone/local';
+import { createWithTimeZone } from './from-anything';
-export function createLocal (input, format, locale, strict) {
- return createLocalOrUTC(input, format, locale, strict, false);
-}
+export var createLocal = createWithTimeZone(new LocalTimeZone());
-import { createLocalOrUTC } from './from-anything';
+import FixedOffsetTimeZone from '../timezone/fixed-offset';
+import { createWithTimeZone } from './from-anything';
-export function createUTC (input, format, locale, strict) {
- return createLocalOrUTC(input, format, locale, strict, true).utc();
+var create = createWithTimeZone(new FixedOffsetTimeZone(0));
+
+export function createUTC () {
+ return create.apply(null, arguments).utcOffset(0);
}
import absFloor from '../utils/abs-floor';
import absCeil from '../utils/abs-ceil';
-import { createUTCDate } from '../create/date-from-array';
export function bubble () {
var milliseconds = this._milliseconds;
-import { get, set } from './get-set';
import { setMonth } from '../units/month';
import { createDuration } from '../duration/create';
import { deprecateSimple } from '../utils/deprecate';
-import { hooks } from '../utils/hooks';
+import updateOffset from '../timezone/update-offset';
import absRound from '../utils/abs-round';
-
// TODO: remove 'name' arg after deprecation is removed
function createAdder(direction, name) {
return function (val, period) {
};
}
-export function addSubtract (mom, duration, isAdding, updateOffset) {
+export function addSubtract (mom, duration, isAdding) {
var milliseconds = duration._milliseconds,
days = absRound(duration._days),
- months = absRound(duration._months);
+ months = absRound(duration._months),
+ date = mom._d;
if (!mom.isValid()) {
// No op
return;
}
- updateOffset = updateOffset == null ? true : updateOffset;
-
if (milliseconds) {
- mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
+ date.setTime(date.valueOf() + milliseconds * isAdding);
}
if (days) {
- set(mom, 'Date', get(mom, 'Date') + days * isAdding);
+ date.setUTCDate(date.getUTCDate() + days * isAdding);
}
if (months) {
- setMonth(mom, get(mom, 'Month') + months * isAdding);
- }
- if (updateOffset) {
- hooks.updateOffset(mom, days || months);
+ setMonth(mom, date.getUTCMonth() + months * isAdding);
}
+ updateOffset(mom, days || months);
}
export var add = createAdder(1, 'add');
export var subtract = createAdder(-1, 'subtract');
-
-import { hooks } from '../utils/hooks';
-import hasOwnProp from '../utils/has-own-prop';
import isUndefined from '../utils/is-undefined';
import getParsingFlags from '../create/parsing-flags';
-
-// Plugins that add properties should also add the key here (null value),
-// so we can properly clone ourselves.
-var momentProperties = hooks.momentProperties = [];
+import updateOffset from '../timezone/update-offset';
export function copyConfig(to, from) {
- var i, prop, val;
-
if (!isUndefined(from._isAMomentObject)) {
to._isAMomentObject = from._isAMomentObject;
}
if (!isUndefined(from._tzm)) {
to._tzm = from._tzm;
}
- if (!isUndefined(from._isUTC)) {
- to._isUTC = from._isUTC;
- }
if (!isUndefined(from._offset)) {
to._offset = from._offset;
}
if (!isUndefined(from._locale)) {
to._locale = from._locale;
}
-
- if (momentProperties.length > 0) {
- for (i in momentProperties) {
- prop = momentProperties[i];
- val = from[prop];
- if (!isUndefined(val)) {
- to[prop] = val;
- }
- }
- }
+ to._z = from._z;
return to;
}
-var updateInProgress = false;
-
// Moment prototype object
export function Moment(config) {
copyConfig(this, config);
this._d = new Date(config._d != null ? config._d.getTime() : NaN);
- // Prevent infinite loop in case updateOffset creates new moment
- // objects.
- if (updateInProgress === false) {
- updateInProgress = true;
- hooks.updateOffset(this);
- updateInProgress = false;
- }
+ updateOffset(this, this._offset == null);
}
export function isMoment (obj) {
input: this._i,
format: this._f,
locale: this._locale,
- isUTC: this._isUTC,
+ timeZone: this._z,
strict: this._strict
};
}
import { normalizeUnits } from '../units/aliases';
-import { hooks } from '../utils/hooks';
+import updateOffset from '../timezone/update-offset';
import isFunction from '../utils/is-function';
export function makeGetSet (unit, keepTime) {
return function (value) {
if (value != null) {
set(this, unit, value);
- hooks.updateOffset(this, keepTime);
- return this;
+ return updateOffset(this, keepTime);
} else {
return get(this, unit);
}
export function get (mom, unit) {
return mom.isValid() ?
- mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
+ mom._d['getUTC' + unit]() : NaN;
}
export function set (mom, unit, value) {
if (mom.isValid()) {
- mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+ mom._d['setUTC' + unit](value);
}
}
import { createLocal } from '../create/local';
import { createUTC } from '../create/utc';
+import { createWithTimeZone } from '../create/from-anything';
import { createInvalid } from '../create/valid';
import { isMoment } from './constructor';
import { min, max } from './min-max';
createUnix,
createLocal,
createInZone,
+ createWithTimeZone,
createInvalid,
momentPrototype
};
--- /dev/null
+export default function FixedOffsetTimeZone (offset) {
+ this._offset = offset;
+}
+
+FixedOffsetTimeZone.prototype.parse = function (timestamp) {
+ return this._offset;
+};
+
+FixedOffsetTimeZone.prototype.abbr = function (timestamp) {
+ return 'UTC';
+};
+
+FixedOffsetTimeZone.prototype.name = function (timestamp) {
+ return 'Coordinated Universal Time';
+};
--- /dev/null
+export default function LocalTimeZone () {}
+
+function getTimezoneOffset (date) {
+ // On Firefox.24 Date#getTimezoneOffset returns a floating point.
+ // https://github.com/moment/moment/pull/1871
+ return -Math.round(date.getTimezoneOffset() / 15) * 15;
+}
+
+LocalTimeZone.prototype.parse = function (timestamp) {
+ var asUtc = new Date(timestamp);
+ return getTimezoneOffset(new Date(
+ asUtc.getUTCFullYear(),
+ asUtc.getUTCMonth(),
+ asUtc.getUTCDate(),
+ asUtc.getUTCHours(),
+ asUtc.getUTCMinutes(),
+ asUtc.getUTCSeconds(),
+ asUtc.getUTCMilliseconds()
+ ));
+};
+
+LocalTimeZone.prototype.abbr = function (timestamp) {
+ return '';
+};
--- /dev/null
+export default function updateOffset (instance, keepLocalTime) {
+ var oldOffset = instance._offset || 0;
+ var newOffset = instance._z.parse(+instance._d);
+ if (oldOffset !== newOffset && !keepLocalTime) {
+ instance._d.setTime(+instance._d + (newOffset - oldOffset) * 60000);
+ }
+ instance._offset = newOffset;
+ return instance;
+}
if (!this.isValid()) {
return input != null ? this : NaN;
}
- var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
+ var day = this._d.getUTCDay();
if (input != null) {
input = parseWeekday(input, this.localeData());
return this.add(input - day, 'd');
import { addUnitAlias } from './aliases';
import { addRegexToken, match3, match1to3 } from '../parse/regex';
import { daysInYear } from './year';
-import { createUTCDate } from '../create/date-from-array';
import { addParseToken } from '../parse/token';
import toInt from '../utils/to-int';
import { addParseToken } from '../parse/token';
import { hooks } from '../utils/hooks';
import { MONTH } from './constants';
+import updateOffset from '../timezone/update-offset';
import toInt from '../utils/to-int';
import isArray from '../utils/is-array';
import indexOf from '../utils/index-of';
}
dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
- mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
+ mom._d.setUTCMonth(value, dayOfMonth);
return mom;
}
export function getSetMonth (value) {
if (value != null) {
setMonth(this, value);
- hooks.updateOffset(this, true);
- return this;
+ return updateOffset(this, true);
} else {
return get(this, 'Month');
}
import zeroFill from '../utils/zero-fill';
import { createDuration } from '../duration/create';
-import { addSubtract } from '../moment/add-subtract';
import { isMoment, copyConfig } from '../moment/constructor';
import { addFormatToken } from '../format/format';
import { addRegexToken, matchOffset, matchShortOffset } from '../parse/regex';
import { addParseToken } from '../parse/token';
import { createLocal } from '../create/local';
-import { prepareConfig } from '../create/from-anything';
+import { prepareConfig, createWithTimeZone } from '../create/from-anything';
import { createUTC } from '../create/utc';
+import FixedOffsetTimeZone from '../timezone/fixed-offset';
+import LocalTimeZone from '../timezone/local';
+import updateOffset from '../timezone/update-offset';
import isDate from '../utils/is-date';
import toInt from '../utils/to-int';
import isUndefined from '../utils/is-undefined';
import compareArrays from '../utils/compare-arrays';
-import { hooks } from '../utils/hooks';
// FORMATTING
addRegexToken('Z', matchShortOffset);
addRegexToken('ZZ', matchShortOffset);
addParseToken(['Z', 'ZZ'], function (input, array, config) {
- config._useUTC = true;
- config._tzm = offsetFromString(matchShortOffset, input);
+ config._offset = config._tzm = offsetFromString(matchShortOffset, input);
});
// HELPERS
// Return a moment from input, that is local/utc/zone equivalent to model.
export function cloneWithOffset(input, model) {
- var res, diff;
- if (model._isUTC) {
- res = model.clone();
- diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
- // Use low-level api, because this fn is low-level api.
- res._d.setTime(res._d.valueOf() + diff);
- hooks.updateOffset(res, false);
- return res;
- } else {
- return createLocal(input).local();
- }
-}
-
-function getDateOffset (m) {
- // On Firefox.24 Date#getTimezoneOffset returns a floating point.
- // https://github.com/moment/moment/pull/1871
- return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
+ var output = createLocal(input);
+ output._z = model._z;
+ return updateOffset(output);
}
-// HOOKS
-
-// This function will be called whenever a moment is mutated.
-// It is intended to keep the offset in sync with the timezone.
-hooks.updateOffset = function () {};
-
// MOMENTS
// keepLocalTime = true means only change the timezone, without
// _changeInProgress == true case, then we have to adjust, because
// there is no such time in the given timezone.
export function getSetOffset (input, keepLocalTime) {
- var offset = this._offset || 0,
- localAdjust;
if (!this.isValid()) {
return input != null ? this : NaN;
}
} else if (Math.abs(input) < 16) {
input = input * 60;
}
- if (!this._isUTC && keepLocalTime) {
- localAdjust = getDateOffset(this);
- }
- this._offset = input;
- this._isUTC = true;
- if (localAdjust != null) {
- this.add(localAdjust, 'm');
- }
- if (offset !== input) {
- if (!keepLocalTime || this._changeInProgress) {
- addSubtract(this, createDuration(input - offset, 'm'), 1, false);
- } else if (!this._changeInProgress) {
- this._changeInProgress = true;
- hooks.updateOffset(this, true);
- this._changeInProgress = null;
- }
- }
- return this;
+ this._z = new FixedOffsetTimeZone(input);
+ return updateOffset(this, keepLocalTime);
} else {
- return this._isUTC ? offset : getDateOffset(this);
+ return this._offset || 0;
}
}
input = -input;
}
- this.utcOffset(input, keepLocalTime);
-
- return this;
+ return this.utcOffset(input, keepLocalTime);
} else {
return -this.utcOffset();
}
}
export function setOffsetToLocal (keepLocalTime) {
- if (this._isUTC) {
- this.utcOffset(0, keepLocalTime);
- this._isUTC = false;
-
- if (keepLocalTime) {
- this.subtract(getDateOffset(this), 'm');
- }
- }
- return this;
+ this._z = new LocalTimeZone();
+ return updateOffset(this, keepLocalTime);
}
export function setOffsetToParsedOffset () {
c = prepareConfig(c);
if (c._a) {
- var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
+ var other = cloneWithOffset(c._a, c);
this._isDSTShifted = this.isValid() &&
compareArrays(c._a, other.toArray()) > 0;
} else {
}
export function isLocal () {
- return this.isValid() ? !this._isUTC : false;
+ return this.isValid() && this._z instanceof LocalTimeZone;
}
export function isUtcOffset () {
- return this.isValid() ? this._isUTC : false;
+ return this.isValid() && this._z instanceof FixedOffsetTimeZone;
}
export function isUtc () {
- return this.isValid() ? this._isUTC && this._offset === 0 : false;
+ return this.isValid() && this._z instanceof FixedOffsetTimeZone && this._offset === 0;
}
addRegexToken('X', matchTimestamp);
addParseToken('X', function (input, array, config) {
config._d = new Date(parseFloat(input, 10) * 1000);
+ config._offset = 0;
});
addParseToken('x', function (input, array, config) {
config._d = new Date(toInt(input));
+ config._offset = 0;
});
// MOMENTS
export function getZoneAbbr () {
- return this._isUTC ? 'UTC' : '';
+ return this._z.abbr(+this);
}
export function getZoneName () {
- return this._isUTC ? 'Coordinated Universal Time' : '';
+ return typeof this._z.name === 'function' ? this._z.name(+this) : this._z.abbr();
}
max,
now,
isMoment,
- momentPrototype as fn,
- createUTC as utc,
- createUnix as unix,
- createLocal as local,
- createInvalid as invalid,
- createInZone as parseZone
+ momentPrototype as fn,
+ createUTC as utc,
+ createUnix as unix,
+ createLocal as local,
+ createInvalid as invalid,
+ createInZone as parseZone,
+ createWithTimeZone as withTimeZone
} from './lib/moment/moment';
import {
moment.isMoment = isMoment;
moment.weekdays = weekdays;
moment.parseZone = parseZone;
+moment.withTimeZone = withTimeZone;
moment.localeData = localeData;
moment.isDuration = isDuration;
moment.monthsShort = monthsShort;
assert.equal(+extend({}, nowu).clone(), +nowu, 'cloning extend-ed utc now is utc now');
});
-test('cloning respects moment.momentProperties', function (assert) {
- var m = moment();
-
- assert.equal(m.clone()._special, undefined, 'cloning ignores extra properties');
- m._special = 'bacon';
- moment.momentProperties.push('_special');
- assert.equal(m.clone()._special, 'bacon', 'cloning respects momentProperties');
- moment.momentProperties.pop();
-});
-
test('undefined', function (assert) {
assert.ok(moment().toDate() instanceof Date, 'undefined');
});
assert.equal(momentA.month(), 5, 'Calling moment() on a moment will create a clone');
});
-test('cloning carrying over utc mode', function (assert) {
- assert.equal(moment().local().clone()._isUTC, false, 'An explicit cloned local moment should have _isUTC == false');
- assert.equal(moment().utc().clone()._isUTC, true, 'An cloned utc moment should have _isUTC == true');
- assert.equal(moment().clone()._isUTC, false, 'An explicit cloned local moment should have _isUTC == false');
- assert.equal(moment.utc().clone()._isUTC, true, 'An explicit cloned utc moment should have _isUTC == true');
- assert.equal(moment(moment().local())._isUTC, false, 'An implicit cloned local moment should have _isUTC == false');
- assert.equal(moment(moment().utc())._isUTC, true, 'An implicit cloned utc moment should have _isUTC == true');
- assert.equal(moment(moment())._isUTC, false, 'An implicit cloned local moment should have _isUTC == false');
- assert.equal(moment(moment.utc())._isUTC, true, 'An implicit cloned utc moment should have _isUTC == true');
+test('cloning carrying over zone', function (assert) {
+ var momentA = moment();
+ assert.equal(momentA._z, momentA.clone()._z, 'An explicitly cloned moment should copy the zone');
+ assert.equal(momentA._z, moment(momentA)._z, 'An implicitly cloned moment should copy the zone');
});
test('parsing iso', function (assert) {
assert.equal(orig.input, '1992-10-22', 'original input is not correct.');
assert.equal(orig.format, 'YYYY-MM-DD', 'original format is defined.');
assert.equal(orig.locale._abbr, 'en', 'default locale is en');
- assert.equal(orig.isUTC, false, 'not a UTC date');
+ assert.ok(orig.timeZone, 'has a zone property');
});
test('valid date at fr locale', function (assert) {
});
test('setters across DST +1', function (assert) {
- var oldUpdateOffset = moment.updateOffset,
- // Based on a real story somewhere in America/Los_Angeles
- dstAt = moment('2014-03-09T02:00:00-08:00').parseZone(),
+ var create = moment.withTimeZone({
+ parse: function (timestamp) {
+ // Based on a real story somewhere in America/Los_Angeles
+ return timestamp < Date.UTC(2014, 2, 9, 2) ? -480 : -420;
+ }
+ }),
m;
- moment.updateOffset = function (mom, keepTime) {
- if (mom.isBefore(dstAt)) {
- mom.utcOffset(-8, keepTime);
- } else {
- mom.utcOffset(-7, keepTime);
- }
- };
-
- m = moment('2014-03-15T00:00:00-07:00').parseZone();
- m.year(2013);
+ m = create('2014-03-15T00:00:00-07:00').year(2013);
assert.equal(m.format(), '2013-03-15T00:00:00-08:00', 'year across +1');
- m = moment('2014-03-15T00:00:00-07:00').parseZone();
- m.month(0);
+ m = create('2014-03-15T00:00:00-07:00').month(0);
assert.equal(m.format(), '2014-01-15T00:00:00-08:00', 'month across +1');
- m = moment('2014-03-15T00:00:00-07:00').parseZone();
- m.date(1);
+ m = create('2014-03-15T00:00:00-07:00').date(1);
assert.equal(m.format(), '2014-03-01T00:00:00-08:00', 'date across +1');
- m = moment('2014-03-09T03:05:00-07:00').parseZone();
- m.hour(0);
+ m = create('2014-03-09T03:05:00-07:00').hour(0);
assert.equal(m.format(), '2014-03-09T00:05:00-08:00', 'hour across +1');
-
- moment.updateOffset = oldUpdateOffset;
});
test('setters across DST -1', function (assert) {
- var oldUpdateOffset = moment.updateOffset,
- // Based on a real story somewhere in America/Los_Angeles
- dstAt = moment('2014-11-02T02:00:00-07:00').parseZone(),
+ var create = moment.withTimeZone({
+ parse: function (timestamp) {
+ // Based on a real story somewhere in America/Los_Angeles
+ return timestamp < Date.UTC(2014, 10, 2, 2) ? -420 : -480;
+ }
+ }),
m;
- moment.updateOffset = function (mom, keepTime) {
- if (mom.isBefore(dstAt)) {
- mom.utcOffset(-7, keepTime);
- } else {
- mom.utcOffset(-8, keepTime);
- }
- };
-
- m = moment('2014-11-15T00:00:00-08:00').parseZone();
- m.year(2013);
+ m = create('2014-11-15T00:00:00-08:00').year(2013);
assert.equal(m.format(), '2013-11-15T00:00:00-07:00', 'year across -1');
- m = moment('2014-11-15T00:00:00-08:00').parseZone();
- m.month(0);
+ m = create('2014-11-15T00:00:00-08:00').month(0);
assert.equal(m.format(), '2014-01-15T00:00:00-07:00', 'month across -1');
- m = moment('2014-11-15T00:00:00-08:00').parseZone();
- m.date(1);
+ m = create('2014-11-15T00:00:00-08:00').date(1);
assert.equal(m.format(), '2014-11-01T00:00:00-07:00', 'date across -1');
- m = moment('2014-11-02T03:30:00-08:00').parseZone();
- m.hour(0);
+ m = create('2014-11-02T03:30:00-08:00').hour(0);
assert.equal(m.format(), '2014-11-02T00:30:00-07:00', 'hour across -1');
-
- moment.updateOffset = oldUpdateOffset;
});
});
test('startOf across DST +1', function (assert) {
- var oldUpdateOffset = moment.updateOffset,
- // Based on a real story somewhere in America/Los_Angeles
- dstAt = moment('2014-03-09T02:00:00-08:00').parseZone(),
+ var create = moment.withTimeZone({
+ parse: function (timestamp) {
+ // Based on a real story somewhere in America/Los_Angeles
+ return timestamp < Date.UTC(2014, 2, 9, 2) ? -480 : -420;
+ }
+ }),
m;
- moment.updateOffset = function (mom, keepTime) {
- if (mom.isBefore(dstAt)) {
- mom.utcOffset(-8, keepTime);
- } else {
- mom.utcOffset(-7, keepTime);
- }
- };
+ m = create('2014-03-15T00:00:00-07:00').startOf('y');
+ assert.equal(m.format(), '2014-01-01T00:00:00-08:00', 'startOf("year") across +1');
- m = moment('2014-03-15T00:00:00-07:00').parseZone();
- m.startOf('y');
- assert.equal(m.format(), '2014-01-01T00:00:00-08:00', 'startOf(\'year\') across +1');
+ m = create('2014-03-15T00:00:00-07:00').startOf('M');
+ assert.equal(m.format(), '2014-03-01T00:00:00-08:00', 'startOf("month") across +1');
- m = moment('2014-03-15T00:00:00-07:00').parseZone();
- m.startOf('M');
- assert.equal(m.format(), '2014-03-01T00:00:00-08:00', 'startOf(\'month\') across +1');
+ m = create('2014-03-09T09:00:00-07:00').startOf('d');
+ assert.equal(m.format(), '2014-03-09T00:00:00-08:00', 'startOf("day") across +1');
- m = moment('2014-03-09T09:00:00-07:00').parseZone();
- m.startOf('d');
- assert.equal(m.format(), '2014-03-09T00:00:00-08:00', 'startOf(\'day\') across +1');
+ m = create('2014-03-09T03:05:00-07:00').startOf('h');
+ assert.equal(m.format(), '2014-03-09T03:00:00-07:00', 'startOf("hour") after +1');
- m = moment('2014-03-09T03:05:00-07:00').parseZone();
- m.startOf('h');
- assert.equal(m.format(), '2014-03-09T03:00:00-07:00', 'startOf(\'hour\') after +1');
-
- m = moment('2014-03-09T01:35:00-08:00').parseZone();
- m.startOf('h');
- assert.equal(m.format(), '2014-03-09T01:00:00-08:00', 'startOf(\'hour\') before +1');
-
- // There is no such time as 2:30-7 to try startOf('hour') across that
-
- moment.updateOffset = oldUpdateOffset;
+ m = create('2014-03-09T01:35:00-08:00').startOf('h');
+ assert.equal(m.format(), '2014-03-09T01:00:00-08:00', 'startOf("hour") before +1');
});
test('startOf across DST -1', function (assert) {
- var oldUpdateOffset = moment.updateOffset,
- // Based on a real story somewhere in America/Los_Angeles
- dstAt = moment('2014-11-02T02:00:00-07:00').parseZone(),
+ var create = moment.withTimeZone({
+ parse: function (timestamp) {
+ // Based on a real story somewhere in America/Los_Angeles
+ return timestamp < Date.UTC(2014, 10, 2, 2) ? -420 : -480;
+ }
+ }),
m;
- moment.updateOffset = function (mom, keepTime) {
- if (mom.isBefore(dstAt)) {
- mom.utcOffset(-7, keepTime);
- } else {
- mom.utcOffset(-8, keepTime);
- }
- };
+ m = create('2014-11-15T00:00:00-08:00').startOf('y');
+ assert.equal(m.format(), '2014-01-01T00:00:00-07:00', 'startOf("year") across -1');
- m = moment('2014-11-15T00:00:00-08:00').parseZone();
- m.startOf('y');
- assert.equal(m.format(), '2014-01-01T00:00:00-07:00', 'startOf(\'year\') across -1');
+ m = create('2014-11-15T00:00:00-08:00').startOf('M');
+ assert.equal(m.format(), '2014-11-01T00:00:00-07:00', 'startOf("month") across -1');
- m = moment('2014-11-15T00:00:00-08:00').parseZone();
- m.startOf('M');
- assert.equal(m.format(), '2014-11-01T00:00:00-07:00', 'startOf(\'month\') across -1');
-
- m = moment('2014-11-02T09:00:00-08:00').parseZone();
- m.startOf('d');
- assert.equal(m.format(), '2014-11-02T00:00:00-07:00', 'startOf(\'day\') across -1');
+ m = create('2014-11-02T09:00:00-08:00').startOf('d');
+ assert.equal(m.format(), '2014-11-02T00:00:00-07:00', 'startOf("day") across -1');
// note that utc offset is -8
- m = moment('2014-11-02T01:30:00-08:00').parseZone();
- m.startOf('h');
- assert.equal(m.format(), '2014-11-02T01:00:00-08:00', 'startOf(\'hour\') after +1');
+ m = create('2014-11-02T01:30:00-08:00').startOf('h');
+ assert.equal(m.format(), '2014-11-02T01:00:00-08:00', 'startOf("hour") after +1');
// note that utc offset is -7
- m = moment('2014-11-02T01:30:00-07:00').parseZone();
- m.startOf('h');
- assert.equal(m.format(), '2014-11-02T01:00:00-07:00', 'startOf(\'hour\') before +1');
-
- moment.updateOffset = oldUpdateOffset;
+ m = create('2014-11-02T01:30:00-07:00').startOf('h');
+ assert.equal(m.format(), '2014-11-02T01:00:00-07:00', 'startOf("hour") before +1');
});
test('endOf millisecond and no-arg', function (assert) {
test('cloning with utc offset', function (assert) {
var m = moment.utc('2012-01-02T08:20:00');
- assert.equal(moment.utc(m)._isUTC, true, 'the local offset should be converted to UTC');
- assert.equal(moment.utc(m.clone().utc())._isUTC, true, 'the local offset should stay in UTC');
+ assert.equal(moment.utc(m).utcOffset(), 0, 'the utc offset should be 0');
+ assert.equal(moment.utc(m.clone().utc()).utcOffset(), 0, 'the utc offset should stay 0');
m.utcOffset(120);
- assert.equal(moment.utc(m)._isUTC, true, 'the explicit utc offset should stay in UTC');
assert.equal(moment.utc(m).utcOffset(), 0, 'the explicit utc offset should have an offset of 0');
});
});
test('update offset after changing any values', function (assert) {
- var oldOffset = moment.updateOffset,
- m = moment.utc([2000, 6, 1]);
-
- moment.updateOffset = function (mom, keepTime) {
- if (mom.__doChange) {
- if (+mom > 962409600000) {
- mom.utcOffset(-120, keepTime);
- } else {
- mom.utcOffset(-60, keepTime);
- }
- }
- };
+ var m = moment.utc([2000, 6, 1]);
assert.equal(m.format('ZZ'), '+0000', 'should be at +0000');
assert.equal(m.format('HH:mm'), '00:00', 'should start 12AM at +0000 timezone');
- m.__doChange = true;
+ m._z = {
+ parse: function (timestamp) {
+ return timestamp > Date.UTC(2000, 6, 1) ? -120 : -60;
+ }
+ };
m.add(1, 'h');
assert.equal(m.format('ZZ'), '-0200', 'should be at -0200');
assert.equal(m.format('ZZ'), '-0100', 'should be at -0100');
assert.equal(m.format('HH:mm'), '23:00', '12AM at +0000 should be 11PM at -0100 timezone');
-
- moment.updateOffset = oldOffset;
});
-//////////////////
test('getters and setters', function (assert) {
var a = moment([2011, 5, 20]);
});
test('add / subtract over dst', function (assert) {
- var oldOffset = moment.updateOffset,
- m = moment.utc([2000, 2, 31, 3]);
-
- moment.updateOffset = function (mom, keepTime) {
- if (mom.clone().utc().month() > 2) {
- mom.utcOffset(60, keepTime);
- } else {
- mom.utcOffset(0, keepTime);
- }
- };
+ var m = moment.utc([2000, 2, 31, 3]);
+
+ function parse (instance) {
+ return new Date(+instance).getUTCMonth() > 2 ? 60 : 0;
+ }
+
+ m._z = {parse: parse, offset: parse};
assert.equal(m.hour(), 3, 'should start at 00:00');
m.subtract(1, 'month');
assert.equal(m.hour(), 3, 'subtracting 1 month should have the same hour');
-
- moment.updateOffset = oldOffset;
});
test('isDST', function (assert) {
- var oldOffset = moment.updateOffset;
-
- moment.updateOffset = function (mom, keepTime) {
- if (mom.month() > 2 && mom.month() < 9) {
- mom.utcOffset(60, keepTime);
- } else {
- mom.utcOffset(0, keepTime);
+ var withSummerDst = moment.withTimeZone({
+ parse: function (timestamp) {
+ var month = new Date(timestamp).getUTCMonth();
+ return (month > 2 && month < 9) ? 60 : 0;
}
- };
+ });
- assert.ok(!moment().month(0).isDST(), 'Jan should not be summer dst');
- assert.ok(moment().month(6).isDST(), 'Jul should be summer dst');
- assert.ok(!moment().month(11).isDST(), 'Dec should not be summer dst');
-
- moment.updateOffset = function (mom) {
- if (mom.month() > 2 && mom.month() < 9) {
- mom.utcOffset(0);
- } else {
- mom.utcOffset(60);
+ var withWinterDst = moment.withTimeZone({
+ parse: function (timestamp) {
+ var month = new Date(timestamp).getUTCMonth();
+ return (month > 2 && month < 9) ? 0 : 60;
}
- };
-
- assert.ok(moment().month(0).isDST(), 'Jan should be winter dst');
- assert.ok(!moment().month(6).isDST(), 'Jul should not be winter dst');
- assert.ok(moment().month(11).isDST(), 'Dec should be winter dst');
-
- moment.updateOffset = oldOffset;
+ });
+
+ assert.ok(!withSummerDst().month(0).isDST(), 'Jan should not be summer dst');
+ assert.ok(withSummerDst().month(6).isDST(), 'Jul should be summer dst');
+ assert.ok(!withSummerDst().month(11).isDST(), 'Dec should not be summer dst');
+ assert.ok(withWinterDst().month(0).isDST(), 'Jan should be winter dst');
+ assert.ok(!withWinterDst().month(6).isDST(), 'Jul should not be winter dst');
+ assert.ok(withWinterDst().month(11).isDST(), 'Dec should be winter dst');
});
test('zone names', function (assert) {
assert.equal(+zoneA, +zoneE, 'moment should equal moment.zone(1000)');
});
-test('update offset after changing any values', function (assert) {
- var oldOffset = moment.updateOffset,
- m = moment.utc([2000, 6, 1]);
-
- moment.updateOffset = function (mom, keepTime) {
- if (mom.__doChange) {
- if (+mom > 962409600000) {
- mom.zone(120, keepTime);
- } else {
- mom.zone(60, keepTime);
- }
- }
- };
-
- assert.equal(m.format('ZZ'), '+0000', 'should be at +0000');
- assert.equal(m.format('HH:mm'), '00:00', 'should start 12AM at +0000 timezone');
-
- m.__doChange = true;
- m.add(1, 'h');
-
- assert.equal(m.format('ZZ'), '-0200', 'should be at -0200');
- assert.equal(m.format('HH:mm'), '23:00', '1AM at +0000 should be 11PM at -0200 timezone');
-
- m.subtract(1, 'h');
-
- assert.equal(m.format('ZZ'), '-0100', 'should be at -0100');
- assert.equal(m.format('HH:mm'), '23:00', '12AM at +0000 should be 11PM at -0100 timezone');
-
- moment.updateOffset = oldOffset;
-});
-
test('getters and setters', function (assert) {
var a = moment([2011, 5, 20]);
assert.ok(zoneA.isBefore(zoneC, 'hour'), 'isBefore:hour should work with two moments with different offsets');
});
-test('add / subtract over dst', function (assert) {
- var oldOffset = moment.updateOffset,
- m = moment.utc([2000, 2, 31, 3]);
-
- moment.updateOffset = function (mom, keepTime) {
- if (mom.clone().utc().month() > 2) {
- mom.zone(-60, keepTime);
- } else {
- mom.zone(0, keepTime);
- }
- };
-
- assert.equal(m.hour(), 3, 'should start at 00:00');
-
- m.add(24, 'hour');
-
- assert.equal(m.hour(), 4, 'adding 24 hours should disregard dst');
-
- m.subtract(24, 'hour');
-
- assert.equal(m.hour(), 3, 'subtracting 24 hours should disregard dst');
-
- m.add(1, 'day');
-
- assert.equal(m.hour(), 3, 'adding 1 day should have the same hour');
-
- m.subtract(1, 'day');
-
- assert.equal(m.hour(), 3, 'subtracting 1 day should have the same hour');
-
- m.add(1, 'month');
-
- assert.equal(m.hour(), 3, 'adding 1 month should have the same hour');
-
- m.subtract(1, 'month');
-
- assert.equal(m.hour(), 3, 'subtracting 1 month should have the same hour');
-
- moment.updateOffset = oldOffset;
-});
-
-test('isDST', function (assert) {
- var oldOffset = moment.updateOffset;
-
- moment.updateOffset = function (mom, keepTime) {
- if (mom.month() > 2 && mom.month() < 9) {
- mom.zone(-60, keepTime);
- } else {
- mom.zone(0, keepTime);
- }
- };
-
- assert.ok(!moment().month(0).isDST(), 'Jan should not be summer dst');
- assert.ok(moment().month(6).isDST(), 'Jul should be summer dst');
- assert.ok(!moment().month(11).isDST(), 'Dec should not be summer dst');
-
- moment.updateOffset = function (mom) {
- if (mom.month() > 2 && mom.month() < 9) {
- mom.zone(0);
- } else {
- mom.zone(-60);
- }
- };
-
- assert.ok(moment().month(0).isDST(), 'Jan should be winter dst');
- assert.ok(!moment().month(6).isDST(), 'Jul should not be winter dst');
- assert.ok(moment().month(11).isDST(), 'Dec should be winter dst');
-
- moment.updateOffset = oldOffset;
-});
-
test('zone names', function (assert) {
test.expectedDeprecations();
assert.equal(moment().zoneAbbr(), '', 'Local zone abbr should be empty');