UNPKG

react-date-picker

Version:

A carefully crafted date picker for React

1,589 lines (1,299 loc) 506 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("React")); else if(typeof define === 'function' && define.amd) define(["React"], factory); else if(typeof exports === 'object') exports["DatePicker"] = factory(require("React")); else root["DatePicker"] = factory(root["React"]); })(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i];for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } }return target; }; function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; }return arr2; } else { return Array.from(arr); } } var React = __webpack_require__(1); var moment = __webpack_require__(2); var assign = __webpack_require__(101); var asConfig = __webpack_require__(102); var MonthView = __webpack_require__(105); var YearView = __webpack_require__(110); var DecadeView = __webpack_require__(111); var Header = __webpack_require__(112); var toMoment = __webpack_require__(107); var hasOwn = function hasOwn(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); }; var onEnter = __webpack_require__(108); var Views = { month: MonthView, year: YearView, decade: DecadeView }; function emptyFn() {} var DatePicker = React.createClass({ displayName: 'DatePicker', propTypes: { todayText: React.PropTypes.string, gotoSelectedText: React.PropTypes.string, renderFooter: React.PropTypes.func, onChange: React.PropTypes.func, date: React.PropTypes.any, viewDate: React.PropTypes.any }, getViewOrder: function getViewOrder() { return this.props.viewOrder || ['month', 'year', 'decade']; }, getDefaultProps: function getDefaultProps() { var props = assign({}, asConfig(), { highlightWeekends: false, weekNumberName: '', isDatePicker: true, navOnDateClick: true, highlightRangeOnMouseMove: true, defaultStyle: { boxSizing: 'border-box' }, onRangeChange: function onRangeChange() {} }); delete props.viewDate; delete props.date; return props; }, getInitialState: function getInitialState() { return { view: this.props.defaultView, viewDate: this.props.defaultViewDate, defaultDate: this.props.defaultDate, defaultRange: this.props.defaultRange }; }, getViewName: function getViewName() { var view = this.props.view != null ? this.props.view : this.state.view; return view || 'month'; }, addViewIndex: function addViewIndex(amount) { var viewName = this.getViewName(); var order = this.getViewOrder(); var index = order.indexOf(viewName); index += amount; return index % order.length; }, getNextViewName: function getNextViewName() { return this.getViewOrder()[this.addViewIndex(1)]; }, getPrevViewName: function getPrevViewName() { return this.getViewOrder()[this.addViewIndex(-1)]; }, getView: function getView() { var views = this.props.views || Views; return views[this.getViewName()] || views.month; }, getViewFactory: function getViewFactory() { var view = this.getView(); if (React.createFactory && view && view.prototype && typeof view.prototype.render == 'function') { view.__factory = view.__factory || React.createFactory(view); view = view.__factory; } return view; }, getViewDate: function getViewDate() { var date = hasOwn(this.props, 'viewDate') ? this.props.viewDate : this.state.viewDate; date = date || this.viewMoment || this.getDate() || new Date(); if (moment.isMoment(date)) { //in order to strip the locale - the date picker may have had its locale changed //between two render calls. If we don't strip this, moment(mom) returns a new moment //with the locale of mom, which is not what we want date = +date; } date = this.toMoment(date); return date; }, getDate: function getDate() { var date; if (hasOwn(this.props, 'date')) { date = this.props.date; } else { date = this.state.defaultDate; } return date ? this.toMoment(date) : null; }, getRange: function getRange() { var _this = this; var range; if (hasOwn(this.props, 'range')) { range = this.props.range; } else if (this.state.defaultRange) { range = this.state.defaultRange; } if (range) { return range.map(function (r) { return r ? _this.toMoment(r) : null; }) || null; } else { return null; } }, render: function render() { var props = this.p = assign({}, this.props); this.toMoment = function (value, dateFormat) { return toMoment(value, dateFormat || props.dateFormat, { locale: props.locale }); }; var view = this.getViewFactory(); props.date = this.getDate(); props.range = this.getRange(); var dateString = props.date == null ? '' : props.date.format(this.props.dateFormat); props.viewDate = this.viewMoment = this.getViewDate(); props.locale = this.props.locale; props.localeData = moment.localeData(props.locale); props.renderDay = this.props.renderDay; props.onRenderDay = this.props.onRenderDay; // props.onChange = this.handleChange // props.onSelect = this.handleSelect var className = (this.props.className || '') + ' date-picker'; props.style = this.prepareStyle(props); var viewProps = props; var viewProps = asConfig(props); viewProps.toMoment = this.toMoment; viewProps.highlightWeekends = this.props.highlightWeekends; viewProps.weekNumbers = this.props.weekNumbers; viewProps.weekNumberName = this.props.weekNumberName; viewProps.dateString = dateString; viewProps.localeData = props.localeData; viewProps.onSelect = this.handleSelect; viewProps.onChange = this.handleChange; viewProps.onWeekChange = this.props.onWeekChange; viewProps.renderWeekNumber = this.props.renderWeekNumber; viewProps.highlightRangeOnMouseMove = this.props.highlightRangeOnMouseMove; viewProps.range = props.range; return React.createElement('div', _extends({}, this.props, { className: className, style: props.style }), this.renderHeader(view, props), React.createElement('div', { className: 'dp-body', style: { flex: 1 } }, view(viewProps)), this.renderFooter(props)); }, prepareStyle: function prepareStyle(props) { return assign({}, props.defaultStyle, props.style); }, renderFooter: function renderFooter(props) { if (this.props.hideFooter) { return; } if (this.props.today) { console.warn('Please use "todayText" prop instead of "today"!'); } if (this.props.gotoSelected) { console.warn('Please use "gotoSelectedText" prop instead of "gotoSelected"!'); } var todayText = this.props.todayText || 'Today'; var gotoSelectedText = this.props.gotoSelectedText || 'Go to selected'; var footerProps = { todayText: todayText, gotoSelectedText: gotoSelectedText, gotoToday: this.gotoNow, gotoSelected: this.gotoSelected.bind(this, props), date: props.date, viewDate: props.viewDate }; var result; if (typeof this.props.footerFactory == 'function') { result = this.props.footerFactory(footerProps); } if (result !== undefined) { return result; } return React.createElement('div', { className: 'dp-footer' }, React.createElement('div', { tabIndex: '1', role: 'link', className: 'dp-footer-today', onClick: footerProps.gotoToday, onKeyUp: onEnter(footerProps.gotoToday) }, todayText), React.createElement('div', { tabIndex: '1', role: 'link', className: 'dp-footer-selected', onClick: footerProps.gotoSelected, onKeyUp: onEnter(footerProps.gotoSelected) }, gotoSelectedText)); }, gotoNow: function gotoNow() { this.gotoDate(+new Date()); }, gotoSelected: function gotoSelected(props) { this.gotoDate(props.date || +new Date()); }, gotoDate: function gotoDate(value) { this.setView('month'); this.setViewDate(value); }, getViewColspan: function getViewColspan() { var map = { month: 5, year: 2, decade: 2 }; return map[this.getViewName()]; }, renderHeader: function renderHeader(view, props) { if (this.props.hideHeader) { return; } props = props || this.props; var viewDate = this.getViewDate(); var headerText = this.getView().getHeaderText(viewDate, props); var colspan = this.getViewColspan(); var prev = this.props.navPrev; var next = this.props.navNext; return React.createElement(Header, { prevText: prev, nextText: next, colspan: colspan, onPrev: this.handleNavPrev, onNext: this.handleNavNext, onChange: this.handleViewChange }, headerText); }, handleRenderDay: function handleRenderDay(date) { return (this.props.renderDay || emptyFn)(date) || []; }, handleViewChange: function handleViewChange() { this.setView(this.getNextViewName()); }, /** * Use this method to set the view. * * @param {String} view 'month'/'year'/'decade' * * It calls onViewChange, and if the view is uncontrolled, also sets it is state, * so the datepicker gets re-rendered view the new view * */ setView: function setView(view) { if (typeof this.props.onViewChange == 'function') { this.props.onViewChange(view); } if (this.props.view == null) { this.setState({ view: view }); } }, setViewDate: function setViewDate(moment) { moment = this.toMoment(moment); var fn = this.props.onViewDateChange; if (typeof fn == 'function') { var text = moment.format(this.props.dateFormat); var view = this.getViewName(); fn(text, moment, view); } if (!hasOwn(this.props, 'viewDate')) { this.setState({ viewDate: moment }); } }, getNext: function getNext() { var current = this.getViewDate(); var toMoment = this.toMoment; return { month: function month() { return toMoment(current).add(1, 'month'); }, year: function year() { return toMoment(current).add(1, 'year'); }, decade: function decade() { return toMoment(current).add(10, 'year'); } }[this.getViewName()](); }, getPrev: function getPrev() { var current = this.getViewDate(); var toMoment = this.toMoment; return { month: function month() { return toMoment(current).add(-1, 'month'); }, year: function year() { return toMoment(current).add(-1, 'year'); }, decade: function decade() { return toMoment(current).add(-10, 'year'); } }[this.getViewName()](); }, handleNavigation: function handleNavigation(direction, event) { var viewMoment = direction == -1 ? this.getPrev() : this.getNext(); this.setViewDate(viewMoment); if (typeof this.props.onNav === 'function') { var text = viewMoment.format(this.props.dateFormat); var view = this.getViewName(); this.props.onNav(text, viewMoment, view, direction, event); } }, handleNavPrev: function handleNavPrev(event) { this.handleNavigation(-1, event); }, handleNavNext: function handleNavNext(event) { this.handleNavigation(1, event); }, handleChange: function handleChange(date, event) { date = this.toMoment(date); if (this.props.navOnDateClick) { var viewDate = this.toMoment(this.getViewDate()); //it's not enough to compare months, since the year can change as well // //also it's ok to hardcode the format here var viewMonth = viewDate.format('YYYY-MM'); var dateMonth = date.format('YYYY-MM'); if (dateMonth > viewMonth) { this.handleNavNext(event); } else if (dateMonth < viewMonth) { this.handleNavPrev(event); } } var text = date.format(this.props.dateFormat); if (!hasOwn(this.props, 'date')) { this.setState({ defaultDate: text }); } ;(this.props.onChange || emptyFn)(text, date, event); if (this.p.range) { this.handleRangeChange(date, event); } }, handleRangeChange: function handleRangeChange(mom) { var _this2 = this; var range = this.p.range; if (range.length < 2) { range = [].concat(_toConsumableArray(range), [mom]); } else { range = [mom]; } range.sort(function (a, b) { return a - b; }); if (!this.props.range) { this.setState({ defaultRange: range }); } var rangeText = range.map(function (date) { return date.format(_this2.props.dateFormat); }); this.props.onRangeChange(rangeText, range, event); }, handleSelect: function handleSelect(date, event) { var viewName = this.getViewName(); var property = { decade: 'year', year: 'month' }[viewName]; var value = date.get(property); var viewMoment = this.toMoment(this.getViewDate()).set(property, value); var view = this.getPrevViewName(); this.setViewDate(viewMoment); this.setView(view); if (typeof this.props.onSelect === 'function') { var text = viewMoment.format(this.props.dateFormat); this.props.onSelect(text, viewMoment, view, event); } } }); DatePicker.views = Views; var PT = React.PropTypes; DatePicker.propTypes = { highlightWeekends: PT.bool, /** * Function to be called when user selects a date. * * Called with the following params: * * @param {String} dateText Date formatted as string * @param {Moment} moment Moment.js instance * @param {Event} event * * @type {Function} */ onChange: PT.func, /** * Function to be called when the user navigates to the next/prev month/year/decade * * Called with the following params: * * @param {String} dateText Date formatted as string * @param {Moment} moment Moment.js instance * @param {String} view The name of the current view (eg: "month") * @param {Number} direction 1 or -1. 1 if the right arrow, to nav to next period was pressed. -1 if the left arrow, to nav to the prev period was pressed. * @param {Event} event * * @type {Function} */ onNav: PT.func, /** * Function to be called when the user selects a year/month. * * Called with the following params: * * @param {String} dateText Date formatted as string * @param {Moment} moment Moment.js instance * @param {String} view The name of the view displayed after following the selection. For now, either "year" or "month" * * @type {Function} */ onSelect: PT.func, /** * A function that should return a React DOM for the day cell. The first param is the props object. * You can use this to have full control over what gets rendered for a day. * * @param {Object} dayProps The props object passed to day rendering * * @type {Function} */ renderDay: PT.func, /** * A function that can manipulate the props object for a day, and SHOULD return a props object (a new one, or the same). * Use this for CUSTOM DAY STYLING. * You can use this to take full control over the styles/css classes/attributes applied to the day cell in the month view. * * @param {Object} dayProps * @return {Object} dayProps * * @type {Function} */ onRenderDay: PT.func, /******************************************/ /********** VIEW-related props ************/ /******************************************/ /** * The default view to show in the picker. This is an uncontrolled prop. * If none specified, the default view will be "month" * * @type {String} */ defaultView: PT.string, /** * The view to show in the picker. This is a CONTROLLED prop! * * When using this controlled prop, make sure you update it when `onViewChange` function is called * if you want to navigate to another view, as expected. * * @type {String} */ view: PT.string, /** * A function to be called when navigating to another view date. * * Called with the following params: * * @param {String} dateText Date formatted as string * @param {Moment} moment Moment.js instance * @param {String} view the name of the view displayed after the navigation occurs. * * @type {Function} */ onViewDateChange: PT.func, /** * A function to be called when the view is changed. * If you're using the controlled `view` prop, make sure you update the `view` prop in this function if you want to navigate to another view, as expected. * * @param {String} nextView One of "month", "year", "decade" * * @type {Function} */ onViewChange: PT.func, /** * Defaults to true. If specified as false, will not navigate to the date that was clicked, even if that date is in the prev/next month * @type {Boolean} */ navOnDateClick: PT.bool, highlightRangeOnMouseMove: PT.bool }; module.exports = DatePicker; /***/ }, /* 1 */ /***/ function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE_1__; /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module) {//! moment.js //! version : 2.11.2 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors //! license : MIT //! momentjs.com ;(function (global, factory) { true ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.moment = factory() }(this, function () { 'use strict'; var hookCallback; function utils_hooks__hooks () { return hookCallback.apply(null, arguments); } // This is done to register the method called with moment() // without creating circular dependencies. function setHookCallback (callback) { hookCallback = callback; } function isArray(input) { return Object.prototype.toString.call(input) === '[object Array]'; } function isDate(input) { return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; } function map(arr, fn) { var res = [], i; for (i = 0; i < arr.length; ++i) { res.push(fn(arr[i], i)); } return res; } function hasOwnProp(a, b) { return Object.prototype.hasOwnProperty.call(a, b); } function extend(a, b) { for (var i in b) { if (hasOwnProp(b, i)) { a[i] = b[i]; } } if (hasOwnProp(b, 'toString')) { a.toString = b.toString; } if (hasOwnProp(b, 'valueOf')) { a.valueOf = b.valueOf; } return a; } function create_utc__createUTC (input, format, locale, strict) { return createLocalOrUTC(input, format, locale, strict, true).utc(); } function defaultParsingFlags() { // We need to deep clone this object. return { empty : false, unusedTokens : [], unusedInput : [], overflow : -2, charsLeftOver : 0, nullInput : false, invalidMonth : null, invalidFormat : false, userInvalidated : false, iso : false }; } function getParsingFlags(m) { if (m._pf == null) { m._pf = defaultParsingFlags(); } return m._pf; } function valid__isValid(m) { if (m._isValid == null) { var flags = getParsingFlags(m); m._isValid = !isNaN(m._d.getTime()) && flags.overflow < 0 && !flags.empty && !flags.invalidMonth && !flags.invalidWeekday && !flags.nullInput && !flags.invalidFormat && !flags.userInvalidated; if (m._strict) { m._isValid = m._isValid && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0 && flags.bigHour === undefined; } } return m._isValid; } function valid__createInvalid (flags) { var m = create_utc__createUTC(NaN); if (flags != null) { extend(getParsingFlags(m), flags); } else { getParsingFlags(m).userInvalidated = true; } return m; } function isUndefined(input) { return input === void 0; } // Plugins that add properties should also add the key here (null value), // so we can properly clone ourselves. var momentProperties = utils_hooks__hooks.momentProperties = []; function copyConfig(to, from) { var i, prop, val; if (!isUndefined(from._isAMomentObject)) { to._isAMomentObject = from._isAMomentObject; } if (!isUndefined(from._i)) { to._i = from._i; } if (!isUndefined(from._f)) { to._f = from._f; } if (!isUndefined(from._l)) { to._l = from._l; } if (!isUndefined(from._strict)) { to._strict = from._strict; } 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._pf)) { to._pf = getParsingFlags(from); } 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; } } } return to; } var updateInProgress = false; // Moment prototype object 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; utils_hooks__hooks.updateOffset(this); updateInProgress = false; } } function isMoment (obj) { return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); } function absFloor (number) { if (number < 0) { return Math.ceil(number); } else { return Math.floor(number); } } function toInt(argumentForCoercion) { var coercedNumber = +argumentForCoercion, value = 0; if (coercedNumber !== 0 && isFinite(coercedNumber)) { value = absFloor(coercedNumber); } return value; } // compare two arrays, return the number of differences function compareArrays(array1, array2, dontConvert) { var len = Math.min(array1.length, array2.length), lengthDiff = Math.abs(array1.length - array2.length), diffs = 0, i; for (i = 0; i < len; i++) { if ((dontConvert && array1[i] !== array2[i]) || (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { diffs++; } } return diffs + lengthDiff; } function Locale() { } // internal storage for locale config files var locales = {}; var globalLocale; function normalizeLocale(key) { return key ? key.toLowerCase().replace('_', '-') : key; } // pick the locale from the array // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root function chooseLocale(names) { var i = 0, j, next, locale, split; while (i < names.length) { split = normalizeLocale(names[i]).split('-'); j = split.length; next = normalizeLocale(names[i + 1]); next = next ? next.split('-') : null; while (j > 0) { locale = loadLocale(split.slice(0, j).join('-')); if (locale) { return locale; } if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { //the next array item is better than a shallower substring of this one break; } j--; } i++; } return null; } function loadLocale(name) { var oldLocale = null; // TODO: Find a better way to register and load all the locales in Node if (!locales[name] && (typeof module !== 'undefined') && module && module.exports) { try { oldLocale = globalLocale._abbr; __webpack_require__(4)("./" + name); // because defineLocale currently also sets the global locale, we // want to undo that for lazy loaded locales locale_locales__getSetGlobalLocale(oldLocale); } catch (e) { } } return locales[name]; } // This function will load locale and then set the global locale. If // no arguments are passed in, it will simply return the current global // locale key. function locale_locales__getSetGlobalLocale (key, values) { var data; if (key) { if (isUndefined(values)) { data = locale_locales__getLocale(key); } else { data = defineLocale(key, values); } if (data) { // moment.duration._locale = moment._locale = data; globalLocale = data; } } return globalLocale._abbr; } function defineLocale (name, values) { if (values !== null) { values.abbr = name; locales[name] = locales[name] || new Locale(); locales[name].set(values); // backwards compat for now: also set the locale locale_locales__getSetGlobalLocale(name); return locales[name]; } else { // useful for testing delete locales[name]; return null; } } // returns locale data function locale_locales__getLocale (key) { var locale; if (key && key._locale && key._locale._abbr) { key = key._locale._abbr; } if (!key) { return globalLocale; } if (!isArray(key)) { //short-circuit everything else locale = loadLocale(key); if (locale) { return locale; } key = [key]; } return chooseLocale(key); } var aliases = {}; function addUnitAlias (unit, shorthand) { var lowerCase = unit.toLowerCase(); aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; } function normalizeUnits(units) { return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; } function normalizeObjectUnits(inputObject) { var normalizedInput = {}, normalizedProp, prop; for (prop in inputObject) { if (hasOwnProp(inputObject, prop)) { normalizedProp = normalizeUnits(prop); if (normalizedProp) { normalizedInput[normalizedProp] = inputObject[prop]; } } } return normalizedInput; } function isFunction(input) { return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; } function makeGetSet (unit, keepTime) { return function (value) { if (value != null) { get_set__set(this, unit, value); utils_hooks__hooks.updateOffset(this, keepTime); return this; } else { return get_set__get(this, unit); } }; } function get_set__get (mom, unit) { return mom.isValid() ? mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; } function get_set__set (mom, unit, value) { if (mom.isValid()) { mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); } } // MOMENTS function getSet (units, value) { var unit; if (typeof units === 'object') { for (unit in units) { this.set(unit, units[unit]); } } else { units = normalizeUnits(units); if (isFunction(this[units])) { return this[units](value); } } return this; } function zeroFill(number, targetLength, forceSign) { var absNumber = '' + Math.abs(number), zerosToFill = targetLength - absNumber.length, sign = number >= 0; return (sign ? (forceSign ? '+' : '') : '-') + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; } var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; var formatFunctions = {}; var formatTokenFunctions = {}; // token: 'M' // padded: ['MM', 2] // ordinal: 'Mo' // callback: function () { this.month() + 1 } function addFormatToken (token, padded, ordinal, callback) { var func = callback; if (typeof callback === 'string') { func = function () { return this[callback](); }; } if (token) { formatTokenFunctions[token] = func; } if (padded) { formatTokenFunctions[padded[0]] = function () { return zeroFill(func.apply(this, arguments), padded[1], padded[2]); }; } if (ordinal) { formatTokenFunctions[ordinal] = function () { return this.localeData().ordinal(func.apply(this, arguments), token); }; } } function removeFormattingTokens(input) { if (input.match(/\[[\s\S]/)) { return input.replace(/^\[|\]$/g, ''); } return input.replace(/\\/g, ''); } function makeFormatFunction(format) { var array = format.match(formattingTokens), i, length; for (i = 0, length = array.length; i < length; i++) { if (formatTokenFunctions[array[i]]) { array[i] = formatTokenFunctions[array[i]]; } else { array[i] = removeFormattingTokens(array[i]); } } return function (mom) { var output = ''; for (i = 0; i < length; i++) { output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; } return output; }; } // format date using native date object function formatMoment(m, format) { if (!m.isValid()) { return m.localeData().invalidDate(); } format = expandFormat(format, m.localeData()); formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); return formatFunctions[format](m); } function expandFormat(format, locale) { var i = 5; function replaceLongDateFormatTokens(input) { return locale.longDateFormat(input) || input; } localFormattingTokens.lastIndex = 0; while (i >= 0 && localFormattingTokens.test(format)) { format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); localFormattingTokens.lastIndex = 0; i -= 1; } return format; } var match1 = /\d/; // 0 - 9 var match2 = /\d\d/; // 00 - 99 var match3 = /\d{3}/; // 000 - 999 var match4 = /\d{4}/; // 0000 - 9999 var match6 = /[+-]?\d{6}/; // -999999 - 999999 var match1to2 = /\d\d?/; // 0 - 99 var match3to4 = /\d\d\d\d?/; // 999 - 9999 var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 var match1to3 = /\d{1,3}/; // 0 - 999 var match1to4 = /\d{1,4}/; // 0 - 9999 var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 var matchUnsigned = /\d+/; // 0 - inf var matchSigned = /[+-]?\d+/; // -inf - inf var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 // any word (or two) characters or numbers including two/three word month in arabic. // includes scottish gaelic two word and hyphenated months var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; var regexes = {}; function addRegexToken (token, regex, strictRegex) { regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { return (isStrict && strictRegex) ? strictRegex : regex; }; } function getParseRegexForToken (token, config) { if (!hasOwnProp(regexes, token)) { return new RegExp(unescapeFormat(token)); } return regexes[token](config._strict, config._locale); } // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript function unescapeFormat(s) { return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { return p1 || p2 || p3 || p4; })); } function regexEscape(s) { return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); } var tokens = {}; function addParseToken (token, callback) { var i, func = callback; if (typeof token === 'string') { token = [token]; } if (typeof callback === 'number') { func = function (input, array) { array[callback] = toInt(input); }; } for (i = 0; i < token.length; i++) { tokens[token[i]] = func; } } function addWeekParseToken (token, callback) { addParseToken(token, function (input, array, config, token) { config._w = config._w || {}; callback(input, config._w, config, token); }); } function addTimeToArrayFromToken(token, input, config) { if (input != null && hasOwnProp(tokens, token)) { tokens[token](input, config._a, config, token); } } var YEAR = 0; var MONTH = 1; var DATE = 2; var HOUR = 3; var MINUTE = 4; var SECOND = 5; var MILLISECOND = 6; var WEEK = 7; var WEEKDAY = 8; function daysInMonth(year, month) { return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); } // FORMATTING addFormatToken('M', ['MM', 2], 'Mo', function () { return this.month() + 1; }); addFormatToken('MMM', 0, 0, function (format) { return this.localeData().monthsShort(this, format); }); addFormatToken('MMMM', 0, 0, function (format) { return this.localeData().months(this, format); }); // ALIASES addUnitAlias('month', 'M'); // PARSING addRegexToken('M', match1to2); addRegexToken('MM', match1to2, match2); addRegexToken('MMM', function (isStrict, locale) { return locale.monthsShortRegex(isStrict); }); addRegexToken('MMMM', function (isStrict, locale) { return locale.monthsRegex(isStrict); }); addParseToken(['M', 'MM'], function (input, array) { array[MONTH] = toInt(input) - 1; }); addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { var month = config._locale.monthsParse(input, token, config._strict); // if we didn't find a month name, mark the date as invalid. if (month != null) { array[MONTH] = month; } else { getParsingFlags(config).invalidMonth = input; } }); // LOCALES var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/; var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); function localeMonths (m, format) { return isArray(this._months) ? this._months[m.month()] : this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; } var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); function localeMonthsShort (m, format) { return isArray(this._monthsShort) ? this._monthsShort[m.month()] : this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; } function localeMonthsParse (monthName, format, strict) { var i, mom, regex; if (!this._monthsParse) { this._monthsParse = []; this._longMonthsParse = []; this._shortMonthsParse = []; } for (i = 0; i < 12; i++) { // make the regex if we don't have it already mom = create_utc__createUTC([2000, i]); if (strict && !this._longMonthsParse[i]) { this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); } if (!strict && !this._monthsParse[i]) { regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); } // test the regex if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { return i; } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { return i; } else if (!strict && this._monthsParse[i].test(monthName)) { return i; } } } // MOMENTS function setMonth (mom, value) { var dayOfMonth; if (!mom.isValid()) { // No op return mom; } // TODO: Move this out of here! if (typeof value === 'string') { value = mom.localeData().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 getSetMonth (value) { if (value != null) { setMonth(this, value); utils_hooks__hooks.updateOffset(this, true); return this; } else { return get_set__get(this, 'Month'); } } function getDaysInMonth () { return daysInMonth(this.year(), this.month()); } var defaultMonthsShortRegex = matchWord; function monthsShortRegex (isStrict) { if (this._monthsParseExact) { if (!hasOwnProp(this, '_monthsRegex')) { computeMonthsParse.call(this); } if (isStrict) { return this._monthsShortStrictRegex; } else { return this._monthsShortRegex; } } else { return this._monthsShortStrictRegex && isStrict ? this._monthsShortStrictRegex : this._monthsShortRegex; } } var defaultMonthsRegex = matchWord; function monthsRegex (isStrict) { if (this._monthsParseExact) { if (!hasOwnProp(this, '_monthsRegex')) { computeMonthsParse.call(this); } if (isStrict) { return this._monthsStrictRegex; } else { return this._monthsRegex; } } else { return this._monthsStrictRegex && isStrict ? this._monthsStrictRegex : this._monthsRegex; } } function computeMonthsParse () { function cmpLenRev(a, b) { return b.length - a.length; } var shortPieces = [], longPieces = [], mixedPieces = [], i, mom; for (i = 0; i < 12; i++) { // make the regex if we don't have it already mom = create_utc__createUTC([2000, i]); shortPieces.push(this.monthsShort(mom, '')); longPieces.push(this.months(mom, '')); mixedPieces.push(this.months(mom, '')); mixedPieces.push(this.monthsShort(mom, '')); } // Sorting makes sure if one month (or abbr) is a prefix of another it // will match the longer piece. shortPieces.sort(cmpLenRev); longPieces.sort(cmpLenRev); mixedPieces.sort(cmpLenRev); for (i = 0; i < 12; i++) { shortPieces[i] = regexEscape(shortPieces[i]); longPieces[i] = regexEscape(longPieces[i]); mixedPieces[i] = regexEscape(mixedPieces[i]); } this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); this._monthsShortRegex = this._monthsRegex; this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')$', 'i'); this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')$', 'i'); } function checkOverflow (m) { var overflow; var a = m._a; if (a && getParsingFlags(m).overflow === -2) { overflow = a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : -1; if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { overflow = DATE; } if (getParsingFlags(m)._overflowWeeks && overflow === -1) { overflow = WEEK; } if (getParsingFlags(m)._overflowWeekday && overflow === -1) { overflow = WEEKDAY; } getParsingFlags(m).overflow = overflow; } return m; } function warn(msg) { if (utils_hooks__hooks.suppressDeprecationWarnings === false && (typeof console !== 'undefined') && console.warn) { console.warn('Deprecation warning: ' + msg); } } function deprecate(msg, fn) { var firstTime = true; return extend(function () { if (firstTime) { warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack); firstTime = false; } return fn.apply(this, arguments); }, fn); } var deprecations = {}; function deprecateSimple(name, msg) { if (!deprecations[name]) { warn(msg); deprecations[name] = true; } } utils_hooks__hooks.suppressDeprecationWarnings = false; // iso 8601 regex // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/; var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )