//! moment.js
-//! version : 2.5.1
+//! version : 2.6.0
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
************************************/
var moment,
- VERSION = "2.5.1",
- global = this,
+ VERSION = "2.6.0",
+ // the global-scope this is NOT the global object in Node.js
+ globalScope = typeof global !== 'undefined' ? global : this,
+ oldGlobalMoment,
round = Math.round,
i,
},
// check for nodeJS
- hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
+ hasModule = (typeof module !== 'undefined' && module.exports),
// ASP.NET json date format regex
aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
// format tokens
- formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
// parsing token regexes
parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
parseTokenT = /T/i, // T (ISO separator)
parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
+ parseTokenOrdinal = /\d{1,2}/,
//strict parsing regexes
parseTokenOneDigit = /\d/, // 0 - 9
// iso time formats and regexes
isoTimes = [
- ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
+ ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/],
['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
['HH:mm', /(T| )\d\d:\d\d/],
['HH', /(T| )\d\d/]
w : 'week',
W : 'isoWeek',
M : 'month',
+ Q : 'quarter',
y : 'year',
DDD : 'dayOfYear',
e : 'weekday',
};
}
+ function deprecate(msg, fn) {
+ var firstTime = true;
+ function printMsg() {
+ if (moment.suppressDeprecationWarnings === false &&
+ typeof console !== 'undefined' && console.warn) {
+ console.warn("Deprecation warning: " + msg);
+ }
+ }
+ return extend(function () {
+ if (firstTime) {
+ printMsg();
+ firstTime = false;
+ }
+ return fn.apply(this, arguments);
+ }, fn);
+ }
+
function padToken(func, count) {
return function (a) {
return leftZeroFill(func.call(this, a), count);
function Duration(duration) {
var normalizedInput = normalizeObjectUnits(duration),
years = normalizedInput.year || 0,
+ quarters = normalizedInput.quarter || 0,
months = normalizedInput.month || 0,
weeks = normalizedInput.week || 0,
days = normalizedInput.day || 0,
// which months you are are talking about, so we have to store
// it separately.
this._months = +months +
+ quarters * 3 +
years * 12;
this._data = {};
}
// helper function for _.addTime and _.subtractTime
- function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
+ function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) {
var milliseconds = duration._milliseconds,
days = duration._days,
- months = duration._months,
- minutes,
- hours;
+ months = duration._months;
+ updateOffset = updateOffset == null ? true : updateOffset;
if (milliseconds) {
mom._d.setTime(+mom._d + milliseconds * isAdding);
}
- // store the minutes and hours so we can restore them
- if (days || months) {
- minutes = mom.minute();
- hours = mom.hour();
- }
if (days) {
- mom.date(mom.date() + days * isAdding);
+ rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding);
}
if (months) {
- mom.month(mom.month() + months * isAdding);
+ rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding);
}
- if (milliseconds && !ignoreUpdateOffset) {
- moment.updateOffset(mom);
- }
- // restore the minutes and hours after possibly changing dst
- if (days || months) {
- mom.minute(minutes);
- mom.hour(hours);
+ if (updateOffset) {
+ moment.updateOffset(mom, days || months);
}
}
return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
}
+ function weeksInYear(year, dow, doy) {
+ return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week;
+ }
+
function daysInYear(year) {
return isLeapYear(year) ? 366 : 365;
}
function getParseRegexForToken(token, config) {
var a, strict = config._strict;
switch (token) {
+ case 'Q':
+ return parseTokenOneDigit;
case 'DDDD':
return parseTokenThreeDigits;
case 'YYYY':
case 'e':
case 'E':
return parseTokenOneOrTwoDigits;
+ case 'Do':
+ return parseTokenOrdinal;
default :
a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
return a;
var a, datePartArray = config._a;
switch (token) {
+ // QUARTER
+ case 'Q':
+ if (input != null) {
+ datePartArray[MONTH] = (toInt(input) - 1) * 3;
+ }
+ break;
// MONTH
case 'M' : // fall through to MM
case 'MM' :
datePartArray[DATE] = toInt(input);
}
break;
+ case 'Do' :
+ if (input != null) {
+ datePartArray[DATE] = toInt(parseInt(input, 10));
+ }
+ break;
// DAY OF YEAR
case 'DDD' : // fall through to DDDD
case 'DDDD' :
break;
// YEAR
case 'YY' :
- datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+ datePartArray[YEAR] = moment.parseTwoDigitYear(input);
break;
case 'YYYY' :
case 'YYYYY' :
//compute day of the year from weeks and weekdays
if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
fixYear = function (val) {
- var int_val = parseInt(val, 10);
+ var intVal = parseInt(val, 10);
return val ?
- (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) :
+ (val.length < 3 ? (intVal > 68 ? 1900 + intVal : 2000 + intVal) : intVal) :
(config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
};
makeDateFromStringAndFormat(config);
}
else {
- config._d = new Date(string);
+ moment.createFromInputFallback(config);
}
}
config._d = new Date(+input);
} else if (typeof(input) === 'object') {
dateFromObject(config);
- } else {
+ } else if (typeof(input) === 'number') {
+ // from milliseconds
config._d = new Date(input);
+ } else {
+ moment.createFromInputFallback(config);
}
}
var input = config._i,
format = config._f;
- if (input === null) {
+ if (input === null || (format === undefined && input === '')) {
return moment.invalid({nullInput: true});
}
return makeMoment(c);
};
+ moment.suppressDeprecationWarnings = false;
+
+ moment.createFromInputFallback = deprecate(
+ "moment construction falls back to js Date. This is " +
+ "discouraged and will be removed in upcoming major " +
+ "release. Please refer to " +
+ "https://github.com/moment/moment/issues/1407 for more info.",
+ function (config) {
+ config._d = new Date(config._i);
+ });
+
// creating with utc
moment.utc = function (input, format, lang, strict) {
var c;
// default format
moment.defaultFormat = isoFormat;
+ // Plugins that add properties should also add the key here (null value),
+ // so we can properly clone ourselves.
+ moment.momentProperties = momentProperties;
+
// This function will be called whenever a moment is mutated.
// It is intended to keep the offset in sync with the timezone.
moment.updateOffset = function () {};
return m;
};
- moment.parseZone = function (input) {
- return moment(input).parseZone();
+ moment.parseZone = function () {
+ return moment.apply(null, arguments).parseZone();
+ };
+
+ moment.parseTwoDigitYear = function (input) {
+ return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
};
/************************************
}
},
- month : function (input) {
- var utc = this._isUTC ? 'UTC' : '',
- dayOfMonth;
-
- if (input != null) {
- if (typeof input === 'string') {
- input = this.lang().monthsParse(input);
- if (typeof input !== 'number') {
- return this;
- }
- }
-
- dayOfMonth = this.date();
- this.date(1);
- this._d['set' + utc + 'Month'](input);
- this.date(Math.min(dayOfMonth, this.daysInMonth()));
-
- moment.updateOffset(this);
- return this;
- } else {
- return this._d['get' + utc + 'Month']();
- }
- },
+ month : makeAccessor('Month', true),
startOf: function (units) {
units = normalizeUnits(units);
case 'year':
this.month(0);
/* falls through */
+ case 'quarter':
case 'month':
this.date(1);
/* falls through */
this.isoWeekday(1);
}
+ // quarters are also special
+ if (units === 'quarter') {
+ this.month(Math.floor(this.month() / 3) * 3);
+ }
+
return this;
},
return other > this ? this : other;
},
- zone : function (input) {
+ // 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.
+ //
+ // 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;
if (input != null) {
if (typeof input === "string") {
this._offset = input;
this._isUTC = true;
if (offset !== input) {
- addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
+ if (!keepTime || this._changeInProgress) {
+ addOrSubtractDurationFromMoment(this,
+ moment.duration(offset - input, 'm'), 1, false);
+ } else if (!this._changeInProgress) {
+ this._changeInProgress = true;
+ moment.updateOffset(this, true);
+ this._changeInProgress = null;
+ }
}
} else {
return this._isUTC ? offset : this._d.getTimezoneOffset();
return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
},
- quarter : function () {
- return Math.ceil((this.month() + 1.0) / 3.0);
+ quarter : function (input) {
+ return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
},
weekYear : function (input) {
return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
},
+ isoWeeksInYear : function () {
+ return weeksInYear(this.year(), 1, 4);
+ },
+
+ weeksInYear : function () {
+ var weekInfo = this._lang._week;
+ return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
+ },
+
get : function (units) {
units = normalizeUnits(units);
return this[units]();
}
});
- // helper for adding shortcuts
- function makeGetterAndSetter(name, key) {
- moment.fn[name] = moment.fn[name + 's'] = function (input) {
- var utc = this._isUTC ? 'UTC' : '';
- if (input != null) {
- this._d['set' + utc + key](input);
- moment.updateOffset(this);
+ function rawMonthSetter(mom, value) {
+ var dayOfMonth;
+
+ // TODO: Move this out of here!
+ if (typeof value === 'string') {
+ value = mom.lang().monthsParse(value);
+ // TODO: Another silent failure?
+ if (typeof value !== 'number') {
+ return mom;
+ }
+ }
+
+ dayOfMonth = Math.min(mom.date(),
+ daysInMonth(mom.year(), value));
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
+ return mom;
+ }
+
+ function rawGetter(mom, unit) {
+ return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]();
+ }
+
+ function rawSetter(mom, unit, value) {
+ if (unit === 'Month') {
+ return rawMonthSetter(mom, value);
+ } else {
+ return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+ }
+ }
+
+ function makeAccessor(unit, keepTime) {
+ return function (value) {
+ if (value != null) {
+ rawSetter(this, unit, value);
+ moment.updateOffset(this, keepTime);
return this;
} else {
- return this._d['get' + utc + key]();
+ return rawGetter(this, unit);
}
};
}
- // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
- for (i = 0; i < proxyGettersAndSetters.length; i ++) {
- makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
- }
-
- // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
- makeGetterAndSetter('year', 'FullYear');
+ moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false);
+ moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false);
+ moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false);
+ // Setting the hour should keep the time, because the user explicitly
+ // specified which hour he wants. So trying to maintain the same hour (in
+ // a new timezone) makes sense. Adding/subtracting hours does not follow
+ // this rule.
+ moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true);
+ // moment.fn.month is defined separately
+ moment.fn.date = makeAccessor('Date', true);
+ moment.fn.dates = deprecate("dates accessor is deprecated. Use date instead.", makeAccessor('Date', true));
+ moment.fn.year = makeAccessor('FullYear', true);
+ moment.fn.years = deprecate("years accessor is deprecated. Use year instead.", makeAccessor('FullYear', true));
// add plural methods
moment.fn.days = moment.fn.day;
moment.fn.months = moment.fn.month;
moment.fn.weeks = moment.fn.week;
moment.fn.isoWeeks = moment.fn.isoWeek;
+ moment.fn.quarters = moment.fn.quarter;
// add aliased format methods
moment.fn.toJSON = moment.fn.toISOString;
Exposing Moment
************************************/
- function makeGlobal(deprecate) {
- var warned = false, local_moment = moment;
+ function makeGlobal(shouldDeprecate) {
/*global ender:false */
if (typeof ender !== 'undefined') {
return;
}
- // here, `this` means `window` in the browser, or `global` on the server
- // add `moment` as a global object via a string identifier,
- // for Closure Compiler "advanced" mode
- if (deprecate) {
- global.moment = function () {
- if (!warned && console && console.warn) {
- warned = true;
- console.warn(
- "Accessing Moment through the global scope is " +
- "deprecated, and will be removed in an upcoming " +
- "release.");
- }
- return local_moment.apply(null, arguments);
- };
- extend(global.moment, local_moment);
+ oldGlobalMoment = globalScope.moment;
+ if (shouldDeprecate) {
+ globalScope.moment = deprecate(
+ "Accessing Moment through the global scope is " +
+ "deprecated, and will be removed in an upcoming " +
+ "release.",
+ moment);
} else {
- global['moment'] = moment;
+ globalScope.moment = moment;
}
}
// CommonJS module is defined
if (hasModule) {
module.exports = moment;
- makeGlobal(true);
} else if (typeof define === "function" && define.amd) {
define("moment", function (require, exports, module) {
- if (module.config && module.config() && module.config().noGlobal !== true) {
- // If user provided noGlobal, he is aware of global
- makeGlobal(module.config().noGlobal === undefined);
+ if (module.config && module.config() && module.config().noGlobal === true) {
+ // release the global variable
+ globalScope.moment = oldGlobalMoment;
}
return moment;
});
+ makeGlobal(true);
} else {
makeGlobal();
}