My Node8 Lambda
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = | |
/******/ (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__) { | |
// listPosts | |
var co = __webpack_require__(1); | |
var https = __webpack_require__(2); | |
var doT = __webpack_require__(3); | |
var moment = __webpack_require__(6); | |
var _ = __webpack_require__(132); | |
var AWS = __webpack_require__(133); | |
var docClient = new AWS.DynamoDB.DocumentClient(); | |
var s3 = new AWS.S3(); | |
var dynamoObjects = __webpack_require__(134); | |
var get_templates = function(template){ | |
return { | |
main_template: __webpack_require__(166)("./"+template+'/main.html'), | |
header: __webpack_require__(168)("./"+template+'/header.html'), | |
footer: __webpack_require__(170)("./"+template+'/footer.html'), | |
template: __webpack_require__(172)("./"+template+'/list.html') | |
} | |
} | |
exports.handler = (event, context, callback) => { | |
var site_base_url = event.site_base_url; | |
var articles_bucket_path = event.articles_bucket_path; | |
var posts_table = event.posts_table; | |
var objects_table = event.objects_table; | |
var template = event.template; | |
var templates = get_templates(template); | |
co(function *(){ | |
var categories_object = yield dynamoObjects(objects_table, 'categories'); | |
var categories = categories_object.object; | |
var settings_object = yield dynamoObjects(objects_table, 'settings'); | |
var settings = settings_object.object; | |
var posts = yield getBlogPostsFromDB(); | |
var recent_posts = _.clone(posts); | |
for(var i = 0; i < categories.length; i++){ | |
if(!_.find(posts, function(post){return _.includes(post.categories, categories[i].category_id)})){ | |
categories.splice(i, 1); | |
i--; | |
} | |
} | |
var html = doT.template(templates.main_template)({ | |
header: doT.template(templates.header)({ | |
website_title: settings.website_title, | |
header_title: settings.header_title, | |
header_desc: settings.header_desc, | |
site_base_url: site_base_url, | |
categories: categories, | |
template_settings: settings.template, | |
recent_posts: recent_posts, | |
}), | |
content: doT.template(templates.template)({ | |
site_base_url: site_base_url, | |
moment: moment, | |
categories: categories, | |
posts: posts, | |
recent_posts: recent_posts, | |
}), | |
footer: doT.template(templates.footer)({ | |
site_base_url: site_base_url, | |
categories: categories, | |
recent_posts: recent_posts, | |
}), | |
}); | |
callback(null, html); | |
}).catch(onerror); | |
function getBlogPostsFromDB(){ | |
return new Promise(function(resolve, reject){ | |
var params = { | |
TableName: posts_table, | |
IndexName: "post_status-date-index", | |
KeyConditionExpression: "post_status = :post_status AND #date > :date", | |
ExpressionAttributeNames: {"#date": "date"}, | |
ExpressionAttributeValues: { | |
":post_status": "published", | |
":date": 0 | |
}, | |
ScanIndexForward: false | |
}; | |
docClient.query(params, function(err, data) { | |
if (err){ | |
reject(err); | |
}else{ | |
resolve(data.Items); | |
} | |
}); | |
}) | |
} | |
function getBlogPostHtml(post_id){ | |
return new Promise(function(resolve, reject){ | |
https.get(site_base_url+"/"+articles_bucket_path+"/"+post_id+"/index.html", (response) => { | |
var body = []; | |
response.on('data', function(chunk) { | |
body.push(chunk); | |
}).on('end', function() { | |
body = Buffer.concat(body).toString('utf8'); | |
resolve(body); | |
}).on('error', function(err) { | |
reject(err); | |
}); | |
}).on('error', (e) => { | |
console.log(`Got error: ${e.message}`); | |
}); | |
}); | |
} | |
function onerror(err) { | |
console.log("ERROR!"); | |
console.log(err); | |
console.log(arguments); | |
callback(err.message); | |
} | |
} | |
/***/ }, | |
/* 1 */ | |
/***/ function(module, exports) { | |
/** | |
* slice() reference. | |
*/ | |
var slice = Array.prototype.slice; | |
/** | |
* Expose `co`. | |
*/ | |
module.exports = co['default'] = co.co = co; | |
/** | |
* Wrap the given generator `fn` into a | |
* function that returns a promise. | |
* This is a separate function so that | |
* every `co()` call doesn't create a new, | |
* unnecessary closure. | |
* | |
* @param {GeneratorFunction} fn | |
* @return {Function} | |
* @api public | |
*/ | |
co.wrap = function (fn) { | |
createPromise.__generatorFunction__ = fn; | |
return createPromise; | |
function createPromise() { | |
return co.call(this, fn.apply(this, arguments)); | |
} | |
}; | |
/** | |
* Execute the generator function or a generator | |
* and return a promise. | |
* | |
* @param {Function} fn | |
* @return {Promise} | |
* @api public | |
*/ | |
function co(gen) { | |
var ctx = this; | |
var args = slice.call(arguments, 1) | |
// we wrap everything in a promise to avoid promise chaining, | |
// which leads to memory leak errors. | |
// see https://github.com/tj/co/issues/180 | |
return new Promise(function(resolve, reject) { | |
if (typeof gen === 'function') gen = gen.apply(ctx, args); | |
if (!gen || typeof gen.next !== 'function') return resolve(gen); | |
onFulfilled(); | |
/** | |
* @param {Mixed} res | |
* @return {Promise} | |
* @api private | |
*/ | |
function onFulfilled(res) { | |
var ret; | |
try { | |
ret = gen.next(res); | |
} catch (e) { | |
return reject(e); | |
} | |
next(ret); | |
} | |
/** | |
* @param {Error} err | |
* @return {Promise} | |
* @api private | |
*/ | |
function onRejected(err) { | |
var ret; | |
try { | |
ret = gen.throw(err); | |
} catch (e) { | |
return reject(e); | |
} | |
next(ret); | |
} | |
/** | |
* Get the next value in the generator, | |
* return a promise. | |
* | |
* @param {Object} ret | |
* @return {Promise} | |
* @api private | |
*/ | |
function next(ret) { | |
if (ret.done) return resolve(ret.value); | |
var value = toPromise.call(ctx, ret.value); | |
if (value && isPromise(value)) return value.then(onFulfilled, onRejected); | |
return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' | |
+ 'but the following object was passed: "' + String(ret.value) + '"')); | |
} | |
}); | |
} | |
/** | |
* Convert a `yield`ed value into a promise. | |
* | |
* @param {Mixed} obj | |
* @return {Promise} | |
* @api private | |
*/ | |
function toPromise(obj) { | |
if (!obj) return obj; | |
if (isPromise(obj)) return obj; | |
if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj); | |
if ('function' == typeof obj) return thunkToPromise.call(this, obj); | |
if (Array.isArray(obj)) return arrayToPromise.call(this, obj); | |
if (isObject(obj)) return objectToPromise.call(this, obj); | |
return obj; | |
} | |
/** | |
* Convert a thunk to a promise. | |
* | |
* @param {Function} | |
* @return {Promise} | |
* @api private | |
*/ | |
function thunkToPromise(fn) { | |
var ctx = this; | |
return new Promise(function (resolve, reject) { | |
fn.call(ctx, function (err, res) { | |
if (err) return reject(err); | |
if (arguments.length > 2) res = slice.call(arguments, 1); | |
resolve(res); | |
}); | |
}); | |
} | |
/** | |
* Convert an array of "yieldables" to a promise. | |
* Uses `Promise.all()` internally. | |
* | |
* @param {Array} obj | |
* @return {Promise} | |
* @api private | |
*/ | |
function arrayToPromise(obj) { | |
return Promise.all(obj.map(toPromise, this)); | |
} | |
/** | |
* Convert an object of "yieldables" to a promise. | |
* Uses `Promise.all()` internally. | |
* | |
* @param {Object} obj | |
* @return {Promise} | |
* @api private | |
*/ | |
function objectToPromise(obj){ | |
var results = new obj.constructor(); | |
var keys = Object.keys(obj); | |
var promises = []; | |
for (var i = 0; i < keys.length; i++) { | |
var key = keys[i]; | |
var promise = toPromise.call(this, obj[key]); | |
if (promise && isPromise(promise)) defer(promise, key); | |
else results[key] = obj[key]; | |
} | |
return Promise.all(promises).then(function () { | |
return results; | |
}); | |
function defer(promise, key) { | |
// predefine the key in the result | |
results[key] = undefined; | |
promises.push(promise.then(function (res) { | |
results[key] = res; | |
})); | |
} | |
} | |
/** | |
* Check if `obj` is a promise. | |
* | |
* @param {Object} obj | |
* @return {Boolean} | |
* @api private | |
*/ | |
function isPromise(obj) { | |
return 'function' == typeof obj.then; | |
} | |
/** | |
* Check if `obj` is a generator. | |
* | |
* @param {Mixed} obj | |
* @return {Boolean} | |
* @api private | |
*/ | |
function isGenerator(obj) { | |
return 'function' == typeof obj.next && 'function' == typeof obj.throw; | |
} | |
/** | |
* Check if `obj` is a generator function. | |
* | |
* @param {Mixed} obj | |
* @return {Boolean} | |
* @api private | |
*/ | |
function isGeneratorFunction(obj) { | |
var constructor = obj.constructor; | |
if (!constructor) return false; | |
if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true; | |
return isGenerator(constructor.prototype); | |
} | |
/** | |
* Check for plain object. | |
* | |
* @param {Mixed} val | |
* @return {Boolean} | |
* @api private | |
*/ | |
function isObject(val) { | |
return Object == val.constructor; | |
} | |
/***/ }, | |
/* 2 */ | |
/***/ function(module, exports) { | |
module.exports = require("https"); | |
/***/ }, | |
/* 3 */ | |
/***/ function(module, exports, __webpack_require__) { | |
/* doT + auto-compilation of doT templates | |
* | |
* 2012, Laura Doktorova, https://github.com/olado/doT | |
* Licensed under the MIT license | |
* | |
* Compiles .def, .dot, .jst files found under the specified path. | |
* It ignores sub-directories. | |
* Template files can have multiple extensions at the same time. | |
* Files with .def extension can be included in other files via {{#def.name}} | |
* Files with .dot extension are compiled into functions with the same name and | |
* can be accessed as renderer.filename | |
* Files with .jst extension are compiled into .js files. Produced .js file can be | |
* loaded as a commonJS, AMD module, or just installed into a global variable | |
* (default is set to window.render). | |
* All inline defines defined in the .jst file are | |
* compiled into separate functions and are available via _render.filename.definename | |
* | |
* Basic usage: | |
* var dots = require("dot").process({path: "./views"}); | |
* dots.mytemplate({foo:"hello world"}); | |
* | |
* The above snippet will: | |
* 1. Compile all templates in views folder (.dot, .def, .jst) | |
* 2. Place .js files compiled from .jst templates into the same folder. | |
* These files can be used with require, i.e. require("./views/mytemplate"). | |
* 3. Return an object with functions compiled from .dot templates as its properties. | |
* 4. Render mytemplate template. | |
*/ | |
var fs = __webpack_require__(4), | |
doT = module.exports = __webpack_require__(5); | |
doT.process = function(options) { | |
//path, destination, global, rendermodule, templateSettings | |
return new InstallDots(options).compileAll(); | |
}; | |
function InstallDots(o) { | |
this.__path = o.path || "./"; | |
if (this.__path[this.__path.length-1] !== '/') this.__path += '/'; | |
this.__destination = o.destination || this.__path; | |
if (this.__destination[this.__destination.length-1] !== '/') this.__destination += '/'; | |
this.__global = o.global || "window.render"; | |
this.__rendermodule = o.rendermodule || {}; | |
this.__settings = o.templateSettings ? copy(o.templateSettings, copy(doT.templateSettings)) : undefined; | |
this.__includes = {}; | |
} | |
InstallDots.prototype.compileToFile = function(path, template, def) { | |
def = def || {}; | |
var modulename = path.substring(path.lastIndexOf("/")+1, path.lastIndexOf(".")) | |
, defs = copy(this.__includes, copy(def)) | |
, settings = this.__settings || doT.templateSettings | |
, compileoptions = copy(settings) | |
, defaultcompiled = doT.template(template, settings, defs) | |
, exports = [] | |
, compiled = "" | |
, fn; | |
for (var property in defs) { | |
if (defs[property] !== def[property] && defs[property] !== this.__includes[property]) { | |
fn = undefined; | |
if (typeof defs[property] === 'string') { | |
fn = doT.template(defs[property], settings, defs); | |
} else if (typeof defs[property] === 'function') { | |
fn = defs[property]; | |
} else if (defs[property].arg) { | |
compileoptions.varname = defs[property].arg; | |
fn = doT.template(defs[property].text, compileoptions, defs); | |
} | |
if (fn) { | |
compiled += fn.toString().replace('anonymous', property); | |
exports.push(property); | |
} | |
} | |
} | |
compiled += defaultcompiled.toString().replace('anonymous', modulename); | |
fs.writeFileSync(path, "(function(){" + compiled | |
+ "var itself=" + modulename + ", _encodeHTML=(" + doT.encodeHTMLSource.toString() + "(" + (settings.doNotSkipEncoded || '') + "));" | |
+ addexports(exports) | |
+ "if(typeof module!=='undefined' && module.exports) module.exports=itself;else if(typeof define==='function')define(function(){return itself;});else {" | |
+ this.__global + "=" + this.__global + "||{};" + this.__global + "['" + modulename + "']=itself;}}());"); | |
}; | |
function addexports(exports) { | |
var ret = ''; | |
for (var i=0; i< exports.length; i++) { | |
ret += "itself." + exports[i]+ "=" + exports[i]+";"; | |
} | |
return ret; | |
} | |
function copy(o, to) { | |
to = to || {}; | |
for (var property in o) { | |
to[property] = o[property]; | |
} | |
return to; | |
} | |
function readdata(path) { | |
var data = fs.readFileSync(path); | |
if (data) return data.toString(); | |
console.log("problems with " + path); | |
} | |
InstallDots.prototype.compilePath = function(path) { | |
var data = readdata(path); | |
if (data) { | |
return doT.template(data, | |
this.__settings || doT.templateSettings, | |
copy(this.__includes)); | |
} | |
}; | |
InstallDots.prototype.compileAll = function() { | |
if (doT.log) console.log("Compiling all doT templates..."); | |
var defFolder = this.__path, | |
sources = fs.readdirSync(defFolder), | |
k, l, name; | |
for( k = 0, l = sources.length; k < l; k++) { | |
name = sources[k]; | |
if (/\.def(\.dot|\.jst)?$/.test(name)) { | |
if (doT.log) console.log("Loaded def " + name); | |
this.__includes[name.substring(0, name.indexOf('.'))] = readdata(defFolder + name); | |
} | |
} | |
for( k = 0, l = sources.length; k < l; k++) { | |
name = sources[k]; | |
if (/\.dot(\.def|\.jst)?$/.test(name)) { | |
if (doT.log) console.log("Compiling " + name + " to function"); | |
this.__rendermodule[name.substring(0, name.indexOf('.'))] = this.compilePath(defFolder + name); | |
} | |
if (/\.jst(\.dot|\.def)?$/.test(name)) { | |
if (doT.log) console.log("Compiling " + name + " to file"); | |
this.compileToFile(this.__destination + name.substring(0, name.indexOf('.')) + '.js', | |
readdata(defFolder + name)); | |
} | |
} | |
return this.__rendermodule; | |
}; | |
/***/ }, | |
/* 4 */ | |
/***/ function(module, exports) { | |
module.exports = require("fs"); | |
/***/ }, | |
/* 5 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var __WEBPACK_AMD_DEFINE_RESULT__;// doT.js | |
// 2011-2014, Laura Doktorova, https://github.com/olado/doT | |
// Licensed under the MIT license. | |
(function () { | |
"use strict"; | |
var doT = { | |
name: "doT", | |
version: "1.1.1", | |
templateSettings: { | |
evaluate: /\{\{([\s\S]+?(\}?)+)\}\}/g, | |
interpolate: /\{\{=([\s\S]+?)\}\}/g, | |
encode: /\{\{!([\s\S]+?)\}\}/g, | |
use: /\{\{#([\s\S]+?)\}\}/g, | |
useParams: /(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g, | |
define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g, | |
defineParams:/^\s*([\w$]+):([\s\S]+)/, | |
conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g, | |
iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g, | |
varname: "it", | |
strip: true, | |
append: true, | |
selfcontained: false, | |
doNotSkipEncoded: false | |
}, | |
template: undefined, //fn, compile template | |
compile: undefined, //fn, for express | |
log: true | |
}, _globals; | |
doT.encodeHTMLSource = function(doNotSkipEncoded) { | |
var encodeHTMLRules = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'", "/": "/" }, | |
matchHTML = doNotSkipEncoded ? /[&<>"'\/]/g : /&(?!#?\w+;)|<|>|"|'|\//g; | |
return function(code) { | |
return code ? code.toString().replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : ""; | |
}; | |
}; | |
_globals = (function(){ return this || (0,eval)("this"); }()); | |
/* istanbul ignore else */ | |
if (typeof module !== "undefined" && module.exports) { | |
module.exports = doT; | |
} else if (true) { | |
!(__WEBPACK_AMD_DEFINE_RESULT__ = function(){return doT;}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); | |
} else { | |
_globals.doT = doT; | |
} | |
var startend = { | |
append: { start: "'+(", end: ")+'", startencode: "'+encodeHTML(" }, | |
split: { start: "';out+=(", end: ");out+='", startencode: "';out+=encodeHTML(" } | |
}, skip = /$^/; | |
function resolveDefs(c, block, def) { | |
return ((typeof block === "string") ? block : block.toString()) | |
.replace(c.define || skip, function(m, code, assign, value) { | |
if (code.indexOf("def.") === 0) { | |
code = code.substring(4); | |
} | |
if (!(code in def)) { | |
if (assign === ":") { | |
if (c.defineParams) value.replace(c.defineParams, function(m, param, v) { | |
def[code] = {arg: param, text: v}; | |
}); | |
if (!(code in def)) def[code]= value; | |
} else { | |
new Function("def", "def['"+code+"']=" + value)(def); | |
} | |
} | |
return ""; | |
}) | |
.replace(c.use || skip, function(m, code) { | |
if (c.useParams) code = code.replace(c.useParams, function(m, s, d, param) { | |
if (def[d] && def[d].arg && param) { | |
var rw = (d+":"+param).replace(/'|\\/g, "_"); | |
def.__exp = def.__exp || {}; | |
def.__exp[rw] = def[d].text.replace(new RegExp("(^|[^\\w$])" + def[d].arg + "([^\\w$])", "g"), "$1" + param + "$2"); | |
return s + "def.__exp['"+rw+"']"; | |
} | |
}); | |
var v = new Function("def", "return " + code)(def); | |
return v ? resolveDefs(c, v, def) : v; | |
}); | |
} | |
function unescape(code) { | |
return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, " "); | |
} | |
doT.template = function(tmpl, c, def) { | |
c = c || doT.templateSettings; | |
var cse = c.append ? startend.append : startend.split, needhtmlencode, sid = 0, indv, | |
str = (c.use || c.define) ? resolveDefs(c, tmpl, def || {}) : tmpl; | |
str = ("var out='" + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ") | |
.replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""): str) | |
.replace(/'|\\/g, "\\$&") | |
.replace(c.interpolate || skip, function(m, code) { | |
return cse.start + unescape(code) + cse.end; | |
}) | |
.replace(c.encode || skip, function(m, code) { | |
needhtmlencode = true; | |
return cse.startencode + unescape(code) + cse.end; | |
}) | |
.replace(c.conditional || skip, function(m, elsecase, code) { | |
return elsecase ? | |
(code ? "';}else if(" + unescape(code) + "){out+='" : "';}else{out+='") : | |
(code ? "';if(" + unescape(code) + "){out+='" : "';}out+='"); | |
}) | |
.replace(c.iterate || skip, function(m, iterate, vname, iname) { | |
if (!iterate) return "';} } out+='"; | |
sid+=1; indv=iname || "i"+sid; iterate=unescape(iterate); | |
return "';var arr"+sid+"="+iterate+";if(arr"+sid+"){var "+vname+","+indv+"=-1,l"+sid+"=arr"+sid+".length-1;while("+indv+"<l"+sid+"){" | |
+vname+"=arr"+sid+"["+indv+"+=1];out+='"; | |
}) | |
.replace(c.evaluate || skip, function(m, code) { | |
return "';" + unescape(code) + "out+='"; | |
}) | |
+ "';return out;") | |
.replace(/\n/g, "\\n").replace(/\t/g, '\\t').replace(/\r/g, "\\r") | |
.replace(/(\s|;|\}|^|\{)out\+='';/g, '$1').replace(/\+''/g, ""); | |
//.replace(/(\s|;|\}|^|\{)out\+=''\+/g,'$1out+='); | |
if (needhtmlencode) { | |
if (!c.selfcontained && _globals && !_globals._encodeHTML) _globals._encodeHTML = doT.encodeHTMLSource(c.doNotSkipEncoded); | |
str = "var encodeHTML = typeof _encodeHTML !== 'undefined' ? _encodeHTML : (" | |
+ doT.encodeHTMLSource.toString() + "(" + (c.doNotSkipEncoded || '') + "));" | |
+ str; | |
} | |
try { | |
return new Function(c.varname, str); | |
} catch (e) { | |
/* istanbul ignore else */ | |
if (typeof console !== "undefined") console.log("Could not create a template function: " + str); | |
throw e; | |
} | |
}; | |
doT.compile = function(tmpl, def) { | |
return doT.template(tmpl, null, def); | |
}; | |
}()); | |
/***/ }, | |
/* 6 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var require;/* WEBPACK VAR INJECTION */(function(module) {//! moment.js | |
;(function (global, factory) { | |
true ? module.exports = factory() : | |
typeof define === 'function' && define.amd ? define(factory) : | |
global.moment = factory() | |
}(this, (function () { 'use strict'; | |
var hookCallback; | |
function 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 input instanceof Array || Object.prototype.toString.call(input) === '[object Array]'; | |
} | |
function isObject(input) { | |
// IE8 will treat undefined and null as object if it wasn't for | |
// input != null | |
return input != null && Object.prototype.toString.call(input) === '[object Object]'; | |
} | |
function isObjectEmpty(obj) { | |
if (Object.getOwnPropertyNames) { | |
return (Object.getOwnPropertyNames(obj).length === 0); | |
} else { | |
var k; | |
for (k in obj) { | |
if (obj.hasOwnProperty(k)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
} | |
function isUndefined(input) { | |
return input === void 0; | |
} | |
function isNumber(input) { | |
return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]'; | |
} | |
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 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, | |
parsedDateParts : [], | |
meridiem : null, | |
rfc2822 : false, | |
weekdayMismatch : false | |
}; | |
} | |
function getParsingFlags(m) { | |
if (m._pf == null) { | |
m._pf = defaultParsingFlags(); | |
} | |
return m._pf; | |
} | |
var some; | |
if (Array.prototype.some) { | |
some = Array.prototype.some; | |
} else { | |
some = function (fun) { | |
var t = Object(this); | |
var len = t.length >>> 0; | |
for (var i = 0; i < len; i++) { | |
if (i in t && fun.call(this, t[i], i, t)) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
} | |
function isValid(m) { | |
if (m._isValid == null) { | |
var flags = getParsingFlags(m); | |
var parsedParts = some.call(flags.parsedDateParts, function (i) { | |
return i != null; | |
}); | |
var isNowValid = !isNaN(m._d.getTime()) && | |
flags.overflow < 0 && | |
!flags.empty && | |
!flags.invalidMonth && | |
!flags.invalidWeekday && | |
!flags.weekdayMismatch && | |
!flags.nullInput && | |
!flags.invalidFormat && | |
!flags.userInvalidated && | |
(!flags.meridiem || (flags.meridiem && parsedParts)); | |
if (m._strict) { | |
isNowValid = isNowValid && | |
flags.charsLeftOver === 0 && | |
flags.unusedTokens.length === 0 && | |
flags.bigHour === undefined; | |
} | |
if (Object.isFrozen == null || !Object.isFrozen(m)) { | |
m._isValid = isNowValid; | |
} | |
else { | |
return isNowValid; | |
} | |
} | |
return m._isValid; | |
} | |
function createInvalid (flags) { | |
var m = createUTC(NaN); | |
if (flags != null) { | |
extend(getParsingFlags(m), flags); | |
} | |
else { | |
getParsingFlags(m).userInvalidated = true; | |
} | |
return m; | |
} | |
// Plugins that add properties should also add the key here (null value), | |
// so we can properly clone ourselves. | |
var momentProperties = 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 = 0; i < momentProperties.length; i++) { | |
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); | |
if (!this.isValid()) { | |
this._d = new Date(NaN); | |
} | |
// Prevent infinite loop in case updateOffset creates new moment | |
// objects. | |
if (updateInProgress === false) { | |
updateInProgress = true; | |
hooks.updateOffset(this); | |
updateInProgress = false; | |
} | |
} | |
function isMoment (obj) { | |
return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); | |
} | |
function absFloor (number) { | |
if (number < 0) { | |
// -0 -> 0 | |
return Math.ceil(number) || 0; | |
} 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 warn(msg) { | |
if (hooks.suppressDeprecationWarnings === false && | |
(typeof console !== 'undefined') && console.warn) { | |
console.warn('Deprecation warning: ' + msg); | |
} | |
} | |
function deprecate(msg, fn) { | |
var firstTime = true; | |
return extend(function () { | |
if (hooks.deprecationHandler != null) { | |
hooks.deprecationHandler(null, msg); | |
} | |
if (firstTime) { | |
var args = []; | |
var arg; | |
for (var i = 0; i < arguments.length; i++) { | |
arg = ''; | |
if (typeof arguments[i] === 'object') { | |
arg += '\n[' + i + '] '; | |
for (var key in arguments[0]) { | |
arg += key + ': ' + arguments[0][key] + ', '; | |
} | |
arg = arg.slice(0, -2); // Remove trailing comma and space | |
} else { | |
arg = arguments[i]; | |
} | |
args.push(arg); | |
} | |
warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack); | |
firstTime = false; | |
} | |
return fn.apply(this, arguments); | |
}, fn); | |
} | |
var deprecations = {}; | |
function deprecateSimple(name, msg) { | |
if (hooks.deprecationHandler != null) { | |
hooks.deprecationHandler(name, msg); | |
} | |
if (!deprecations[name]) { | |
warn(msg); | |
deprecations[name] = true; | |
} | |
} | |
hooks.suppressDeprecationWarnings = false; | |
hooks.deprecationHandler = null; | |
function isFunction(input) { | |
return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; | |
} | |
function set (config) { | |
var prop, i; | |
for (i in config) { | |
prop = config[i]; | |
if (isFunction(prop)) { | |
this[i] = prop; | |
} else { | |
this['_' + i] = prop; | |
} | |
} | |
this._config = config; | |
// Lenient ordinal parsing accepts just a number in addition to | |
// number + (possibly) stuff coming from _dayOfMonthOrdinalParse. | |
// TODO: Remove "ordinalParse" fallback in next major release. | |
this._dayOfMonthOrdinalParseLenient = new RegExp( | |
(this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + | |
'|' + (/\d{1,2}/).source); | |
} | |
function mergeConfigs(parentConfig, childConfig) { | |
var res = extend({}, parentConfig), prop; | |
for (prop in childConfig) { | |
if (hasOwnProp(childConfig, prop)) { | |
if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) { | |
res[prop] = {}; | |
extend(res[prop], parentConfig[prop]); | |
extend(res[prop], childConfig[prop]); | |
} else if (childConfig[prop] != null) { | |
res[prop] = childConfig[prop]; | |
} else { | |
delete res[prop]; | |
} | |
} | |
} | |
for (prop in parentConfig) { | |
if (hasOwnProp(parentConfig, prop) && | |
!hasOwnProp(childConfig, prop) && | |
isObject(parentConfig[prop])) { | |
// make sure changes to properties don't modify parent config | |
res[prop] = extend({}, res[prop]); | |
} | |
} | |
return res; | |
} | |
function Locale(config) { | |
if (config != null) { | |
this.set(config); | |
} | |
} | |
var keys; | |
if (Object.keys) { | |
keys = Object.keys; | |
} else { | |
keys = function (obj) { | |
var i, res = []; | |
for (i in obj) { | |
if (hasOwnProp(obj, i)) { | |
res.push(i); | |
} | |
} | |
return res; | |
}; | |
} | |
var defaultCalendar = { | |
sameDay : '[Today at] LT', | |
nextDay : '[Tomorrow at] LT', | |
nextWeek : 'dddd [at] LT', | |
lastDay : '[Yesterday at] LT', | |
lastWeek : '[Last] dddd [at] LT', | |
sameElse : 'L' | |
}; | |
function calendar (key, mom, now) { | |
var output = this._calendar[key] || this._calendar['sameElse']; | |
return isFunction(output) ? output.call(mom, now) : output; | |
} | |
var defaultLongDateFormat = { | |
LTS : 'h:mm:ss A', | |
LT : 'h:mm A', | |
L : 'MM/DD/YYYY', | |
LL : 'MMMM D, YYYY', | |
LLL : 'MMMM D, YYYY h:mm A', | |
LLLL : 'dddd, MMMM D, YYYY h:mm A' | |
}; | |
function longDateFormat (key) { | |
var format = this._longDateFormat[key], | |
formatUpper = this._longDateFormat[key.toUpperCase()]; | |
if (format || !formatUpper) { | |
return format; | |
} | |
this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { | |
return val.slice(1); | |
}); | |
return this._longDateFormat[key]; | |
} | |
var defaultInvalidDate = 'Invalid date'; | |
function invalidDate () { | |
return this._invalidDate; | |
} | |
var defaultOrdinal = '%d'; | |
var defaultDayOfMonthOrdinalParse = /\d{1,2}/; | |
function ordinal (number) { | |
return this._ordinal.replace('%d', number); | |
} | |
var defaultRelativeTime = { | |
future : 'in %s', | |
past : '%s ago', | |
s : 'a few seconds', | |
ss : '%d seconds', | |
m : 'a minute', | |
mm : '%d minutes', | |
h : 'an hour', | |
hh : '%d hours', | |
d : 'a day', | |
dd : '%d days', | |
M : 'a month', | |
MM : '%d months', | |
y : 'a year', | |
yy : '%d years' | |
}; | |
function relativeTime (number, withoutSuffix, string, isFuture) { | |
var output = this._relativeTime[string]; | |
return (isFunction(output)) ? | |
output(number, withoutSuffix, string, isFuture) : | |
output.replace(/%d/i, number); | |
} | |
function pastFuture (diff, output) { | |
var format = this._relativeTime[diff > 0 ? 'future' : 'past']; | |
return isFunction(format) ? format(output) : format.replace(/%s/i, output); | |
} | |
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; | |
} | |
var priorities = {}; | |
function addUnitPriority(unit, priority) { | |
priorities[unit] = priority; | |
} | |
function getPrioritizedUnits(unitsObj) { | |
var units = []; | |
for (var u in unitsObj) { | |
units.push({unit: u, priority: priorities[u]}); | |
} | |
units.sort(function (a, b) { | |
return a.priority - b.priority; | |
}); | |
return units; | |
} | |
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?|kk?|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 = '', i; | |
for (i = 0; i < length; i++) { | |
output += isFunction(array[i]) ? 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]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){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 (isNumber(callback)) { | |
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; | |
// FORMATTING | |
addFormatToken('Y', 0, 0, function () { | |
var y = this.year(); | |
return y <= 9999 ? '' + y : '+' + y; | |
}); | |
addFormatToken(0, ['YY', 2], 0, function () { | |
return this.year() % 100; | |
}); | |
addFormatToken(0, ['YYYY', 4], 0, 'year'); | |
addFormatToken(0, ['YYYYY', 5], 0, 'year'); | |
addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); | |
// ALIASES | |
addUnitAlias('year', 'y'); | |
// PRIORITIES | |
addUnitPriority('year', 1); | |
// PARSING | |
addRegexToken('Y', matchSigned); | |
addRegexToken('YY', match1to2, match2); | |
addRegexToken('YYYY', match1to4, match4); | |
addRegexToken('YYYYY', match1to6, match6); | |
addRegexToken('YYYYYY', match1to6, match6); | |
addParseToken(['YYYYY', 'YYYYYY'], YEAR); | |
addParseToken('YYYY', function (input, array) { | |
array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input); | |
}); | |
addParseToken('YY', function (input, array) { | |
array[YEAR] = hooks.parseTwoDigitYear(input); | |
}); | |
addParseToken('Y', function (input, array) { | |
array[YEAR] = parseInt(input, 10); | |
}); | |
// HELPERS | |
function daysInYear(year) { | |
return isLeapYear(year) ? 366 : 365; | |
} | |
function isLeapYear(year) { | |
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; | |
} | |
// HOOKS | |
hooks.parseTwoDigitYear = function (input) { | |
return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); | |
}; | |
// MOMENTS | |
var getSetYear = makeGetSet('FullYear', true); | |
function getIsLeapYear () { | |
return isLeapYear(this.year()); | |
} | |
function makeGetSet (unit, keepTime) { | |
return function (value) { | |
if (value != null) { | |
set$1(this, unit, value); | |
hooks.updateOffset(this, keepTime); | |
return this; | |
} else { | |
return get(this, unit); | |
} | |
}; | |
} | |
function get (mom, unit) { | |
return mom.isValid() ? | |
mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; | |
} | |
function set$1 (mom, unit, value) { | |
if (mom.isValid() && !isNaN(value)) { | |
if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) { | |
mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month())); | |
} | |
else { | |
mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); | |
} | |
} | |
} | |
// MOMENTS | |
function stringGet (units) { | |
units = normalizeUnits(units); | |
if (isFunction(this[units])) { | |
return this[units](); | |
} | |
return this; | |
} | |
function stringSet (units, value) { | |
if (typeof units === 'object') { | |
units = normalizeObjectUnits(units); | |
var prioritized = getPrioritizedUnits(units); | |
for (var i = 0; i < prioritized.length; i++) { | |
this[prioritized[i].unit](units[prioritized[i].unit]); | |
} | |
} else { | |
units = normalizeUnits(units); | |
if (isFunction(this[units])) { | |
return this[units](value); | |
} | |
} | |
return this; | |
} | |
function mod(n, x) { | |
return ((n % x) + x) % x; | |
} | |
var indexOf; | |
if (Array.prototype.indexOf) { | |
indexOf = Array.prototype.indexOf; | |
} else { | |
indexOf = function (o) { | |
// I know | |
var i; | |
for (i = 0; i < this.length; ++i) { | |
if (this[i] === o) { | |
return i; | |
} | |
} | |
return -1; | |
}; | |
} | |
function daysInMonth(year, month) { | |
if (isNaN(year) || isNaN(month)) { | |
return NaN; | |
} | |
var modMonth = mod(month, 12); | |
year += (month - modMonth) / 12; | |
return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2); | |
} | |
// 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'); | |
// PRIORITY | |
addUnitPriority('month', 8); | |
// 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) { | |
if (!m) { | |
return isArray(this._months) ? this._months : | |
this._months['standalone']; | |
} | |
return isArray(this._months) ? this._months[m.month()] : | |
this._months[(this._months.isFormat || 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) { | |
if (!m) { | |
return isArray(this._monthsShort) ? this._monthsShort : | |
this._monthsShort['standalone']; | |
} | |
return isArray(this._monthsShort) ? this._monthsShort[m.month()] : | |
this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; | |
} | |
function handleStrictParse(monthName, format, strict) { | |
var i, ii, mom, llc = monthName.toLocaleLowerCase(); | |
if (!this._monthsParse) { | |
// this is not used | |
this._monthsParse = []; | |
this._longMonthsParse = []; | |
this._shortMonthsParse = []; | |
for (i = 0; i < 12; ++i) { | |
mom = createUTC([2000, i]); | |
this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase(); | |
this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); | |
} | |
} | |
if (strict) { | |
if (format === 'MMM') { | |
ii = indexOf.call(this._shortMonthsParse, llc); | |
return ii !== -1 ? ii : null; | |
} else { | |
ii = indexOf.call(this._longMonthsParse, llc); | |
return ii !== -1 ? ii : null; | |
} | |
} else { | |
if (format === 'MMM') { | |
ii = indexOf.call(this._shortMonthsParse, llc); | |
if (ii !== -1) { | |
return ii; | |
} | |
ii = indexOf.call(this._longMonthsParse, llc); | |
return ii !== -1 ? ii : null; | |
} else { | |
ii = indexOf.call(this._longMonthsParse, llc); | |
if (ii !== -1) { | |
return ii; | |
} | |
ii = indexOf.call(this._shortMonthsParse, llc); | |
return ii !== -1 ? ii : null; | |
} | |
} | |
} | |
function localeMonthsParse (monthName, format, strict) { | |
var i, mom, regex; | |
if (this._monthsParseExact) { | |
return handleStrictParse.call(this, monthName, format, strict); | |
} | |
if (!this._monthsParse) { | |
this._monthsParse = []; | |
this._longMonthsParse = []; | |
this._shortMonthsParse = []; | |
} | |
// TODO: add sorting | |
// Sorting makes sure if one month (or abbr) is a prefix of another | |
// see sorting in computeMonthsParse | |
for (i = 0; i < 12; i++) { | |
// make the regex if we don't have it already | |
mom = 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; | |
} | |
if (typeof value === 'string') { | |
if (/^\d+$/.test(value)) { | |
value = toInt(value); | |
} else { | |
value = mom.localeData().monthsParse(value); | |
// TODO: Another silent failure? | |
if (!isNumber(value)) { | |
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); | |
hooks.updateOffset(this, true); | |
return this; | |
} else { | |
return 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 { | |
if (!hasOwnProp(this, '_monthsShortRegex')) { | |
this._monthsShortRegex = defaultMonthsShortRegex; | |
} | |
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 { | |
if (!hasOwnProp(this, '_monthsRegex')) { | |
this._monthsRegex = defaultMonthsRegex; | |
} | |
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 = 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]); | |
} | |
for (i = 0; i < 24; 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 createDate (y, m, d, h, M, s, ms) { | |
// can't just apply() to create a date: | |
// https://stackoverflow.com/q/181348 | |
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; | |
} | |
function createUTCDate (y) { | |
var date = new Date(Date.UTC.apply(null, arguments)); | |
// the Date.UTC function remaps years 0-99 to 1900-1999 | |
if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) { | |
date.setUTCFullYear(y); | |
} | |
return date; | |
} | |
// start-of-first-week - start-of-year | |
function firstWeekOffset(year, dow, doy) { | |
var // first-week day -- which january is always in the first week (4 for iso, 1 for other) | |
fwd = 7 + dow - doy, | |
// first-week day local weekday -- which local weekday is fwd | |
fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; | |
return -fwdlw + fwd - 1; | |
} | |
// https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday | |
function dayOfYearFromWeeks(year, week, weekday, dow, doy) { | |
var localWeekday = (7 + weekday - dow) % 7, | |
weekOffset = firstWeekOffset(year, dow, doy), | |
dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, | |
resYear, resDayOfYear; | |
if (dayOfYear <= 0) { | |
resYear = year - 1; | |
resDayOfYear = daysInYear(resYear) + dayOfYear; | |
} else if (dayOfYear > daysInYear(year)) { | |
resYear = year + 1; | |
resDayOfYear = dayOfYear - daysInYear(year); | |
} else { | |
resYear = year; | |
resDayOfYear = dayOfYear; | |
} | |
return { | |
year: resYear, | |
dayOfYear: resDayOfYear | |
}; | |
} | |
function weekOfYear(mom, dow, doy) { | |
var weekOffset = firstWeekOffset(mom.year(), dow, doy), | |
week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, | |
resWeek, resYear; | |
if (week < 1) { | |
resYear = mom.year() - 1; | |
resWeek = week + weeksInYear(resYear, dow, doy); | |
} else if (week > weeksInYear(mom.year(), dow, doy)) { | |
resWeek = week - weeksInYear(mom.year(), dow, doy); | |
resYear = mom.year() + 1; | |
} else { | |
resYear = mom.year(); | |
resWeek = week; | |
} | |
return { | |
week: resWeek, | |
year: resYear | |
}; | |
} | |
function weeksInYear(year, dow, doy) { | |
var weekOffset = firstWeekOffset(year, dow, doy), | |
weekOffsetNext = firstWeekOffset(year + 1, dow, doy); | |
return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; | |
} | |
// FORMATTING | |
addFormatToken('w', ['ww', 2], 'wo', 'week'); | |
addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); | |
// ALIASES | |
addUnitAlias('week', 'w'); | |
addUnitAlias('isoWeek', 'W'); | |
// PRIORITIES | |
addUnitPriority('week', 5); | |
addUnitPriority('isoWeek', 5); | |
// PARSING | |
addRegexToken('w', match1to2); | |
addRegexToken('ww', match1to2, match2); | |
addRegexToken('W', match1to2); | |
addRegexToken('WW', match1to2, match2); | |
addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { | |
week[token.substr(0, 1)] = toInt(input); | |
}); | |
// HELPERS | |
// LOCALES | |
function localeWeek (mom) { | |
return weekOfYear(mom, this._week.dow, this._week.doy).week; | |
} | |
var defaultLocaleWeek = { | |
dow : 0, // Sunday is the first day of the week. | |
doy : 6 // The week that contains Jan 1st is the first week of the year. | |
}; | |
function localeFirstDayOfWeek () { | |
return this._week.dow; | |
} | |
function localeFirstDayOfYear () { | |
return this._week.doy; | |
} | |
// MOMENTS | |
function getSetWeek (input) { | |
var week = this.localeData().week(this); | |
return input == null ? week : this.add((input - week) * 7, 'd'); | |
} | |
function getSetISOWeek (input) { | |
var week = weekOfYear(this, 1, 4).week; | |
return input == null ? week : this.add((input - week) * 7, 'd'); | |
} | |
// FORMATTING | |
addFormatToken('d', 0, 'do', 'day'); | |
addFormatToken('dd', 0, 0, function (format) { | |
return this.localeData().weekdaysMin(this, format); | |
}); | |
addFormatToken('ddd', 0, 0, function (format) { | |
return this.localeData().weekdaysShort(this, format); | |
}); | |
addFormatToken('dddd', 0, 0, function (format) { | |
return this.localeData().weekdays(this, format); | |
}); | |
addFormatToken('e', 0, 0, 'weekday'); | |
addFormatToken('E', 0, 0, 'isoWeekday'); | |
// ALIASES | |
addUnitAlias('day', 'd'); | |
addUnitAlias('weekday', 'e'); | |
addUnitAlias('isoWeekday', 'E'); | |
// PRIORITY | |
addUnitPriority('day', 11); | |
addUnitPriority('weekday', 11); | |
addUnitPriority('isoWeekday', 11); | |
// PARSING | |
addRegexToken('d', match1to2); | |
addRegexToken('e', match1to2); | |
addRegexToken('E', match1to2); | |
addRegexToken('dd', function (isStrict, locale) { | |
return locale.weekdaysMinRegex(isStrict); | |
}); | |
addRegexToken('ddd', function (isStrict, locale) { | |
return locale.weekdaysShortRegex(isStrict); | |
}); | |
addRegexToken('dddd', function (isStrict, locale) { | |
return locale.weekdaysRegex(isStrict); | |
}); | |
addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { | |
var weekday = config._locale.weekdaysParse(input, token, config._strict); | |
// if we didn't get a weekday name, mark the date as invalid | |
if (weekday != null) { | |
week.d = weekday; | |
} else { | |
getParsingFlags(config).invalidWeekday = input; | |
} | |
}); | |
addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { | |
week[token] = toInt(input); | |
}); | |
// HELPERS | |
function parseWeekday(input, locale) { | |
if (typeof input !== 'string') { | |
return input; | |
} | |
if (!isNaN(input)) { | |
return parseInt(input, 10); | |
} | |
input = locale.weekdaysParse(input); | |
if (typeof input === 'number') { | |
return input; | |
} | |
return null; | |
} | |
function parseIsoWeekday(input, locale) { | |
if (typeof input === 'string') { | |
return locale.weekdaysParse(input) % 7 || 7; | |
} | |
return isNaN(input) ? null : input; | |
} | |
// LOCALES | |
var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); | |
function localeWeekdays (m, format) { | |
if (!m) { | |
return isArray(this._weekdays) ? this._weekdays : | |
this._weekdays['standalone']; | |
} | |
return isArray(this._weekdays) ? this._weekdays[m.day()] : | |
this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()]; | |
} | |
var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); | |
function localeWeekdaysShort (m) { | |
return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort; | |
} | |
var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); | |
function localeWeekdaysMin (m) { | |
return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin; | |
} | |
function handleStrictParse$1(weekdayName, format, strict) { | |
var i, ii, mom, llc = weekdayName.toLocaleLowerCase(); | |
if (!this._weekdaysParse) { | |
this._weekdaysParse = []; | |
this._shortWeekdaysParse = []; | |
this._minWeekdaysParse = []; | |
for (i = 0; i < 7; ++i) { | |
mom = createUTC([2000, 1]).day(i); | |
this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase(); | |
this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase(); | |
this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); | |
} | |
} | |
if (strict) { | |
if (format === 'dddd') { | |
ii = indexOf.call(this._weekdaysParse, llc); | |
return ii !== -1 ? ii : null; | |
} else if (format === 'ddd') { | |
ii = indexOf.call(this._shortWeekdaysParse, llc); | |
return ii !== -1 ? ii : null; | |
} else { | |
ii = indexOf.call(this._minWeekdaysParse, llc); | |
return ii !== -1 ? ii : null; | |
} | |
} else { | |
if (format === 'dddd') { | |
ii = indexOf.call(this._weekdaysParse, llc); | |
if (ii !== -1) { | |
return ii; | |
} | |
ii = indexOf.call(this._shortWeekdaysParse, llc); | |
if (ii !== -1) { | |
return ii; | |
} | |
ii = indexOf.call(this._minWeekdaysParse, llc); | |
return ii !== -1 ? ii : null; | |
} else if (format === 'ddd') { | |
ii = indexOf.call(this._shortWeekdaysParse, llc); | |
if (ii !== -1) { | |
return ii; | |
} | |
ii = indexOf.call(this._weekdaysParse, llc); | |
if (ii !== -1) { | |
return ii; | |
} | |
ii = indexOf.call(this._minWeekdaysParse, llc); | |
return ii !== -1 ? ii : null; | |
} else { | |
ii = indexOf.call(this._minWeekdaysParse, llc); | |
if (ii !== -1) { | |
return ii; | |
} | |
ii = indexOf.call(this._weekdaysParse, llc); | |
if (ii !== -1) { | |
return ii; | |
} | |
ii = indexOf.call(this._shortWeekdaysParse, llc); | |
return ii !== -1 ? ii : null; | |
} | |
} | |
} | |
function localeWeekdaysParse (weekdayName, format, strict) { | |
var i, mom, regex; | |
if (this._weekdaysParseExact) { | |
return handleStrictParse$1.call(this, weekdayName, format, strict); | |
} | |
if (!this._weekdaysParse) { | |
this._weekdaysParse = []; | |
this._minWeekdaysParse = []; | |
this._shortWeekdaysParse = []; | |
this._fullWeekdaysParse = []; | |
} | |
for (i = 0; i < 7; i++) { | |
// make the regex if we don't have it already | |
mom = createUTC([2000, 1]).day(i); | |
if (strict && !this._fullWeekdaysParse[i]) { | |
this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i'); | |
this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i'); | |
this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i'); | |
} | |
if (!this._weekdaysParse[i]) { | |
regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); | |
this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); | |
} | |
// test the regex | |
if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) { | |
return i; | |
} else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) { | |
return i; | |
} else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) { | |
return i; | |
} else if (!strict && this._weekdaysParse[i].test(weekdayName)) { | |
return i; | |
} | |
} | |
} | |
// MOMENTS | |
function getSetDayOfWeek (input) { | |
if (!this.isValid()) { | |
return input != null ? this : NaN; | |
} | |
var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); | |
if (input != null) { | |
input = parseWeekday(input, this.localeData()); | |
return this.add(input - day, 'd'); | |
} else { | |
return day; | |
} | |
} | |
function getSetLocaleDayOfWeek (input) { | |
if (!this.isValid()) { | |
return input != null ? this : NaN; | |
} | |
var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; | |
return input == null ? weekday : this.add(input - weekday, 'd'); | |
} | |
function getSetISODayOfWeek (input) { | |
if (!this.isValid()) { | |
return input != null ? this : NaN; | |
} | |
// behaves the same as moment#day except | |
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) | |
// as a setter, sunday should belong to the previous week. | |
if (input != null) { | |
var weekday = parseIsoWeekday(input, this.localeData()); | |
return this.day(this.day() % 7 ? weekday : weekday - 7); | |
} else { | |
return this.day() || 7; | |
} | |
} | |
var defaultWeekdaysRegex = matchWord; | |
function weekdaysRegex (isStrict) { | |
if (this._weekdaysParseExact) { | |
if (!hasOwnProp(this, '_weekdaysRegex')) { | |
computeWeekdaysParse.call(this); | |
} | |
if (isStrict) { | |
return this._weekdaysStrictRegex; | |
} else { | |
return this._weekdaysRegex; | |
} | |
} else { | |
if (!hasOwnProp(this, '_weekdaysRegex')) { | |
this._weekdaysRegex = defaultWeekdaysRegex; | |
} | |
return this._weekdaysStrictRegex && isStrict ? | |
this._weekdaysStrictRegex : this._weekdaysRegex; | |
} | |
} | |
var defaultWeekdaysShortRegex = matchWord; | |
function weekdaysShortRegex (isStrict) { | |
if (this._weekdaysParseExact) { | |
if (!hasOwnProp(this, '_weekdaysRegex')) { | |
computeWeekdaysParse.call(this); | |
} | |
if (isStrict) { | |
return this._weekdaysShortStrictRegex; | |
} else { | |
return this._weekdaysShortRegex; | |
} | |
} else { | |
if (!hasOwnProp(this, '_weekdaysShortRegex')) { | |
this._weekdaysShortRegex = defaultWeekdaysShortRegex; | |
} | |
return this._weekdaysShortStrictRegex && isStrict ? | |
this._weekdaysShortStrictRegex : this._weekdaysShortRegex; | |
} | |
} | |
var defaultWeekdaysMinRegex = matchWord; | |
function weekdaysMinRegex (isStrict) { | |
if (this._weekdaysParseExact) { | |
if (!hasOwnProp(this, '_weekdaysRegex')) { | |
computeWeekdaysParse.call(this); | |
} | |
if (isStrict) { | |
return this._weekdaysMinStrictRegex; | |
} else { | |
return this._weekdaysMinRegex; | |
} | |
} else { | |
if (!hasOwnProp(this, '_weekdaysMinRegex')) { | |
this._weekdaysMinRegex = defaultWeekdaysMinRegex; | |
} | |
return this._weekdaysMinStrictRegex && isStrict ? | |
this._weekdaysMinStrictRegex : this._weekdaysMinRegex; | |
} | |
} | |
function computeWeekdaysParse () { | |
function cmpLenRev(a, b) { | |
return b.length - a.length; | |
} | |
var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], | |
i, mom, minp, shortp, longp; | |
for (i = 0; i < 7; i++) { | |
// make the regex if we don't have it already | |
mom = createUTC([2000, 1]).day(i); | |
minp = this.weekdaysMin(mom, ''); | |
shortp = this.weekdaysShort(mom, ''); | |
longp = this.weekdays(mom, ''); | |
minPieces.push(minp); | |
shortPieces.push(shortp); | |
longPieces.push(longp); | |
mixedPieces.push(minp); | |
mixedPieces.push(shortp); | |
mixedPieces.push(longp); | |
} | |
// Sorting makes sure if one weekday (or abbr) is a prefix of another it | |
// will match the longer piece. | |
minPieces.sort(cmpLenRev); | |
shortPieces.sort(cmpLenRev); | |
longPieces.sort(cmpLenRev); | |
mixedPieces.sort(cmpLenRev); | |
for (i = 0; i < 7; i++) { | |
shortPieces[i] = regexEscape(shortPieces[i]); | |
longPieces[i] = regexEscape(longPieces[i]); | |
mixedPieces[i] = regexEscape(mixedPieces[i]); | |
} | |
this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); | |
this._weekdaysShortRegex = this._weekdaysRegex; | |
this._weekdaysMinRegex = this._weekdaysRegex; | |
this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); | |
this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); | |
this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i'); | |
} | |
// FORMATTING | |
function hFormat() { | |
return this.hours() % 12 || 12; | |
} | |
function kFormat() { | |
return this.hours() || 24; | |
} | |
addFormatToken('H', ['HH', 2], 0, 'hour'); | |
addFormatToken('h', ['hh', 2], 0, hFormat); | |
addFormatToken('k', ['kk', 2], 0, kFormat); | |
addFormatToken('hmm', 0, 0, function () { | |
return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); | |
}); | |
addFormatToken('hmmss', 0, 0, function () { | |
return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + | |
zeroFill(this.seconds(), 2); | |
}); | |
addFormatToken('Hmm', 0, 0, function () { | |
return '' + this.hours() + zeroFill(this.minutes(), 2); | |
}); | |
addFormatToken('Hmmss', 0, 0, function () { | |
return '' + this.hours() + zeroFill(this.minutes(), 2) + | |
zeroFill(this.seconds(), 2); | |
}); | |
function meridiem (token, lowercase) { | |
addFormatToken(token, 0, 0, function () { | |
return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); | |
}); | |
} | |
meridiem('a', true); | |
meridiem('A', false); | |
// ALIASES | |
addUnitAlias('hour', 'h'); | |
// PRIORITY | |
addUnitPriority('hour', 13); | |
// PARSING | |
function matchMeridiem (isStrict, locale) { | |
return locale._meridiemParse; | |
} | |
addRegexToken('a', matchMeridiem); | |
addRegexToken('A', matchMeridiem); | |
addRegexToken('H', match1to2); | |
addRegexToken('h', match1to2); | |
addRegexToken('k', match1to2); | |
addRegexToken('HH', match1to2, match2); | |
addRegexToken('hh', match1to2, match2); | |
addRegexToken('kk', match1to2, match2); | |
addRegexToken('hmm', match3to4); | |
addRegexToken('hmmss', match5to6); | |
addRegexToken('Hmm', match3to4); | |
addRegexToken('Hmmss', match5to6); | |
addParseToken(['H', 'HH'], HOUR); | |
addParseToken(['k', 'kk'], function (input, array, config) { | |
var kInput = toInt(input); | |
array[HOUR] = kInput === 24 ? 0 : kInput; | |
}); | |
addParseToken(['a', 'A'], function (input, array, config) { | |
config._isPm = config._locale.isPM(input); | |
config._meridiem = input; | |
}); | |
addParseToken(['h', 'hh'], function (input, array, config) { | |
array[HOUR] = toInt(input); | |
getParsingFlags(config).bigHour = true; | |
}); | |
addParseToken('hmm', function (input, array, config) { | |
var pos = input.length - 2; | |
array[HOUR] = toInt(input.substr(0, pos)); | |
array[MINUTE] = toInt(input.substr(pos)); | |
getParsingFlags(config).bigHour = true; | |
}); | |
addParseToken('hmmss', function (input, array, config) { | |
var pos1 = input.length - 4; | |
var pos2 = input.length - 2; | |
array[HOUR] = toInt(input.substr(0, pos1)); | |
array[MINUTE] = toInt(input.substr(pos1, 2)); | |
array[SECOND] = toInt(input.substr(pos2)); | |
getParsingFlags(config).bigHour = true; | |
}); | |
addParseToken('Hmm', function (input, array, config) { | |
var pos = input.length - 2; | |
array[HOUR] = toInt(input.substr(0, pos)); | |
array[MINUTE] = toInt(input.substr(pos)); | |
}); | |
addParseToken('Hmmss', function (input, array, config) { | |
var pos1 = input.length - 4; | |
var pos2 = input.length - 2; | |
array[HOUR] = toInt(input.substr(0, pos1)); | |
array[MINUTE] = toInt(input.substr(pos1, 2)); | |
array[SECOND] = toInt(input.substr(pos2)); | |
}); | |
// LOCALES | |
function localeIsPM (input) { | |
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays | |
// Using charAt should be more compatible. | |
return ((input + '').toLowerCase().charAt(0) === 'p'); | |
} | |
var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; | |
function localeMeridiem (hours, minutes, isLower) { | |
if (hours > 11) { | |
return isLower ? 'pm' : 'PM'; | |
} else { | |
return isLower ? 'am' : 'AM'; | |
} | |
} | |
// MOMENTS | |
// Setting the hour should keep the time, because the user explicitly | |
// specified which hour they want. So trying to maintain the same hour (in | |
// a new timezone) makes sense. Adding/subtracting hours does not follow | |
// this rule. | |
var getSetHour = makeGetSet('Hours', true); | |
var baseConfig = { | |
calendar: defaultCalendar, | |
longDateFormat: defaultLongDateFormat, | |
invalidDate: defaultInvalidDate, | |
ordinal: defaultOrdinal, | |
dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse, | |
relativeTime: defaultRelativeTime, | |
months: defaultLocaleMonths, | |
monthsShort: defaultLocaleMonthsShort, | |
week: defaultLocaleWeek, | |
weekdays: defaultLocaleWeekdays, | |
weekdaysMin: defaultLocaleWeekdaysMin, | |
weekdaysShort: defaultLocaleWeekdaysShort, | |
meridiemParse: defaultLocaleMeridiemParse | |
}; | |
// internal storage for locale config files | |
var locales = {}; | |
var localeFamilies = {}; | |
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 globalLocale; | |
} | |
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; | |
var aliasedRequire = require; | |
__webpack_require__(8)("./" + name); | |
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 getSetGlobalLocale (key, values) { | |
var data; | |
if (key) { | |
if (isUndefined(values)) { | |
data = getLocale(key); | |
} | |
else { | |
data = defineLocale(key, values); | |
} | |
if (data) { | |
// moment.duration._locale = moment._locale = data; | |
globalLocale = data; | |
} | |
else { | |
if ((typeof console !== 'undefined') && console.warn) { | |
//warn user if arguments are passed but the locale could not be set | |
console.warn('Locale ' + key + ' not found. Did you forget to load it?'); | |
} | |
} | |
} | |
return globalLocale._abbr; | |
} | |
function defineLocale (name, config) { | |
if (config !== null) { | |
var locale, parentConfig = baseConfig; | |
config.abbr = name; | |
if (locales[name] != null) { | |
deprecateSimple('defineLocaleOverride', | |
'use moment.updateLocale(localeName, config) to change ' + | |
'an existing locale. moment.defineLocale(localeName, ' + | |
'config) should only be used for creating a new locale ' + | |
'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'); | |
parentConfig = locales[name]._config; | |
} else if (config.parentLocale != null) { | |
if (locales[config.parentLocale] != null) { | |
parentConfig = locales[config.parentLocale]._config; | |
} else { | |
locale = loadLocale(config.parentLocale); | |
if (locale != null) { | |
parentConfig = locale._config; | |
} else { | |
if (!localeFamilies[config.parentLocale]) { | |
localeFamilies[config.parentLocale] = []; | |
} | |
localeFamilies[config.parentLocale].push({ | |
name: name, | |
config: config | |
}); | |
return null; | |
} | |
} | |
} | |
locales[name] = new Locale(mergeConfigs(parentConfig, config)); | |
if (localeFamilies[name]) { | |
localeFamilies[name].forEach(function (x) { | |
defineLocale(x.name, x.config); | |
}); | |
} | |
// backwards compat for now: also set the locale | |
// make sure we set the locale AFTER all child locales have been | |
// created, so we won't end up with the child locale set. | |
getSetGlobalLocale(name); | |
return locales[name]; | |
} else { | |
// useful for testing | |
delete locales[name]; | |
return null; | |
} | |
} | |
function updateLocale(name, config) { | |
if (config != null) { | |
var locale, tmpLocale, parentConfig = baseConfig; | |
// MERGE | |
tmpLocale = loadLocale(name); | |
if (tmpLocale != null) { | |
parentConfig = tmpLocale._config; | |
} | |
config = mergeConfigs(parentConfig, config); | |
locale = new Locale(config); | |
locale.parentLocale = locales[name]; | |
locales[name] = locale; | |
// backwards compat for now: also set the locale | |
getSetGlobalLocale(name); | |
} else { | |
// pass null for config to unupdate, useful for tests | |
if (locales[name] != null) { | |
if (locales[name].parentLocale != null) { | |
locales[name] = locales[name].parentLocale; | |
} else if (locales[name] != null) { | |
delete locales[name]; | |
} | |
} | |
} | |
return locales[name]; | |
} | |
// returns locale data | |
function 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); | |
} | |
function listLocales() { | |
return keys(locales); | |
} | |
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; | |
} | |
// Pick the first defined of two or three arguments. | |
function defaults(a, b, c) { | |
if (a != null) { | |
return a; | |
} | |
if (b != null) { | |
return b; | |
} | |
return c; | |
} | |
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()]; | |
} | |
// convert an array to a date. | |
// the array should mirror the parameters below | |
// note: all values past the year are optional and will default to the lowest possible value. | |
// [year, month, day , hour, minute, second, millisecond] | |
function configFromArray (config) { | |
var i, date, input = [], currentDate, expectedWeekday, yearToUse; | |
if (config._d) { | |
return; | |
} | |
currentDate = currentDateArray(config); | |
//compute day of the year from weeks and weekdays | |
if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { | |
dayOfYearFromWeekInfo(config); | |
} | |
//if the day of the year is set, figure out what it is | |
if (config._dayOfYear != null) { | |
yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); | |
if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) { | |
getParsingFlags(config)._overflowDayOfYear = true; | |
} | |
date = createUTCDate(yearToUse, 0, config._dayOfYear); | |
config._a[MONTH] = date.getUTCMonth(); | |
config._a[DATE] = date.getUTCDate(); | |
} | |
// Default to current date. | |
// * if no year, month, day of month are given, default to today | |
// * if day of month is given, default month and year | |
// * if month is given, default only year | |
// * if year is given, don't default anything | |
for (i = 0; i < 3 && config._a[i] == null; ++i) { | |
config._a[i] = input[i] = currentDate[i]; | |
} | |
// Zero out whatever was not defaulted, including time | |
for (; i < 7; i++) { | |
config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; | |
} | |
// Check for 24:00:00.000 | |
if (config._a[HOUR] === 24 && | |
config._a[MINUTE] === 0 && | |
config._a[SECOND] === 0 && | |
config._a[MILLISECOND] === 0) { | |
config._nextDay = true; | |
config._a[HOUR] = 0; | |
} | |
config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); | |
expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay(); | |
// 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); | |
} | |
if (config._nextDay) { | |
config._a[HOUR] = 24; | |
} | |
// check for mismatching day of week | |
if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) { | |
getParsingFlags(config).weekdayMismatch = true; | |
} | |
} | |
function dayOfYearFromWeekInfo(config) { | |
var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow; | |
w = config._w; | |
if (w.GG != null || w.W != null || w.E != null) { | |
dow = 1; | |
doy = 4; | |
// TODO: We need to take the current isoWeekYear, but that depends on | |
// how we interpret now (local, utc, fixed offset). So create | |
// a now version of current config (take local/utc/offset flags, and | |
// create now). | |
weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year); | |
week = defaults(w.W, 1); | |
weekday = defaults(w.E, 1); | |
if (weekday < 1 || weekday > 7) { | |
weekdayOverflow = true; | |
} | |
} else { | |
dow = config._locale._week.dow; | |
doy = config._locale._week.doy; | |
var curWeek = weekOfYear(createLocal(), dow, doy); | |
weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); | |
// Default to current week. | |
week = defaults(w.w, curWeek.week); | |
if (w.d != null) { | |
// weekday -- low day numbers are considered next week | |
weekday = w.d; | |
if (weekday < 0 || weekday > 6) { | |
weekdayOverflow = true; | |
} | |
} else if (w.e != null) { | |
// local weekday -- counting starts from begining of week | |
weekday = w.e + dow; | |
if (w.e < 0 || w.e > 6) { | |
weekdayOverflow = true; | |
} | |
} else { | |
// default to begining of week | |
weekday = dow; | |
} | |
} | |
if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { | |
getParsingFlags(config)._overflowWeeks = true; | |
} else if (weekdayOverflow != null) { | |
getParsingFlags(config)._overflowWeekday = true; | |
} else { | |
temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); | |
config._a[YEAR] = temp.year; | |
config._dayOfYear = temp.dayOfYear; | |
} | |
} | |
// 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| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; | |
var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; | |
var isoDates = [ | |
['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], | |
['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], | |
['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], | |
['GGGG-[W]WW', /\d{4}-W\d\d/, false], | |
['YYYY-DDD', /\d{4}-\d{3}/], | |
['YYYY-MM', /\d{4}-\d\d/, false], | |
['YYYYYYMMDD', /[+-]\d{10}/], | |
['YYYYMMDD', /\d{8}/], | |
// YYYYMM is NOT allowed by the standard | |
['GGGG[W]WWE', /\d{4}W\d{3}/], | |
['GGGG[W]WW', /\d{4}W\d{2}/, false], | |
['YYYYDDD', /\d{7}/] | |
]; | |
// iso time formats and regexes | |
var isoTimes = [ | |
['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], | |
['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], | |
['HH:mm:ss', /\d\d:\d\d:\d\d/], | |
['HH:mm', /\d\d:\d\d/], | |
['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], | |
['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], | |
['HHmmss', /\d\d\d\d\d\d/], | |
['HHmm', /\d\d\d\d/], | |
['HH', /\d\d/] | |
]; | |
var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; | |
// date from iso format | |
function configFromISO(config) { | |
var i, l, | |
string = config._i, | |
match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), | |
allowTime, dateFormat, timeFormat, tzFormat; | |
if (match) { | |
getParsingFlags(config).iso = true; | |
for (i = 0, l = isoDates.length; i < l; i++) { | |
if (isoDates[i][1].exec(match[1])) { | |
dateFormat = isoDates[i][0]; | |
allowTime = isoDates[i][2] !== false; | |
break; | |
} | |
} | |
if (dateFormat == null) { | |
config._isValid = false; | |
return; | |
} | |
if (match[3]) { | |
for (i = 0, l = isoTimes.length; i < l; i++) { | |
if (isoTimes[i][1].exec(match[3])) { | |
// match[2] should be 'T' or space | |
timeFormat = (match[2] || ' ') + isoTimes[i][0]; | |
break; | |
} | |
} | |
if (timeFormat == null) { | |
config._isValid = false; | |
return; | |
} | |
} | |
if (!allowTime && timeFormat != null) { | |
config._isValid = false; | |
return; | |
} | |
if (match[4]) { | |
if (tzRegex.exec(match[4])) { | |
tzFormat = 'Z'; | |
} else { | |
config._isValid = false; | |
return; | |
} | |
} | |
config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); | |
configFromStringAndFormat(config); | |
} else { | |
config._isValid = false; | |
} | |
} | |
// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 | |
var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/; | |
function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) { | |
var result = [ | |
untruncateYear(yearStr), | |
defaultLocaleMonthsShort.indexOf(monthStr), | |
parseInt(dayStr, 10), | |
parseInt(hourStr, 10), | |
parseInt(minuteStr, 10) | |
]; | |
if (secondStr) { | |
result.push(parseInt(secondStr, 10)); | |
} | |
return result; | |
} | |
function untruncateYear(yearStr) { | |
var year = parseInt(yearStr, 10); | |
if (year <= 49) { | |
return 2000 + year; | |
} else if (year <= 999) { | |
return 1900 + year; | |
} | |
return year; | |
} | |
function preprocessRFC2822(s) { | |
// Remove comments and folding whitespace and replace multiple-spaces with a single space | |
return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, ''); | |
} | |
function checkWeekday(weekdayStr, parsedInput, config) { | |
if (weekdayStr) { | |
// TODO: Replace the vanilla JS Date object with an indepentent day-of-week check. | |
var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr), | |
weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay(); | |
if (weekdayProvided !== weekdayActual) { | |
getParsingFlags(config).weekdayMismatch = true; | |
config._isValid = false; | |
return false; | |
} | |
} | |
return true; | |
} | |
var obsOffsets = { | |
UT: 0, | |
GMT: 0, | |
EDT: -4 * 60, | |
EST: -5 * 60, | |
CDT: -5 * 60, | |
CST: -6 * 60, | |
MDT: -6 * 60, | |
MST: -7 * 60, | |
PDT: -7 * 60, | |
PST: -8 * 60 | |
}; | |
function calculateOffset(obsOffset, militaryOffset, numOffset) { | |
if (obsOffset) { | |
return obsOffsets[obsOffset]; | |
} else if (militaryOffset) { | |
// the only allowed military tz is Z | |
return 0; | |
} else { | |
var hm = parseInt(numOffset, 10); | |
var m = hm % 100, h = (hm - m) / 100; | |
return h * 60 + m; | |
} | |
} | |
// date and time from ref 2822 format | |
function configFromRFC2822(config) { | |
var match = rfc2822.exec(preprocessRFC2822(config._i)); | |
if (match) { | |
var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]); | |
if (!checkWeekday(match[1], parsedArray, config)) { | |
return; | |
} | |
config._a = parsedArray; | |
config._tzm = calculateOffset(match[8], match[9], match[10]); | |
config._d = createUTCDate.apply(null, config._a); | |
config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); | |
getParsingFlags(config).rfc2822 = true; | |
} else { | |
config._isValid = false; | |
} | |
} | |
// date from iso format or fallback | |
function configFromString(config) { | |
var matched = aspNetJsonRegex.exec(config._i); | |
if (matched !== null) { | |
config._d = new Date(+matched[1]); | |
return; | |
} | |
configFromISO(config); | |
if (config._isValid === false) { | |
delete config._isValid; | |
} else { | |
return; | |
} | |
configFromRFC2822(config); | |
if (config._isValid === false) { | |
delete config._isValid; | |
} else { | |
return; | |
} | |
// Final attempt, use Input Fallback | |
hooks.createFromInputFallback(config); | |
} | |
hooks.createFromInputFallback = deprecate( | |
'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + | |
'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + | |
'discouraged and will be removed in an upcoming major release. Please refer to ' + | |
'http://momentjs.com/guides/#/warnings/js-date/ for more info.', | |
function (config) { | |
config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); | |
} | |
); | |
// constant that refers to the ISO standard | |
hooks.ISO_8601 = function () {}; | |
// constant that refers to the RFC 2822 form | |
hooks.RFC_2822 = function () {}; | |
// date from string and format string | |
function configFromStringAndFormat(config) { | |
// TODO: Move this to another part of the creation flow to prevent circular deps | |
if (config._f === hooks.ISO_8601) { | |
configFromISO(config); | |
return; | |
} | |
if (config._f === hooks.RFC_2822) { | |
configFromRFC2822(config); | |
return; | |
} | |
config._a = []; | |
getParsingFlags(config).empty = true; | |
// This array is used to make a Date, either with `new Date` or `Date.UTC` | |
var string = '' + config._i, | |
i, parsedInput, tokens, token, skipped, | |
stringLength = string.length, | |
totalParsedInputLength = 0; | |
tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; | |
for (i = 0; i < tokens.length; i++) { | |
token = tokens[i]; | |
parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; | |
// console.log('token', token, 'parsedInput', parsedInput, | |
// 'regex', getParseRegexForToken(token, config)); | |
if (parsedInput) { | |
skipped = string.substr(0, string.indexOf(parsedInput)); | |
if (skipped.length > 0) { | |
getParsingFlags(config).unusedInput.push(skipped); | |
} | |
string = string.slice(string.indexOf(parsedInput) + parsedInput.length); | |
totalParsedInputLength += parsedInput.length; | |
} | |
// don't parse if it's not a known token | |
if (formatTokenFunctions[token]) { | |
if (parsedInput) { | |
getParsingFlags(config).empty = false; | |
} | |
else { | |
getParsingFlags(config).unusedTokens.push(token); | |
} | |
addTimeToArrayFromToken(token, parsedInput, config); | |
} | |
else if (config._strict && !parsedInput) { | |
getParsingFlags(config).unusedTokens.push(token); | |
} | |
} | |
// add remaining unparsed input length to the string | |
getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; | |
if (string.length > 0) { | |
getParsingFlags(config).unusedInput.push(string); | |
} | |
// clear _12h flag if hour is <= 12 | |
if (config._a[HOUR] <= 12 && | |
getParsingFlags(config).bigHour === true && | |
config._a[HOUR] > 0) { | |
getParsingFlags(config).bigHour = undefined; | |
} | |
getParsingFlags(config).parsedDateParts = config._a.slice(0); | |
getParsingFlags(config).meridiem = config._meridiem; | |
// handle meridiem | |
config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); | |
configFromArray(config); | |
checkOverflow(config); | |
} | |
function meridiemFixWrap (locale, hour, meridiem) { | |
var isPm; | |
if (meridiem == null) { | |
// nothing to do | |
return hour; | |
} | |
if (locale.meridiemHour != null) { | |
return locale.meridiemHour(hour, meridiem); | |
} else if (locale.isPM != null) { | |
// Fallback | |
isPm = locale.isPM(meridiem); | |
if (isPm && hour < 12) { | |
hour += 12; | |
} | |
if (!isPm && hour === 12) { | |
hour = 0; | |
} | |
return hour; | |
} else { | |
// this is not supposed to happen | |
return hour; | |
} | |
} | |
// date from string and array of format strings | |
function configFromStringAndArray(config) { | |
var tempConfig, | |
bestMoment, | |
scoreToBeat, | |
i, | |
currentScore; | |
if (config._f.length === 0) { | |
getParsingFlags(config).invalidFormat = true; | |
config._d = new Date(NaN); | |
return; | |
} | |
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 (!isValid(tempConfig)) { | |
continue; | |
} | |
// if there is any input that was not parsed add a penalty for that format | |
currentScore += getParsingFlags(tempConfig).charsLeftOver; | |
//or tokens | |
currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; | |
getParsingFlags(tempConfig).score = currentScore; | |
if (scoreToBeat == null || currentScore < scoreToBeat) { | |
scoreToBeat = currentScore; | |
bestMoment = tempConfig; | |
} | |
} | |
extend(config, bestMoment || tempConfig); | |
} | |
function configFromObject(config) { | |
if (config._d) { | |
return; | |
} | |
var i = normalizeObjectUnits(config._i); | |
config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) { | |
return obj && parseInt(obj, 10); | |
}); | |
configFromArray(config); | |
} | |
function createFromConfig (config) { | |
var res = new Moment(checkOverflow(prepareConfig(config))); | |
if (res._nextDay) { | |
// Adding is smart enough around DST | |
res.add(1, 'd'); | |
res._nextDay = undefined; | |
} | |
return res; | |
} | |
function prepareConfig (config) { | |
var input = config._i, | |
format = config._f; | |
config._locale = config._locale || getLocale(config._l); | |
if (input === null || (format === undefined && input === '')) { | |
return createInvalid({nullInput: true}); | |
} | |
if (typeof input === 'string') { | |
config._i = input = config._locale.preparse(input); | |
} | |
if (isMoment(input)) { | |
return new Moment(checkOverflow(input)); | |
} else if (isDate(input)) { | |
config._d = input; | |
} else if (isArray(format)) { | |
configFromStringAndArray(config); | |
} else if (format) { | |
configFromStringAndFormat(config); | |
} else { | |
configFromInput(config); | |
} | |
if (!isValid(config)) { | |
config._d = null; | |
} | |
return config; | |
} | |
function configFromInput(config) { | |
var input = config._i; | |
if (isUndefined(input)) { | |
config._d = new Date(hooks.now()); | |
} else if (isDate(input)) { | |
config._d = new Date(input.valueOf()); | |
} else if (typeof input === 'string') { | |
configFromString(config); | |
} else if (isArray(input)) { | |
config._a = map(input.slice(0), function (obj) { | |
return parseInt(obj, 10); | |
}); | |
configFromArray(config); | |
} else if (isObject(input)) { | |
configFromObject(config); | |
} else if (isNumber(input)) { | |
// from milliseconds | |
config._d = new Date(input); | |
} else { | |
hooks.createFromInputFallback(config); | |
} | |
} | |
function createLocalOrUTC (input, format, locale, strict, isUTC) { | |
var c = {}; | |
if (locale === true || locale === false) { | |
strict = locale; | |
locale = undefined; | |
} | |
if ((isObject(input) && isObjectEmpty(input)) || | |
(isArray(input) && input.length === 0)) { | |
input = 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; | |
return createFromConfig(c); | |
} | |
function createLocal (input, format, locale, strict) { | |
return createLocalOrUTC(input, format, locale, strict, false); | |
} | |
var prototypeMin = deprecate( | |
'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', | |
function () { | |
var other = createLocal.apply(null, arguments); | |
if (this.isValid() && other.isValid()) { | |
return other < this ? this : other; | |
} else { | |
return createInvalid(); | |
} | |
} | |
); | |
var prototypeMax = deprecate( | |
'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', | |
function () { | |
var other = createLocal.apply(null, arguments); | |
if (this.isValid() && other.isValid()) { | |
return other > this ? this : other; | |
} else { | |
return createInvalid(); | |
} | |