├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── dist ├── vue-moment.cjs.js ├── vue-moment.es.js ├── vue-moment.js ├── vue-moment.min.js └── vue-moment.min.js.map ├── package.json ├── readme.md ├── tests ├── .eslintrc └── vue-moment.spec.js ├── vue-moment.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }] 4 | ], 5 | "env": { 6 | "test": { 7 | "presets": [ 8 | ["env", { "targets": { "node": "current" }}] 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | end_of_line = lf 10 | max_line_length = null 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb", 3 | "parser": "babel-eslint", 4 | "rules": { 5 | "no-param-reassign": 0, 6 | "prefer-rest-params": 0, 7 | "no-plusplus": 0, 8 | "prefer-destructuring": 0, 9 | "no-shadow": 0, 10 | "no-console": 0, 11 | "global-require": 0 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | before_install: 5 | - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.27.5 6 | - export PATH="$HOME/.yarn/bin:$PATH" 7 | cache: yarn 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Brock Petrie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dist/vue-moment.cjs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { 4 | return typeof obj; 5 | } : function (obj) { 6 | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 7 | }; 8 | 9 | function _toConsumableArray(arr) { 10 | if (Array.isArray(arr)) { 11 | for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { 12 | arr2[i] = arr[i]; 13 | }return arr2; 14 | } else { 15 | return Array.from(arr); 16 | } 17 | } 18 | 19 | module.exports = { 20 | install: function install(Vue, options) { 21 | var moment = options && options.moment ? options.moment : require('moment'); 22 | 23 | Object.defineProperties(Vue.prototype, { 24 | $moment: { 25 | get: function get() { 26 | return moment; 27 | } 28 | } 29 | }); 30 | 31 | Vue.moment = moment; 32 | 33 | Vue.filter('moment', function () { 34 | var arguments$1 = arguments; 35 | 36 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 37 | args[_key] = arguments$1[_key]; 38 | } 39 | 40 | args = Array.prototype.slice.call(args); 41 | var input = args.shift(); 42 | var date = void 0; 43 | 44 | if (Array.isArray(input) && typeof input[0] === 'string') { 45 | // If input is array, assume we're being passed a format pattern to parse against. 46 | // Format pattern will accept an array of potential formats to parse against. 47 | // Date string should be at [0], format pattern(s) should be at [1] 48 | date = moment(input[0], input[1], true); 49 | } else if (typeof input === 'number') { 50 | if (input.toString().length < 12) { 51 | // If input is an integer with fewer than 12 digits, assume Unix seconds... 52 | date = moment.unix(input); 53 | } else { 54 | // ..otherwise, assume milliseconds. 55 | date = moment(input); 56 | } 57 | } else { 58 | // Otherwise, throw the input at moment and see what happens... 59 | date = moment(input); 60 | } 61 | 62 | if (!input || !date.isValid()) { 63 | // Log a warning if moment couldn't reconcile the input. Better than throwing an error? 64 | console.warn('Could not build a valid `moment` object from input.'); 65 | return input; 66 | } 67 | 68 | function parse() { 69 | var arguments$1 = arguments; 70 | 71 | for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 72 | args[_key2] = arguments$1[_key2]; 73 | } 74 | 75 | args = Array.prototype.slice.call(args); 76 | var method = args.shift(); 77 | 78 | switch (method) { 79 | case 'add': 80 | { 81 | /* 82 | * Mutates the original moment by adding time. 83 | * http://momentjs.com/docs/#/manipulating/add/ 84 | */ 85 | 86 | var addends = args.shift().split(',').map(Function.prototype.call, String.prototype.trim); 87 | var obj = {}; 88 | 89 | for (var n = 0; n < addends.length; n++) { 90 | var addend = addends[n].split(' '); 91 | obj[addend[1]] = addend[0]; 92 | } 93 | date.add(obj); 94 | break; 95 | } 96 | 97 | case 'subtract': 98 | { 99 | /* 100 | * Mutates the original moment by subtracting time. 101 | * http://momentjs.com/docs/#/manipulating/subtract/ 102 | */ 103 | 104 | var subtrahends = args.shift().split(',').map(Function.prototype.call, String.prototype.trim); 105 | var _obj = {}; 106 | 107 | for (var _n = 0; _n < subtrahends.length; _n++) { 108 | var subtrahend = subtrahends[_n].split(' '); 109 | _obj[subtrahend[1]] = subtrahend[0]; 110 | } 111 | date.subtract(_obj); 112 | break; 113 | } 114 | 115 | case 'from': 116 | { 117 | /* 118 | * Display a moment in relative time, either from now or from a specified date. 119 | * http://momentjs.com/docs/#/displaying/fromnow/ 120 | */ 121 | 122 | var from = 'now'; 123 | var removeSuffix = false; 124 | 125 | if (args[0] === 'now') { args.shift(); } 126 | // If valid, assume it is a date we want the output computed against. 127 | if (moment(args[0]).isValid()) { from = moment(args.shift()); } 128 | 129 | if (args[0] === true) { 130 | args.shift(); 131 | removeSuffix = true; 132 | } 133 | 134 | if (from !== 'now') { 135 | date = date.from(from, removeSuffix); 136 | } else { 137 | date = date.fromNow(removeSuffix); 138 | } 139 | break; 140 | } 141 | 142 | case 'diff': 143 | { 144 | /* 145 | * Mutates the original moment by doing a difference with another date. 146 | * http://momentjs.com/docs/#/displaying/difference/ 147 | */ 148 | 149 | var referenceTime = moment(); 150 | var units = ''; 151 | var float = false; 152 | 153 | if (moment(args[0]).isValid()) { 154 | // If valid, assume it is a date we want the output computed against. 155 | referenceTime = moment(args.shift()); 156 | } else if (args[0] === null || args[0] === 'now') { 157 | // If null or 'now', remove argument and proceed with default referenceTime. 158 | args.shift(); 159 | } 160 | 161 | if (args[0]) { units = args.shift(); } 162 | 163 | if (args[0] === true) { float = args.shift(); } 164 | 165 | date = date.diff(referenceTime, units, float); 166 | break; 167 | } 168 | 169 | case 'calendar': 170 | { 171 | /* 172 | * Formats a date with different strings depending on how close 173 | * to a certain date (today by default) the date is. 174 | * http://momentjs.com/docs/#/displaying/calendar-time/ 175 | */ 176 | 177 | var _referenceTime = moment(); 178 | var formats = {}; 179 | 180 | if (moment(args[0]).isValid()) { 181 | // If valid, assume it is a date we want the output computed against. 182 | _referenceTime = moment(args.shift()); 183 | } else if (args[0] === null || args[0] === 'now') { 184 | // If null or 'now', remove argument and proceed with default referenceTime. 185 | args.shift(); 186 | } 187 | 188 | if (_typeof(args[0]) === 'object') { formats = args.shift(); } 189 | 190 | date = date.calendar(_referenceTime, formats); 191 | break; 192 | } 193 | 194 | case 'utc': 195 | { 196 | /* 197 | * Mutates the original moment by converting to UTC 198 | * https://momentjs.com/docs/#/manipulating/utc/ 199 | */ 200 | date.utc(); 201 | break; 202 | } 203 | 204 | case 'timezone': 205 | { 206 | /* 207 | * Mutates the original moment by converting to a new timezone. 208 | * https://momentjs.com/timezone/docs/#/using-timezones/converting-to-zone/ 209 | */ 210 | date.tz(args.shift()); 211 | break; 212 | } 213 | 214 | default: 215 | { 216 | /* 217 | * Formats a date by taking a string of tokens and replacing 218 | * them with their corresponding values. 219 | * http://momentjs.com/docs/#/displaying/format/ 220 | */ 221 | 222 | var format = method; 223 | date = date.format(format); 224 | } 225 | } 226 | 227 | if (args.length) { parse.apply(parse, args); } 228 | } 229 | 230 | parse.apply(parse, args); 231 | 232 | return date; 233 | }); 234 | 235 | Vue.filter('duration', function () { 236 | var arguments$1 = arguments; 237 | 238 | for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { 239 | args[_key3] = arguments$1[_key3]; 240 | } 241 | 242 | /* 243 | * Basic pass-through filter for leveraging moment.js's ability 244 | * to manipulate and display durations. 245 | * https://momentjs.com/docs/#/durations/ 246 | */ 247 | args = Array.prototype.slice.call(args); 248 | var input = args.shift(); 249 | var method = args.shift(); 250 | 251 | function createDuration(time) { 252 | if (!Array.isArray(time)) { time = [time]; } 253 | var result = moment.duration.apply(moment, _toConsumableArray(time)); 254 | if (!result.isValid()) { console.warn('Could not build a valid `duration` object from input.'); } 255 | return result; 256 | } 257 | var duration = createDuration(input); 258 | 259 | if (method === 'add' || method === 'subtract') { 260 | // Generates a duration object and either adds or subtracts it 261 | // from our original duration. 262 | var durationChange = createDuration(args); 263 | duration[method](durationChange); 264 | } else if (duration && duration[method]) { 265 | var _duration; 266 | 267 | // This gives a full proxy to moment.duration functions. 268 | duration = (_duration = duration)[method].apply(_duration, _toConsumableArray(args)); 269 | } 270 | 271 | return duration; 272 | }); 273 | } 274 | }; 275 | -------------------------------------------------------------------------------- /dist/vue-moment.es.js: -------------------------------------------------------------------------------- 1 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { 2 | return typeof obj; 3 | } : function (obj) { 4 | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 5 | }; 6 | 7 | function _toConsumableArray(arr) { 8 | if (Array.isArray(arr)) { 9 | for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { 10 | arr2[i] = arr[i]; 11 | }return arr2; 12 | } else { 13 | return Array.from(arr); 14 | } 15 | } 16 | 17 | module.exports = { 18 | install: function install(Vue, options) { 19 | var moment = options && options.moment ? options.moment : require('moment'); 20 | 21 | Object.defineProperties(Vue.prototype, { 22 | $moment: { 23 | get: function get() { 24 | return moment; 25 | } 26 | } 27 | }); 28 | 29 | Vue.moment = moment; 30 | 31 | Vue.filter('moment', function () { 32 | var arguments$1 = arguments; 33 | 34 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 35 | args[_key] = arguments$1[_key]; 36 | } 37 | 38 | args = Array.prototype.slice.call(args); 39 | var input = args.shift(); 40 | var date = void 0; 41 | 42 | if (Array.isArray(input) && typeof input[0] === 'string') { 43 | // If input is array, assume we're being passed a format pattern to parse against. 44 | // Format pattern will accept an array of potential formats to parse against. 45 | // Date string should be at [0], format pattern(s) should be at [1] 46 | date = moment(input[0], input[1], true); 47 | } else if (typeof input === 'number') { 48 | if (input.toString().length < 12) { 49 | // If input is an integer with fewer than 12 digits, assume Unix seconds... 50 | date = moment.unix(input); 51 | } else { 52 | // ..otherwise, assume milliseconds. 53 | date = moment(input); 54 | } 55 | } else { 56 | // Otherwise, throw the input at moment and see what happens... 57 | date = moment(input); 58 | } 59 | 60 | if (!input || !date.isValid()) { 61 | // Log a warning if moment couldn't reconcile the input. Better than throwing an error? 62 | console.warn('Could not build a valid `moment` object from input.'); 63 | return input; 64 | } 65 | 66 | function parse() { 67 | var arguments$1 = arguments; 68 | 69 | for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 70 | args[_key2] = arguments$1[_key2]; 71 | } 72 | 73 | args = Array.prototype.slice.call(args); 74 | var method = args.shift(); 75 | 76 | switch (method) { 77 | case 'add': 78 | { 79 | /* 80 | * Mutates the original moment by adding time. 81 | * http://momentjs.com/docs/#/manipulating/add/ 82 | */ 83 | 84 | var addends = args.shift().split(',').map(Function.prototype.call, String.prototype.trim); 85 | var obj = {}; 86 | 87 | for (var n = 0; n < addends.length; n++) { 88 | var addend = addends[n].split(' '); 89 | obj[addend[1]] = addend[0]; 90 | } 91 | date.add(obj); 92 | break; 93 | } 94 | 95 | case 'subtract': 96 | { 97 | /* 98 | * Mutates the original moment by subtracting time. 99 | * http://momentjs.com/docs/#/manipulating/subtract/ 100 | */ 101 | 102 | var subtrahends = args.shift().split(',').map(Function.prototype.call, String.prototype.trim); 103 | var _obj = {}; 104 | 105 | for (var _n = 0; _n < subtrahends.length; _n++) { 106 | var subtrahend = subtrahends[_n].split(' '); 107 | _obj[subtrahend[1]] = subtrahend[0]; 108 | } 109 | date.subtract(_obj); 110 | break; 111 | } 112 | 113 | case 'from': 114 | { 115 | /* 116 | * Display a moment in relative time, either from now or from a specified date. 117 | * http://momentjs.com/docs/#/displaying/fromnow/ 118 | */ 119 | 120 | var from = 'now'; 121 | var removeSuffix = false; 122 | 123 | if (args[0] === 'now') { args.shift(); } 124 | // If valid, assume it is a date we want the output computed against. 125 | if (moment(args[0]).isValid()) { from = moment(args.shift()); } 126 | 127 | if (args[0] === true) { 128 | args.shift(); 129 | removeSuffix = true; 130 | } 131 | 132 | if (from !== 'now') { 133 | date = date.from(from, removeSuffix); 134 | } else { 135 | date = date.fromNow(removeSuffix); 136 | } 137 | break; 138 | } 139 | 140 | case 'diff': 141 | { 142 | /* 143 | * Mutates the original moment by doing a difference with another date. 144 | * http://momentjs.com/docs/#/displaying/difference/ 145 | */ 146 | 147 | var referenceTime = moment(); 148 | var units = ''; 149 | var float = false; 150 | 151 | if (moment(args[0]).isValid()) { 152 | // If valid, assume it is a date we want the output computed against. 153 | referenceTime = moment(args.shift()); 154 | } else if (args[0] === null || args[0] === 'now') { 155 | // If null or 'now', remove argument and proceed with default referenceTime. 156 | args.shift(); 157 | } 158 | 159 | if (args[0]) { units = args.shift(); } 160 | 161 | if (args[0] === true) { float = args.shift(); } 162 | 163 | date = date.diff(referenceTime, units, float); 164 | break; 165 | } 166 | 167 | case 'calendar': 168 | { 169 | /* 170 | * Formats a date with different strings depending on how close 171 | * to a certain date (today by default) the date is. 172 | * http://momentjs.com/docs/#/displaying/calendar-time/ 173 | */ 174 | 175 | var _referenceTime = moment(); 176 | var formats = {}; 177 | 178 | if (moment(args[0]).isValid()) { 179 | // If valid, assume it is a date we want the output computed against. 180 | _referenceTime = moment(args.shift()); 181 | } else if (args[0] === null || args[0] === 'now') { 182 | // If null or 'now', remove argument and proceed with default referenceTime. 183 | args.shift(); 184 | } 185 | 186 | if (_typeof(args[0]) === 'object') { formats = args.shift(); } 187 | 188 | date = date.calendar(_referenceTime, formats); 189 | break; 190 | } 191 | 192 | case 'utc': 193 | { 194 | /* 195 | * Mutates the original moment by converting to UTC 196 | * https://momentjs.com/docs/#/manipulating/utc/ 197 | */ 198 | date.utc(); 199 | break; 200 | } 201 | 202 | case 'timezone': 203 | { 204 | /* 205 | * Mutates the original moment by converting to a new timezone. 206 | * https://momentjs.com/timezone/docs/#/using-timezones/converting-to-zone/ 207 | */ 208 | date.tz(args.shift()); 209 | break; 210 | } 211 | 212 | default: 213 | { 214 | /* 215 | * Formats a date by taking a string of tokens and replacing 216 | * them with their corresponding values. 217 | * http://momentjs.com/docs/#/displaying/format/ 218 | */ 219 | 220 | var format = method; 221 | date = date.format(format); 222 | } 223 | } 224 | 225 | if (args.length) { parse.apply(parse, args); } 226 | } 227 | 228 | parse.apply(parse, args); 229 | 230 | return date; 231 | }); 232 | 233 | Vue.filter('duration', function () { 234 | var arguments$1 = arguments; 235 | 236 | for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { 237 | args[_key3] = arguments$1[_key3]; 238 | } 239 | 240 | /* 241 | * Basic pass-through filter for leveraging moment.js's ability 242 | * to manipulate and display durations. 243 | * https://momentjs.com/docs/#/durations/ 244 | */ 245 | args = Array.prototype.slice.call(args); 246 | var input = args.shift(); 247 | var method = args.shift(); 248 | 249 | function createDuration(time) { 250 | if (!Array.isArray(time)) { time = [time]; } 251 | var result = moment.duration.apply(moment, _toConsumableArray(time)); 252 | if (!result.isValid()) { console.warn('Could not build a valid `duration` object from input.'); } 253 | return result; 254 | } 255 | var duration = createDuration(input); 256 | 257 | if (method === 'add' || method === 'subtract') { 258 | // Generates a duration object and either adds or subtracts it 259 | // from our original duration. 260 | var durationChange = createDuration(args); 261 | duration[method](durationChange); 262 | } else if (duration && duration[method]) { 263 | var _duration; 264 | 265 | // This gives a full proxy to moment.duration functions. 266 | duration = (_duration = duration)[method].apply(_duration, _toConsumableArray(args)); 267 | } 268 | 269 | return duration; 270 | }); 271 | } 272 | }; 273 | -------------------------------------------------------------------------------- /dist/vue-moment.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.vueMoment={})}(this,function(t){"use strict";var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(){throw new Error("Dynamic requires are not currently supported by rollup-plugin-commonjs")}var i,s=(function(t,i){var s,r,a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};s=e,r=function(){var e,i;function s(){return e.apply(null,arguments)}function r(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function o(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function u(t){return void 0===t}function l(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function d(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function h(t,e){var n,i=[];for(n=0;n>>0,i=0;i0)for(n=0;n=0?n?"+":"":"-")+Math.pow(10,Math.max(0,s)).toString().substr(1)+i}var A=/(\[[^\[]*\])|(\\)?([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,E=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,j={},I={};function z(t,e,n,i){var s=i;"string"==typeof i&&(s=function(){return this[i]()}),t&&(I[t]=s),e&&(I[e[0]]=function(){return G(s.apply(this,arguments),e[1],e[2])}),n&&(I[n]=function(){return this.localeData().ordinal(s.apply(this,arguments),t)})}function Z(t,e){return t.isValid()?(e=$(e,t.localeData()),j[e]=j[e]||function(t){var e,n,i,s=t.match(A);for(e=0,n=s.length;e=0&&E.test(t);)t=t.replace(E,i),E.lastIndex=0,n-=1;return t}var q=/\d/,J=/\d\d/,B=/\d{3}/,Q=/\d{4}/,X=/[+-]?\d{6}/,K=/\d\d?/,tt=/\d\d\d\d?/,et=/\d\d\d\d\d\d?/,nt=/\d{1,3}/,it=/\d{1,4}/,st=/[+-]?\d{1,6}/,rt=/\d+/,at=/[+-]?\d+/,ot=/Z|[+-]\d\d:?\d\d/gi,ut=/Z|[+-]\d\d(?::?\d\d)?/gi,lt=/[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,dt={};function ht(t,e,n){dt[t]=W(e)?e:function(t,i){return t&&n?n:e}}function ct(t,e){return c(dt,t)?dt[t](e._strict,e._locale):new RegExp(ft(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,i,s){return e||n||i||s})))}function ft(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var mt={};function _t(t,e){var n,i=e;for("string"==typeof t&&(t=[t]),l(e)&&(i=function(t,n){n[e]=D(t)}),n=0;n68?1900:2e3)};var xt,Pt=Wt("FullYear",!0);function Wt(t,e){return function(n){return null!=n?(Ht(this,t,n),s.updateOffset(this,e),this):Ct(this,t)}}function Ct(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function Ht(t,e,n){t.isValid()&&!isNaN(n)&&("FullYear"===e&&Tt(t.year())&&1===t.month()&&29===t.date()?t._d["set"+(t._isUTC?"UTC":"")+e](n,t.month(),Rt(n,t.month())):t._d["set"+(t._isUTC?"UTC":"")+e](n))}function Rt(t,e){if(isNaN(t)||isNaN(e))return NaN;var n,i=(e%(n=12)+n)%n;return t+=(e-i)/12,1===i?Tt(t)?29:28:31-i%7%2}xt=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e=0){var n=Array.prototype.slice.call(arguments);n[0]=t+400,e=new Date(Date.UTC.apply(null,n)),isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t)}else e=new Date(Date.UTC.apply(null,arguments));return e}function It(t,e,n){var i=7+e-n;return-((7+jt(t,0,i).getUTCDay()-e)%7)+i-1}function zt(t,e,n,i,s){var r,a,o=1+7*(e-1)+(7+n-i)%7+It(t,i,s);return o<=0?a=bt(r=t-1)+o:o>bt(t)?(r=t+1,a=o-bt(t)):(r=t,a=o),{year:r,dayOfYear:a}}function Zt(t,e,n){var i,s,r=It(t.year(),e,n),a=Math.floor((t.dayOfYear()-r-1)/7)+1;return a<1?i=a+$t(s=t.year()-1,e,n):a>$t(t.year(),e,n)?(i=a-$t(t.year(),e,n),s=t.year()+1):(s=t.year(),i=a),{week:i,year:s}}function $t(t,e,n){var i=It(t,e,n),s=It(t+1,e,n);return(bt(t)-i+s)/7}z("w",["ww",2],"wo","week"),z("W",["WW",2],"Wo","isoWeek"),F("week","w"),F("isoWeek","W"),N("week",5),N("isoWeek",5),ht("w",K),ht("ww",K,J),ht("W",K),ht("WW",K,J),yt(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=D(t)});function qt(t,e){return t.slice(e,7).concat(t.slice(0,e))}z("d",0,"do","day"),z("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),z("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),z("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),z("e",0,0,"weekday"),z("E",0,0,"isoWeekday"),F("day","d"),F("weekday","e"),F("isoWeekday","E"),N("day",11),N("weekday",11),N("isoWeekday",11),ht("d",K),ht("e",K),ht("E",K),ht("dd",function(t,e){return e.weekdaysMinRegex(t)}),ht("ddd",function(t,e){return e.weekdaysShortRegex(t)}),ht("dddd",function(t,e){return e.weekdaysRegex(t)}),yt(["dd","ddd","dddd"],function(t,e,n,i){var s=n._locale.weekdaysParse(t,i,n._strict);null!=s?e.d=s:_(n).invalidWeekday=t}),yt(["d","e","E"],function(t,e,n,i){e[i]=D(t)});var Jt="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Bt="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var Qt="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var Xt=lt;var Kt=lt;var te=lt;function ee(){function t(t,e){return e.length-t.length}var e,n,i,s,r,a=[],o=[],u=[],l=[];for(e=0;e<7;e++)n=m([2e3,1]).day(e),i=this.weekdaysMin(n,""),s=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(i),o.push(s),u.push(r),l.push(i),l.push(s),l.push(r);for(a.sort(t),o.sort(t),u.sort(t),l.sort(t),e=0;e<7;e++)o[e]=ft(o[e]),u[e]=ft(u[e]),l[e]=ft(l[e]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function ne(){return this.hours()%12||12}function ie(t,e){z(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function se(t,e){return e._meridiemParse}z("H",["HH",2],0,"hour"),z("h",["hh",2],0,ne),z("k",["kk",2],0,function(){return this.hours()||24}),z("hmm",0,0,function(){return""+ne.apply(this)+G(this.minutes(),2)}),z("hmmss",0,0,function(){return""+ne.apply(this)+G(this.minutes(),2)+G(this.seconds(),2)}),z("Hmm",0,0,function(){return""+this.hours()+G(this.minutes(),2)}),z("Hmmss",0,0,function(){return""+this.hours()+G(this.minutes(),2)+G(this.seconds(),2)}),ie("a",!0),ie("A",!1),F("hour","h"),N("hour",13),ht("a",se),ht("A",se),ht("H",K),ht("h",K),ht("k",K),ht("HH",K,J),ht("hh",K,J),ht("kk",K,J),ht("hmm",tt),ht("hmmss",et),ht("Hmm",tt),ht("Hmmss",et),_t(["H","HH"],St),_t(["k","kk"],function(t,e,n){var i=D(t);e[St]=24===i?0:i}),_t(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),_t(["h","hh"],function(t,e,n){e[St]=D(t),_(n).bigHour=!0}),_t("hmm",function(t,e,n){var i=t.length-2;e[St]=D(t.substr(0,i)),e[Mt]=D(t.substr(i)),_(n).bigHour=!0}),_t("hmmss",function(t,e,n){var i=t.length-4,s=t.length-2;e[St]=D(t.substr(0,i)),e[Mt]=D(t.substr(i,2)),e[kt]=D(t.substr(s)),_(n).bigHour=!0}),_t("Hmm",function(t,e,n){var i=t.length-2;e[St]=D(t.substr(0,i)),e[Mt]=D(t.substr(i))}),_t("Hmmss",function(t,e,n){var i=t.length-4,s=t.length-2;e[St]=D(t.substr(0,i)),e[Mt]=D(t.substr(i,2)),e[kt]=D(t.substr(s))});var re,ae=Wt("Hours",!0),oe={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{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"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{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"},months:Ut,monthsShort:Lt,week:{dow:0,doy:6},weekdays:Jt,weekdaysMin:Qt,weekdaysShort:Bt,meridiemParse:/[ap]\.?m?\.?/i},ue={},le={};function de(t){return t?t.toLowerCase().replace("_","-"):t}function he(e){var i=null;if(!ue[e]&&t&&t.exports)try{i=re._abbr,n("./locale/"+e),ce(i)}catch(t){}return ue[e]}function ce(t,e){var n;return t&&((n=u(e)?me(t):fe(t,e))?re=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),re._abbr}function fe(t,e){if(null!==e){var n,i=oe;if(e.abbr=t,null!=ue[t])P("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."),i=ue[t]._config;else if(null!=e.parentLocale)if(null!=ue[e.parentLocale])i=ue[e.parentLocale]._config;else{if(null==(n=he(e.parentLocale)))return le[e.parentLocale]||(le[e.parentLocale]=[]),le[e.parentLocale].push({name:t,config:e}),null;i=n._config}return ue[t]=new H(C(i,e)),le[t]&&le[t].forEach(function(t){fe(t.name,t.config)}),ce(t),ue[t]}return delete ue[t],null}function me(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return re;if(!r(t)){if(e=he(t))return e;t=[t]}return function(t){for(var e,n,i,s,r=0;r0;){if(i=he(s.slice(0,e).join("-")))return i;if(n&&n.length>=e&&Y(s,n,!0)>=e-1)break;e--}r++}return re}(t)}function _e(t){var e,n=t._a;return n&&-2===_(t).overflow&&(e=n[vt]<0||n[vt]>11?vt:n[wt]<1||n[wt]>Rt(n[gt],n[vt])?wt:n[St]<0||n[St]>24||24===n[St]&&(0!==n[Mt]||0!==n[kt]||0!==n[Dt])?St:n[Mt]<0||n[Mt]>59?Mt:n[kt]<0||n[kt]>59?kt:n[Dt]<0||n[Dt]>999?Dt:-1,_(t)._overflowDayOfYear&&(ewt)&&(e=wt),_(t)._overflowWeeks&&-1===e&&(e=Yt),_(t)._overflowWeekday&&-1===e&&(e=Ot),_(t).overflow=e),t}function ye(t,e,n){return null!=t?t:null!=e?e:n}function pe(t){var e,n,i,r,a,o=[];if(!t._d){for(i=function(t){var e=new Date(s.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}(t),t._w&&null==t._a[wt]&&null==t._a[vt]&&function(t){var e,n,i,s,r,a,o,u;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)r=1,a=4,n=ye(e.GG,t._a[gt],Zt(Ce(),1,4).year),i=ye(e.W,1),((s=ye(e.E,1))<1||s>7)&&(u=!0);else{r=t._locale._week.dow,a=t._locale._week.doy;var l=Zt(Ce(),r,a);n=ye(e.gg,t._a[gt],l.year),i=ye(e.w,l.week),null!=e.d?((s=e.d)<0||s>6)&&(u=!0):null!=e.e?(s=e.e+r,(e.e<0||e.e>6)&&(u=!0)):s=r}i<1||i>$t(n,r,a)?_(t)._overflowWeeks=!0:null!=u?_(t)._overflowWeekday=!0:(o=zt(n,i,s,r,a),t._a[gt]=o.year,t._dayOfYear=o.dayOfYear)}(t),null!=t._dayOfYear&&(a=ye(t._a[gt],i[gt]),(t._dayOfYear>bt(a)||0===t._dayOfYear)&&(_(t)._overflowDayOfYear=!0),n=jt(a,0,t._dayOfYear),t._a[vt]=n.getUTCMonth(),t._a[wt]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=o[e]=i[e];for(;e<7;e++)t._a[e]=o[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[St]&&0===t._a[Mt]&&0===t._a[kt]&&0===t._a[Dt]&&(t._nextDay=!0,t._a[St]=0),t._d=(t._useUTC?jt:function(t,e,n,i,s,r,a){var o;return t<100&&t>=0?(o=new Date(t+400,e,n,i,s,r,a),isFinite(o.getFullYear())&&o.setFullYear(t)):o=new Date(t,e,n,i,s,r,a),o}).apply(null,o),r=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[St]=24),t._w&&void 0!==t._w.d&&t._w.d!==r&&(_(t).weekdayMismatch=!0)}}var ge=/^\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)?)?$/,ve=/^\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)?)?$/,we=/Z|[+-]\d\d(?::?\d\d)?/,Se=[["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/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Me=[["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/]],ke=/^\/?Date\((\-?\d+)/i;function De(t){var e,n,i,s,r,a,o=t._i,u=ge.exec(o)||ve.exec(o);if(u){for(_(t).iso=!0,e=0,n=Se.length;e0&&_(t).unusedInput.push(a),o=o.slice(o.indexOf(n)+n.length),l+=n.length),I[r]?(n?_(t).empty=!1:_(t).unusedTokens.push(r),pt(r,n,t)):t._strict&&!n&&_(t).unusedTokens.push(r);_(t).charsLeftOver=u-l,o.length>0&&_(t).unusedInput.push(o),t._a[St]<=12&&!0===_(t).bigHour&&t._a[St]>0&&(_(t).bigHour=void 0),_(t).parsedDateParts=t._a.slice(0),_(t).meridiem=t._meridiem,t._a[St]=function(t,e,n){var i;if(null==n)return e;return null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?((i=t.isPM(n))&&e<12&&(e+=12),i||12!==e||(e=0),e):e}(t._locale,t._a[St],t._meridiem),pe(t),_e(t)}else Te(t);else De(t)}function Pe(t){var e=t._i,n=t._f;return t._locale=t._locale||me(t._l),null===e||void 0===n&&""===e?p({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),M(e)?new S(_e(e)):(d(e)?t._d=e:r(n)?function(t){var e,n,i,s,r;if(0===t._f.length)return _(t).invalidFormat=!0,void(t._d=new Date(NaN));for(s=0;sthis?this:t:p()});function Fe(t,e){var n,i;if(1===e.length&&r(e[0])&&(e=e[0]),!e.length)return Ce();for(n=e[0],i=1;i=0?new Date(t+400,e,n)-ln:new Date(t,e,n).valueOf()}function cn(t,e,n){return t<100&&t>=0?Date.UTC(t+400,e,n)-ln:Date.UTC(t,e,n)}function fn(t,e){z(0,[t,t.length],0,e)}function mn(t,e,n,i,s){var r;return null==t?Zt(this,i,s).year:(e>(r=$t(t,i,s))&&(e=r),function(t,e,n,i,s){var r=zt(t,e,n,i,s),a=jt(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,t,e,n,i,s))}z(0,["gg",2],0,function(){return this.weekYear()%100}),z(0,["GG",2],0,function(){return this.isoWeekYear()%100}),fn("gggg","weekYear"),fn("ggggg","weekYear"),fn("GGGG","isoWeekYear"),fn("GGGGG","isoWeekYear"),F("weekYear","gg"),F("isoWeekYear","GG"),N("weekYear",1),N("isoWeekYear",1),ht("G",at),ht("g",at),ht("GG",K,J),ht("gg",K,J),ht("GGGG",it,Q),ht("gggg",it,Q),ht("GGGGG",st,X),ht("ggggg",st,X),yt(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,i){e[i.substr(0,2)]=D(t)}),yt(["gg","GG"],function(t,e,n,i){e[i]=s.parseTwoDigitYear(t)}),z("Q",0,"Qo","quarter"),F("quarter","Q"),N("quarter",7),ht("Q",q),_t("Q",function(t,e){e[vt]=3*(D(t)-1)}),z("D",["DD",2],"Do","date"),F("date","D"),N("date",9),ht("D",K),ht("DD",K,J),ht("Do",function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient}),_t(["D","DD"],wt),_t("Do",function(t,e){e[wt]=D(t.match(K)[0])});var _n=Wt("Date",!0);z("DDD",["DDDD",3],"DDDo","dayOfYear"),F("dayOfYear","DDD"),N("dayOfYear",4),ht("DDD",nt),ht("DDDD",B),_t(["DDD","DDDD"],function(t,e,n){n._dayOfYear=D(t)}),z("m",["mm",2],0,"minute"),F("minute","m"),N("minute",14),ht("m",K),ht("mm",K,J),_t(["m","mm"],Mt);var yn=Wt("Minutes",!1);z("s",["ss",2],0,"second"),F("second","s"),N("second",15),ht("s",K),ht("ss",K,J),_t(["s","ss"],kt);var pn,gn=Wt("Seconds",!1);for(z("S",0,0,function(){return~~(this.millisecond()/100)}),z(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),z(0,["SSS",3],0,"millisecond"),z(0,["SSSS",4],0,function(){return 10*this.millisecond()}),z(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),z(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),z(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),z(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),z(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),F("millisecond","ms"),N("millisecond",16),ht("S",nt,q),ht("SS",nt,J),ht("SSS",nt,B),pn="SSSS";pn.length<=9;pn+="S")ht(pn,rt);function vn(t,e){e[Dt]=D(1e3*("0."+t))}for(pn="S";pn.length<=9;pn+="S")_t(pn,vn);var wn=Wt("Milliseconds",!1);z("z",0,0,"zoneAbbr"),z("zz",0,0,"zoneName");var Sn=S.prototype;function Mn(t){return t}Sn.add=Ke,Sn.calendar=function(t,e){var n=t||Ce(),i=je(n,this).startOf("day"),r=s.calendarFormat(this,i)||"sameElse",a=e&&(W(e[r])?e[r].call(this,n):e[r]);return this.format(a||this.localeData().calendar(r,this,Ce(n)))},Sn.clone=function(){return new S(this)},Sn.diff=function(t,e,n){var i,s,r;if(!this.isValid())return NaN;if(!(i=je(t,this)).isValid())return NaN;switch(s=6e4*(i.utcOffset()-this.utcOffset()),e=U(e)){case"year":r=en(this,i)/12;break;case"month":r=en(this,i);break;case"quarter":r=en(this,i)/3;break;case"second":r=(this-i)/1e3;break;case"minute":r=(this-i)/6e4;break;case"hour":r=(this-i)/36e5;break;case"day":r=(this-i-s)/864e5;break;case"week":r=(this-i-s)/6048e5;break;default:r=this-i}return n?r:k(r)},Sn.endOf=function(t){var e;if(void 0===(t=U(t))||"millisecond"===t||!this.isValid())return this;var n=this._isUTC?cn:hn;switch(t){case"year":e=n(this.year()+1,0,1)-1;break;case"quarter":e=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":e=n(this.year(),this.month()+1,1)-1;break;case"week":e=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":e=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":e=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":e=this._d.valueOf(),e+=un-dn(e+(this._isUTC?0:this.utcOffset()*on),un)-1;break;case"minute":e=this._d.valueOf(),e+=on-dn(e,on)-1;break;case"second":e=this._d.valueOf(),e+=an-dn(e,an)-1}return this._d.setTime(e),s.updateOffset(this,!0),this},Sn.format=function(t){t||(t=this.isUtc()?s.defaultFormatUtc:s.defaultFormat);var e=Z(this,t);return this.localeData().postformat(e)},Sn.from=function(t,e){return this.isValid()&&(M(t)&&t.isValid()||Ce(t).isValid())?qe({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},Sn.fromNow=function(t){return this.from(Ce(),t)},Sn.to=function(t,e){return this.isValid()&&(M(t)&&t.isValid()||Ce(t).isValid())?qe({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},Sn.toNow=function(t){return this.to(Ce(),t)},Sn.get=function(t){return W(this[t=U(t)])?this[t]():this},Sn.invalidAt=function(){return _(this).overflow},Sn.isAfter=function(t,e){var n=M(t)?t:Ce(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=U(e)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()9999?Z(n,e?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):W(Date.prototype.toISOString)?e?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",Z(n,"Z")):Z(n,e?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},Sn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',i=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",s=e+'[")]';return this.format(n+i+"-MM-DD[T]HH:mm:ss.SSS"+s)},Sn.toJSON=function(){return this.isValid()?this.toISOString():null},Sn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},Sn.unix=function(){return Math.floor(this.valueOf()/1e3)},Sn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},Sn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},Sn.year=Pt,Sn.isLeapYear=function(){return Tt(this.year())},Sn.weekYear=function(t){return mn.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},Sn.isoWeekYear=function(t){return mn.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},Sn.quarter=Sn.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},Sn.month=Nt,Sn.daysInMonth=function(){return Rt(this.year(),this.month())},Sn.week=Sn.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},Sn.isoWeek=Sn.isoWeeks=function(t){var e=Zt(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},Sn.weeksInYear=function(){var t=this.localeData()._week;return $t(this.year(),t.dow,t.doy)},Sn.isoWeeksInYear=function(){return $t(this.year(),1,4)},Sn.date=_n,Sn.day=Sn.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=function(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}(t,this.localeData()),this.add(t-e,"d")):e},Sn.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},Sn.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=function(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7},Sn.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},Sn.hour=Sn.hours=ae,Sn.minute=Sn.minutes=yn,Sn.second=Sn.seconds=gn,Sn.millisecond=Sn.milliseconds=wn,Sn.utcOffset=function(t,e,n){var i,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=Ee(ut,t)))return this}else Math.abs(t)<16&&!n&&(t*=60);return!this._isUTC&&e&&(i=Ie(this)),this._offset=t,this._isUTC=!0,null!=i&&this.add(i,"m"),r!==t&&(!e||this._changeInProgress?Xe(this,qe(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,s.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Ie(this)},Sn.utc=function(t){return this.utcOffset(0,t)},Sn.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Ie(this),"m")),this},Sn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=Ee(ot,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},Sn.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?Ce(t).utcOffset():0,(this.utcOffset()-t)%60==0)},Sn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Sn.isLocal=function(){return!!this.isValid()&&!this._isUTC},Sn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Sn.isUtc=ze,Sn.isUTC=ze,Sn.zoneAbbr=function(){return this._isUTC?"UTC":""},Sn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Sn.dates=b("dates accessor is deprecated. Use date instead.",_n),Sn.months=b("months accessor is deprecated. Use month instead",Nt),Sn.years=b("years accessor is deprecated. Use year instead",Pt),Sn.zone=b("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),Sn.isDSTShifted=b("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!u(this._isDSTShifted))return this._isDSTShifted;var t={};if(v(t,this),(t=Pe(t))._a){var e=t._isUTC?m(t._a):Ce(t._a);this._isDSTShifted=this.isValid()&&Y(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var kn=H.prototype;function Dn(t,e,n,i){var s=me(),r=m().set(i,e);return s[n](r,t)}function Yn(t,e,n){if(l(t)&&(e=t,t=void 0),t=t||"",null!=e)return Dn(t,e,n,"month");var i,s=[];for(i=0;i<12;i++)s[i]=Dn(t,i,n,"month");return s}function On(t,e,n,i){"boolean"==typeof t?(l(e)&&(n=e,e=void 0),e=e||""):(n=e=t,t=!1,l(e)&&(n=e,e=void 0),e=e||"");var s,r=me(),a=t?r._week.dow:0;if(null!=n)return Dn(e,(n+a)%7,i,"day");var o=[];for(s=0;s<7;s++)o[s]=Dn(e,(s+a)%7,i,"day");return o}kn.calendar=function(t,e,n){var i=this._calendar[t]||this._calendar.sameElse;return W(i)?i.call(e,n):i},kn.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},kn.invalidDate=function(){return this._invalidDate},kn.ordinal=function(t){return this._ordinal.replace("%d",t)},kn.preparse=Mn,kn.postformat=Mn,kn.relativeTime=function(t,e,n,i){var s=this._relativeTime[n];return W(s)?s(t,e,n,i):s.replace(/%d/i,t)},kn.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return W(n)?n(e):n.replace(/%s/i,e)},kn.set=function(t){var e,n;for(n in t)W(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},kn.months=function(t,e){return t?r(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||Ft).test(e)?"format":"standalone"][t.month()]:r(this._months)?this._months:this._months.standalone},kn.monthsShort=function(t,e){return t?r(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[Ft.test(e)?"format":"standalone"][t.month()]:r(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},kn.monthsParse=function(t,e,n){var i,s,r;if(this._monthsParseExact)return function(t,e,n){var i,s,r,a=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],i=0;i<12;++i)r=m([2e3,i]),this._shortMonthsParse[i]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[i]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===e?-1!==(s=xt.call(this._shortMonthsParse,a))?s:null:-1!==(s=xt.call(this._longMonthsParse,a))?s:null:"MMM"===e?-1!==(s=xt.call(this._shortMonthsParse,a))?s:-1!==(s=xt.call(this._longMonthsParse,a))?s:null:-1!==(s=xt.call(this._longMonthsParse,a))?s:-1!==(s=xt.call(this._shortMonthsParse,a))?s:null}.call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;i<12;i++){if(s=m([2e3,i]),n&&!this._longMonthsParse[i]&&(this._longMonthsParse[i]=new RegExp("^"+this.months(s,"").replace(".","")+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+this.monthsShort(s,"").replace(".","")+"$","i")),n||this._monthsParse[i]||(r="^"+this.months(s,"")+"|^"+this.monthsShort(s,""),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}},kn.monthsRegex=function(t){return this._monthsParseExact?(c(this,"_monthsRegex")||Et.call(this),t?this._monthsStrictRegex:this._monthsRegex):(c(this,"_monthsRegex")||(this._monthsRegex=At),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},kn.monthsShortRegex=function(t){return this._monthsParseExact?(c(this,"_monthsRegex")||Et.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(c(this,"_monthsShortRegex")||(this._monthsShortRegex=Gt),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},kn.week=function(t){return Zt(t,this._week.dow,this._week.doy).week},kn.firstDayOfYear=function(){return this._week.doy},kn.firstDayOfWeek=function(){return this._week.dow},kn.weekdays=function(t,e){var n=r(this._weekdays)?this._weekdays:this._weekdays[t&&!0!==t&&this._weekdays.isFormat.test(e)?"format":"standalone"];return!0===t?qt(n,this._week.dow):t?n[t.day()]:n},kn.weekdaysMin=function(t){return!0===t?qt(this._weekdaysMin,this._week.dow):t?this._weekdaysMin[t.day()]:this._weekdaysMin},kn.weekdaysShort=function(t){return!0===t?qt(this._weekdaysShort,this._week.dow):t?this._weekdaysShort[t.day()]:this._weekdaysShort},kn.weekdaysParse=function(t,e,n){var i,s,r;if(this._weekdaysParseExact)return function(t,e,n){var i,s,r,a=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;i<7;++i)r=m([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(s=xt.call(this._weekdaysParse,a))?s:null:"ddd"===e?-1!==(s=xt.call(this._shortWeekdaysParse,a))?s:null:-1!==(s=xt.call(this._minWeekdaysParse,a))?s:null:"dddd"===e?-1!==(s=xt.call(this._weekdaysParse,a))?s:-1!==(s=xt.call(this._shortWeekdaysParse,a))?s:-1!==(s=xt.call(this._minWeekdaysParse,a))?s:null:"ddd"===e?-1!==(s=xt.call(this._shortWeekdaysParse,a))?s:-1!==(s=xt.call(this._weekdaysParse,a))?s:-1!==(s=xt.call(this._minWeekdaysParse,a))?s:null:-1!==(s=xt.call(this._minWeekdaysParse,a))?s:-1!==(s=xt.call(this._weekdaysParse,a))?s:-1!==(s=xt.call(this._shortWeekdaysParse,a))?s:null}.call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;i<7;i++){if(s=m([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(s,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(s,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(s,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(s,"")+"|^"+this.weekdaysShort(s,"")+"|^"+this.weekdaysMin(s,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[i].test(t))return i;if(n&&"ddd"===e&&this._shortWeekdaysParse[i].test(t))return i;if(n&&"dd"===e&&this._minWeekdaysParse[i].test(t))return i;if(!n&&this._weekdaysParse[i].test(t))return i}},kn.weekdaysRegex=function(t){return this._weekdaysParseExact?(c(this,"_weekdaysRegex")||ee.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(c(this,"_weekdaysRegex")||(this._weekdaysRegex=Xt),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},kn.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(c(this,"_weekdaysRegex")||ee.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(c(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Kt),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},kn.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(c(this,"_weekdaysRegex")||ee.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(c(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=te),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},kn.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},kn.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},ce("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===D(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),s.lang=b("moment.lang is deprecated. Use moment.locale instead.",ce),s.langData=b("moment.langData is deprecated. Use moment.localeData instead.",me);var bn=Math.abs;function Tn(t,e,n,i){var s=qe(e,n);return t._milliseconds+=i*s._milliseconds,t._days+=i*s._days,t._months+=i*s._months,t._bubble()}function xn(t){return t<0?Math.floor(t):Math.ceil(t)}function Pn(t){return 4800*t/146097}function Wn(t){return 146097*t/4800}function Cn(t){return function(){return this.as(t)}}var Hn=Cn("ms"),Rn=Cn("s"),Fn=Cn("m"),Un=Cn("h"),Ln=Cn("d"),Vn=Cn("w"),Nn=Cn("M"),Gn=Cn("Q"),An=Cn("y");function En(t){return function(){return this.isValid()?this._data[t]:NaN}}var jn=En("milliseconds"),In=En("seconds"),zn=En("minutes"),Zn=En("hours"),$n=En("days"),qn=En("months"),Jn=En("years");var Bn=Math.round,Qn={ss:44,s:45,m:45,h:22,d:26,M:11};var Xn=Math.abs;function Kn(t){return(t>0)-(t<0)||+t}function ti(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n=Xn(this._milliseconds)/1e3,i=Xn(this._days),s=Xn(this._months);e=k((t=k(n/60))/60),n%=60,t%=60;var r=k(s/12),a=s%=12,o=i,u=e,l=t,d=n?n.toFixed(3).replace(/\.?0+$/,""):"",h=this.asSeconds();if(!h)return"P0D";var c=h<0?"-":"",f=Kn(this._months)!==Kn(h)?"-":"",m=Kn(this._days)!==Kn(h)?"-":"",_=Kn(this._milliseconds)!==Kn(h)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||d?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(d?_+d+"S":"")}var ei=Le.prototype;return ei.isValid=function(){return this._isValid},ei.abs=function(){var t=this._data;return this._milliseconds=bn(this._milliseconds),this._days=bn(this._days),this._months=bn(this._months),t.milliseconds=bn(t.milliseconds),t.seconds=bn(t.seconds),t.minutes=bn(t.minutes),t.hours=bn(t.hours),t.months=bn(t.months),t.years=bn(t.years),this},ei.add=function(t,e){return Tn(this,t,e,1)},ei.subtract=function(t,e){return Tn(this,t,e,-1)},ei.as=function(t){if(!this.isValid())return NaN;var e,n,i=this._milliseconds;if("month"===(t=U(t))||"quarter"===t||"year"===t)switch(e=this._days+i/864e5,n=this._months+Pn(e),t){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(e=this._days+Math.round(Wn(this._months)),t){case"week":return e/7+i/6048e5;case"day":return e+i/864e5;case"hour":return 24*e+i/36e5;case"minute":return 1440*e+i/6e4;case"second":return 86400*e+i/1e3;case"millisecond":return Math.floor(864e5*e)+i;default:throw new Error("Unknown unit "+t)}},ei.asMilliseconds=Hn,ei.asSeconds=Rn,ei.asMinutes=Fn,ei.asHours=Un,ei.asDays=Ln,ei.asWeeks=Vn,ei.asMonths=Nn,ei.asQuarters=Gn,ei.asYears=An,ei.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*D(this._months/12):NaN},ei._bubble=function(){var t,e,n,i,s,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return r>=0&&a>=0&&o>=0||r<=0&&a<=0&&o<=0||(r+=864e5*xn(Wn(o)+a),a=0,o=0),u.milliseconds=r%1e3,t=k(r/1e3),u.seconds=t%60,e=k(t/60),u.minutes=e%60,n=k(e/60),u.hours=n%24,o+=s=k(Pn(a+=k(n/24))),a-=xn(Wn(s)),i=k(o/12),o%=12,u.days=a,u.months=o,u.years=i,this},ei.clone=function(){return qe(this)},ei.get=function(t){return t=U(t),this.isValid()?this[t+"s"]():NaN},ei.milliseconds=jn,ei.seconds=In,ei.minutes=zn,ei.hours=Zn,ei.days=$n,ei.weeks=function(){return k(this.days()/7)},ei.months=qn,ei.years=Jn,ei.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),n=function(t,e,n){var i=qe(t).abs(),s=Bn(i.as("s")),r=Bn(i.as("m")),a=Bn(i.as("h")),o=Bn(i.as("d")),u=Bn(i.as("M")),l=Bn(i.as("y")),d=s<=Qn.ss&&["s",s]||s0,d[4]=n,function(t,e,n,i,s){return s.relativeTime(e||1,!!n,t,i)}.apply(null,d)}(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},ei.toISOString=ti,ei.toString=ti,ei.toJSON=ti,ei.locale=nn,ei.localeData=rn,ei.toIsoString=b("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ti),ei.lang=sn,z("X",0,0,"unix"),z("x",0,0,"valueOf"),ht("x",at),ht("X",/[+-]?\d+(\.\d{1,3})?/),_t("X",function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))}),_t("x",function(t,e,n){n._d=new Date(D(t))}),s.version="2.24.0",e=Ce,s.fn=Sn,s.min=function(){return Fe("isBefore",[].slice.call(arguments,0))},s.max=function(){return Fe("isAfter",[].slice.call(arguments,0))},s.now=function(){return Date.now?Date.now():+new Date},s.utc=m,s.unix=function(t){return Ce(1e3*t)},s.months=function(t,e){return Yn(t,e,"months")},s.isDate=d,s.locale=ce,s.invalid=p,s.duration=qe,s.isMoment=M,s.weekdays=function(t,e,n){return On(t,e,n,"weekdays")},s.parseZone=function(){return Ce.apply(null,arguments).parseZone()},s.localeData=me,s.isDuration=Ve,s.monthsShort=function(t,e){return Yn(t,e,"monthsShort")},s.weekdaysMin=function(t,e,n){return On(t,e,n,"weekdaysMin")},s.defineLocale=fe,s.updateLocale=function(t,e){if(null!=e){var n,i,s=oe;null!=(i=he(t))&&(s=i._config),(n=new H(e=C(s,e))).parentLocale=ue[t],ue[t]=n,ce(t)}else null!=ue[t]&&(null!=ue[t].parentLocale?ue[t]=ue[t].parentLocale:null!=ue[t]&&delete ue[t]);return ue[t]},s.locales=function(){return T(ue)},s.weekdaysShort=function(t,e,n){return On(t,e,n,"weekdaysShort")},s.normalizeUnits=U,s.relativeTimeRounding=function(t){return void 0===t?Bn:"function"==typeof t&&(Bn=t,!0)},s.relativeTimeThreshold=function(t,e){return void 0!==Qn[t]&&(void 0===e?Qn[t]:(Qn[t]=e,"s"===t&&(Qn.ss=e-1),!0))},s.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},s.prototype=Sn,s.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},s},"object"===a(i)?t.exports=r():s.moment=r()}(i={exports:{}},i.exports),i.exports),r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};function a(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e=1.x.x" 35 | }, 36 | "devDependencies": { 37 | "babel-core": "^6.26.0", 38 | "babel-eslint": "^8.0.3", 39 | "babel-jest": "^21.2.0", 40 | "babel-loader": "^7.1.2", 41 | "babel-preset-env": "^1.6.1", 42 | "bili": "^2.1.2", 43 | "eslint": "^4.12.1", 44 | "eslint-config-airbnb": "^16.1.0", 45 | "eslint-loader": "^1.9.0", 46 | "eslint-plugin-import": "^2.8.0", 47 | "eslint-plugin-jsx-a11y": "^6.0.2", 48 | "eslint-plugin-react": "^7.5.1", 49 | "jest": "^21.2.1", 50 | "jest-cli": "^21.2.1", 51 | "jest-serializer-vue": "^0.2.0", 52 | "jest-vue": "^0.8.1", 53 | "moment-timezone": "^0.5.14", 54 | "pre-commit": "^1.2.2", 55 | "rollup-plugin-babel": "^3.0.4", 56 | "vue": "^2.5.2" 57 | }, 58 | "pre-commit": "eslint", 59 | "jest": { 60 | "moduleFileExtensions": [ 61 | "js", 62 | "vue" 63 | ], 64 | "moduleNameMapper": { 65 | "^@/(.*)$": "/$1" 66 | }, 67 | "transform": { 68 | "^.+\\.js$": "/node_modules/babel-jest", 69 | ".*\\.(vue)$": "/node_modules/jest-vue" 70 | }, 71 | "snapshotSerializers": [ 72 | "/node_modules/jest-serializer-vue" 73 | ], 74 | "mapCoverage": true 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # vue-moment 2 | [![npm version](https://badge.fury.io/js/vue-moment.svg)](https://badge.fury.io/js/vue-moment) 3 | [![Build Status](https://travis-ci.org/brockpetrie/vue-moment.svg?branch=master)](https://travis-ci.org/brockpetrie/vue-moment) 4 | [![Monthly Downloads](https://img.shields.io/npm/dm/vue-moment.svg)](https://www.npmjs.com/package/vue-moment) 5 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 6 | 7 | Handy [Moment.js](http://www.momentjs.com) filters for your [Vue.js](http://vuejs.org/) project. 8 | 9 | ## Installation 10 | 11 | Install via NPM... 12 | 13 | ```sh 14 | $ npm install vue-moment 15 | ``` 16 | 17 | ...and require the plugin like so: 18 | 19 | ```js 20 | Vue.use(require('vue-moment')); 21 | ``` 22 | 23 | ### Typescript (optional) 24 | If you project is using Typescript, you can add type infomation using a 3rd party lib 25 | 26 | ```sh 27 | npm install @types/vue-moment --save-dev 28 | ``` 29 | 30 | ## Usage 31 | 32 | Simply set `moment` as the filtering function and you're good to go. At least one argument is expected, which the filter assumes to be a `format` string if the argument doesn't match any of the other filtering methods. 33 | 34 | ```html 35 | {{ someDate | moment("dddd, MMMM Do YYYY") }} 36 | 37 | {{ new Date() | moment("dddd, MMMM Do YYYY") }} 38 | ``` 39 | 40 | ## Passing Your Date 41 | 42 | Moment.js expects your input to be either: a valid ISO 8601 formatted string (see ), a valid `Date` object, a Unix timestamp (in seconds or milliseconds, passed as a Number), or a date string with an accompanying format pattern (i.e. when you know the format of the date input). For the latter, `vue-moment` allows you to pass your date and format pattern(s) as an array, like such: 43 | 44 | ```html 45 | {{ [ someDate, "MM.DD.YY" ] | moment("dddd, MMMM Do YYYY") }} 46 | 47 | {{ [ someDate, ["MM.DD.YY", "MM-DD-YY", "MM-DD-YYYY"] ] | moment("dddd, MMMM Do YYYY") }} 48 | ``` 49 | 50 | As of 3.0.0, passing an empty or invalid input will no longer initiate moment with a new `Date` object fallback. 51 | 52 | ## Filtering Methods 53 | 54 | ### format (default) 55 | 56 | This is the default filtering option. Formats the date against a string of tokens. See for a list of tokens and examples. 57 | 58 | **Default** 59 | 60 | ```html 61 | {{ someDate | moment("YYYY") }} 62 | 63 | {{ someDate | moment("ddd, hA") }} 64 | 65 | {{ someDate | moment("dddd, MMMM Do YYYY, h:mm:ss a") }} 66 | 67 | ``` 68 | 69 | For more information about `moment#format`, check out . 70 | 71 | 72 | ### from 73 | 74 | Display a Moment in relative time, either from now or from a specified date. 75 | 76 | **Default** (calculates from current time) 77 | 78 | ```html 79 | {{ someDate | moment("from", "now") }} 80 | 81 | {{ someDate | moment("from") }} 82 | ``` 83 | 84 | **With a reference time given** 85 | 86 | ```html 87 | {{ someDate | moment("from", "Jan. 11th, 1985") }} 88 | ``` 89 | 90 | **With suffix hidden** (e.g. '4 days ago' -> '4 days') 91 | 92 | ```html 93 | {{ someDate | moment("from", "now", true) }} 94 | 95 | {{ someDate | moment("from", true) }} 96 | 97 | {{ someDate | moment("from", "Jan. 11th, 2000", true) }} 98 | ``` 99 | 100 | For more information about `moment#fromNow` and `moment#from`, check out and . 101 | 102 | 103 | ### calendar 104 | 105 | Formats a date with different strings depending on how close to a certain date (today by default) the date is. You can also pass a reference date and options. 106 | 107 | **Default** (calculates from current time) 108 | 109 | ```html 110 | {{ someDate | moment("calendar") }} 111 | 112 | ``` 113 | 114 | **With a reference time given** 115 | 116 | ```html 117 | {{ someDate | moment("calendar", "July 10 2011") }} 118 | 119 | ``` 120 | 121 | **With options** 122 | 123 | ```html 124 | {{ new Date() | moment('add', '6 days', 'calendar', null, { nextWeek: '[Happens in a week]' }) }} 125 | 126 | ``` 127 | 128 | For more information about `moment#calendar`, check out . 129 | 130 | 131 | ### add 132 | 133 | Mutates the original Moment by adding time. 134 | 135 | ```html 136 | {{ someDate | moment("add", "7 days") }} 137 | 138 | {{ someDate | moment("add", "1 year, 3 months, 30 weeks, 10 days") }} 139 | ``` 140 | 141 | For more information about `moment#add`, check out . 142 | 143 | 144 | ### subtract 145 | 146 | Works the same as `add`, but mutates the original moment by subtracting time. 147 | 148 | ```html 149 | {{ someDate | moment("subtract", "3 hours") }} 150 | ``` 151 | 152 | For more information about `moment#subtract`, check out . 153 | 154 | ### timezone 155 | 156 | Convert the date to a certain timezone 157 | 158 | ```html 159 | {{ date | moment('timezone', 'America/Los_Angeles', 'LLLL ss')}} 160 | ``` 161 | 162 | **To use this filter you will need to pass `moment-timezone` through to the plugin** 163 | 164 | ```js 165 | // main.js 166 | import Vue from 'vue' 167 | import VueMoment from 'vue-moment' 168 | import moment from 'moment-timezone' 169 | 170 | Vue.use(VueMoment, { 171 | moment, 172 | }) 173 | ``` 174 | 175 | For more information about `moment#timezone`, check out . 176 | 177 | 178 | ## Chaining 179 | 180 | There's some built-in (and not thoroughly tested) support for chaining, like so: 181 | 182 | ```html 183 | {{ someDate | moment("add", "2 years, 8 days", "subtract", "3 hours", "ddd, hA") }} 184 | ``` 185 | 186 | This would add 2 years and 8 months to the date, then subtract 3 hours, then format the resulting date. 187 | 188 | 189 | ## Durations 190 | 191 | `vue-moment` also provides a `duration` filter that leverages Moment's ability to parse, manipulate and display durations of time. Durations should be passed as either: a String of a valid ISO 8601 formatted duration, a Number of milliseconds, an Array containing a number and unit of measurement (for passing a number other than milliseconds), or an Object of values (for when multiple different units of measurement are needed). 192 | 193 | ```html 194 | {{ 3600000 | duration('humanize') }} 195 | 196 | {{ 'PT1800S' | duration('humanize') }} 197 | 198 | {{ [35, 'days'] | duration('humanize', true) }} 199 | 200 | ``` 201 | 202 | This filter is purely a pass-through proxy to `moment.duration` methods, so pretty much all the functions outlined in their [docs](https://momentjs.com/docs/#/durations/) are callable. 203 | 204 | ```html 205 | {{ [-1, 'minutes'] | duration('humanize', true) }} 206 | 207 | {{ { days: 10, months: 1 } | duration('asDays') }} 208 | 209 | {{ 'P3D' | duration('as', 'hours') }} 210 | 211 | ``` 212 | 213 | For manipulating a duration by either subtraction or addition, first use the relevant filter option, then chain your duration display filter. 214 | 215 | ```html 216 | {{ [1, 'minutes'] | duration('subtract', 120000) | duration('humanize', true) }} 217 | 218 | {{ [-10, 'minutes'] | duration('add', 'PT11M') | duration('humanize', true) }} 219 | 220 | {{ [2, 'years'] | duration('add', 1, 'year') | duration('humanize') }} 221 | 222 | ``` 223 | 224 | `duration` is for contextless lengths of time; for comparing 2 dates, use the `diff` method rather than hacking around with Moment durations. For more information about `moment#duration`, check out . 225 | 226 | 227 | ## Configuration 228 | 229 | `vue-moment` should respect any global Moment customizations, including i18n locales. For more info, check out . 230 | 231 | You can also pass a custom Moment object through with the plugin options. This technique is especially useful for overcoming the browserify locale bug demonstrated in the docs 232 | 233 | ```js 234 | const moment = require('moment') 235 | require('moment/locale/es') 236 | 237 | Vue.use(require('vue-moment'), { 238 | moment 239 | }) 240 | 241 | console.log(Vue.moment().locale()) //es 242 | ``` 243 | 244 | ## this.$moment 245 | 246 | `vue-moment` attaches the momentjs instance to your Vue app as `this.$moment`. 247 | 248 | This allows you to call [the static methods momentjs provides](https://momentjs.com/docs/#/i18n/listing-months-weekdays/). 249 | 250 | If you're using i18n, it allows you to change the locale globally by calling `this.$moment.locale(myNewLocale)` 251 | 252 | -------------------------------------------------------------------------------- /tests/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "jest": true, 5 | }, 6 | "rules": { 7 | "no-console": 0, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/vue-moment.spec.js: -------------------------------------------------------------------------------- 1 | import moment from 'moment-timezone'; 2 | import Vue from 'vue/dist/vue'; 3 | import VueMoment from '../vue-moment'; 4 | 5 | Vue.use(VueMoment, { 6 | moment, 7 | }); 8 | 9 | const now = moment(); 10 | const tomorrow = moment().add(1, 'day'); 11 | const period = 'P1D'; 12 | 13 | const vm = new Vue({ 14 | template: '
{{ now | moment(...args) }}
', 15 | data() { 16 | return { 17 | now, 18 | args: [ 19 | 'YYYY-MM-DD', 20 | ], 21 | }; 22 | }, 23 | }).$mount(); 24 | 25 | const vmd = new Vue({ 26 | template: '
{{ period | duration(...args) | duration(...formatter) }}
', 27 | data() { 28 | return { 29 | period, 30 | args: [], 31 | formatter: ['humanize', true], 32 | }; 33 | }, 34 | }).$mount(); 35 | 36 | describe('VueMoment', () => { 37 | describe('installing plugin', () => { 38 | it('loads prototype', () => { 39 | expect(typeof vm.$moment).toEqual('function'); 40 | }); 41 | 42 | it('prototype works', () => { 43 | expect(vm.$moment(now).format('YYYY-MM-DD')).toEqual(now.format('YYYY-MM-DD')); 44 | }); 45 | 46 | it('sets locale', () => { 47 | vm.$moment.locale('fr'); 48 | expect(vm.$moment.locale()).toEqual('fr'); 49 | vm.$moment.locale('en'); 50 | }); 51 | }); 52 | 53 | describe('using filter', () => { 54 | it('formats date', () => { 55 | expect(vm.$el.textContent).toContain(now.format('YYYY-MM-DD')); 56 | }); 57 | 58 | describe('relative dates', () => { 59 | describe('from', () => { 60 | it('simple', (done) => { 61 | vm.args = ['from']; 62 | vm.$nextTick(() => { 63 | expect(vm.$el.textContent).toContain('a few seconds ago'); 64 | done(); 65 | }); 66 | }); 67 | 68 | it('change reference', (done) => { 69 | vm.args = ['from', tomorrow]; 70 | vm.$nextTick(() => { 71 | expect(vm.$el.textContent).toContain('a day ago'); 72 | done(); 73 | }); 74 | }); 75 | 76 | it('remove prefix', (done) => { 77 | vm.args = ['from', tomorrow, true]; 78 | vm.$nextTick(() => { 79 | expect(vm.$el.textContent).toContain('a day'); 80 | done(); 81 | }); 82 | }); 83 | }); 84 | 85 | describe('calendar', () => { 86 | it('simple', (done) => { 87 | vm.args = ['calendar']; 88 | vm.$nextTick(() => { 89 | expect(vm.$el.textContent).toContain(now.calendar()); 90 | done(); 91 | }); 92 | }); 93 | 94 | it('with options', (done) => { 95 | vm.args = ['calendar', tomorrow, { lastDay: '[Yesterday]' }]; 96 | vm.$nextTick(() => { 97 | expect(vm.$el.textContent).toContain('Yesterday'); 98 | done(); 99 | }); 100 | }); 101 | }); 102 | 103 | describe('diff', () => { 104 | it('simple', (done) => { 105 | vm.args = ['diff', tomorrow, 'hours']; 106 | vm.$nextTick(() => { 107 | expect(vm.$el.textContent).toContain('24'); 108 | done(); 109 | }); 110 | }); 111 | }); 112 | }); 113 | 114 | describe('mutations', () => { 115 | it('add', (done) => { 116 | vm.args = ['add', '1 day']; 117 | vm.$nextTick(() => { 118 | expect(vm.$el.textContent).toContain(now.clone().add(1, 'days').toISOString()); 119 | done(); 120 | }); 121 | }); 122 | 123 | it('subtract', (done) => { 124 | vm.args = ['subtract', '1 day']; 125 | vm.$nextTick(() => { 126 | expect(vm.$el.textContent).toContain(now.clone().subtract(1, 'days').toISOString()); 127 | done(); 128 | }); 129 | }); 130 | 131 | it('utc', (done) => { 132 | vm.args = ['utc']; 133 | vm.$nextTick(() => { 134 | expect(vm.$el.textContent).toContain(now.clone().utc().toISOString()); 135 | done(); 136 | }); 137 | }); 138 | 139 | it('timezone', (done) => { 140 | vm.args = ['timezone', 'America/Los_Angeles']; 141 | vm.$nextTick(() => { 142 | expect(vm.$el.textContent).toContain(now.clone().tz('America/Los_Angeles').toISOString()); 143 | done(); 144 | }); 145 | }); 146 | }); 147 | 148 | describe('chaining', () => { 149 | it('simple', (done) => { 150 | vm.args = ['add', '2 days', 'subtract', '1 day', 'YYYY-MM-DD']; 151 | vm.$nextTick(() => { 152 | expect(vm.$el.textContent).toContain(now.clone().add(1, 'days').format('YYYY-MM-DD')); 153 | done(); 154 | }); 155 | }); 156 | }); 157 | 158 | describe('durations', () => { 159 | afterEach(() => { 160 | vmd.period = period; 161 | vmd.args = []; 162 | vmd.formatter = ['humanize', true]; 163 | }); 164 | 165 | it('simple humanize', (done) => { 166 | vmd.$nextTick(() => { 167 | expect(vmd.$el.textContent).toContain('in a day'); 168 | done(); 169 | }); 170 | }); 171 | 172 | it('add', (done) => { 173 | vmd.args = ['add', 'P1D']; 174 | vmd.$nextTick(() => { 175 | expect(vmd.$el.textContent).toContain('in 2 days'); 176 | done(); 177 | }); 178 | }); 179 | 180 | it('subtract', (done) => { 181 | vmd.args = ['subtract', 'P2D']; 182 | vmd.$nextTick(() => { 183 | expect(vmd.$el.textContent).toContain('a day ago'); 184 | done(); 185 | }); 186 | }); 187 | 188 | it('to string', (done) => { 189 | vmd.period = [5, 'days']; 190 | vmd.formatter = ['toISOString']; 191 | vmd.$nextTick(() => { 192 | expect(vmd.$el.textContent).toContain('P5D'); 193 | done(); 194 | }); 195 | }); 196 | 197 | it('getter', (done) => { 198 | vmd.formatter = ['asHours']; 199 | vmd.$nextTick(() => { 200 | expect(vmd.$el.textContent).toContain('24'); 201 | done(); 202 | }); 203 | }); 204 | }); 205 | }); 206 | 207 | describe('handle inputs', () => { 208 | beforeEach(() => { 209 | global.console.warn = jest.fn(); 210 | }); 211 | 212 | afterAll(() => { 213 | vm.now = moment(); 214 | }); 215 | 216 | it('handles string', (done) => { 217 | vm.now = '2017-01-01'; 218 | vm.args = ['YYYY-MM-DD']; 219 | vm.$nextTick(() => { 220 | expect(console.warn).not.toBeCalled(); 221 | expect(vm.$el.textContent).toContain('2017-01-01'); 222 | done(); 223 | }); 224 | }); 225 | 226 | it('handles numeric: seconds', (done) => { 227 | vm.now = 1484438400; 228 | vm.args = ['YYYY-MM']; 229 | vm.$nextTick(() => { 230 | expect(console.warn).not.toBeCalled(); 231 | expect(vm.$el.textContent).toContain('2017-01'); 232 | done(); 233 | }); 234 | }); 235 | 236 | it('handles numeric: milliseconds', (done) => { 237 | vm.now = 1484438400000; 238 | vm.args = ['YYYY-MM']; 239 | vm.$nextTick(() => { 240 | expect(console.warn).not.toBeCalled(); 241 | expect(vm.$el.textContent).toContain('2017-01'); 242 | done(); 243 | }); 244 | }); 245 | 246 | it('handles object', (done) => { 247 | vm.now = { y: 2017, m: 1, d: 1 }; 248 | vm.args = ['YYYY-MM-DD']; 249 | vm.$nextTick(() => { 250 | expect(console.warn).not.toBeCalled(); 251 | expect(vm.$el.textContent).toContain('2017-01-01'); 252 | done(); 253 | }); 254 | }); 255 | 256 | it('handles Date object', (done) => { 257 | vm.now = new Date(2017, 0, 1); 258 | vm.args = ['YYYY-MM-DD']; 259 | vm.$nextTick(() => { 260 | expect(console.warn).not.toBeCalled(); 261 | expect(vm.$el.textContent).toContain('2017-01-01'); 262 | done(); 263 | }); 264 | }); 265 | 266 | it('handles Moment object', (done) => { 267 | vm.now = moment('2017-01-01'); 268 | vm.args = ['YYYY-MM-DD']; 269 | vm.$nextTick(() => { 270 | expect(console.warn).not.toBeCalled(); 271 | expect(vm.$el.textContent).toContain('2017-01-01'); 272 | done(); 273 | }); 274 | }); 275 | 276 | it('handles undefined', (done) => { 277 | vm.now = undefined; 278 | vm.$nextTick(() => { 279 | expect(console.warn).toBeCalled(); 280 | done(); 281 | }); 282 | }); 283 | 284 | it('handles invalid string', (done) => { 285 | vm.now = 'foo'; 286 | vm.$nextTick(() => { 287 | expect(console.warn).toBeCalled(); 288 | expect(vm.$el.textContent).toContain('foo'); 289 | done(); 290 | }); 291 | }); 292 | }); 293 | }); 294 | -------------------------------------------------------------------------------- /vue-moment.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | install(Vue, options) { 3 | const moment = options && options.moment ? options.moment : require('moment'); 4 | 5 | Object.defineProperties(Vue.prototype, { 6 | $moment: { 7 | get() { 8 | return moment; 9 | }, 10 | }, 11 | }); 12 | 13 | Vue.moment = moment; 14 | 15 | Vue.filter('moment', (...args) => { 16 | args = Array.prototype.slice.call(args); 17 | const input = args.shift(); 18 | let date; 19 | 20 | if (Array.isArray(input) && typeof input[0] === 'string') { 21 | // If input is array, assume we're being passed a format pattern to parse against. 22 | // Format pattern will accept an array of potential formats to parse against. 23 | // Date string should be at [0], format pattern(s) should be at [1] 24 | date = moment(input[0], input[1], true); 25 | } else if (typeof input === 'number') { 26 | if (input.toString().length < 12) { 27 | // If input is an integer with fewer than 12 digits, assume Unix seconds... 28 | date = moment.unix(input); 29 | } else { 30 | // ..otherwise, assume milliseconds. 31 | date = moment(input); 32 | } 33 | } else { 34 | // Otherwise, throw the input at moment and see what happens... 35 | date = moment(input); 36 | } 37 | 38 | if (!input || !date.isValid()) { 39 | // Log a warning if moment couldn't reconcile the input. Better than throwing an error? 40 | console.warn('Could not build a valid `moment` object from input.'); 41 | return input; 42 | } 43 | 44 | function parse(...args) { 45 | args = Array.prototype.slice.call(args); 46 | const method = args.shift(); 47 | 48 | switch (method) { 49 | case 'add': { 50 | /* 51 | * Mutates the original moment by adding time. 52 | * http://momentjs.com/docs/#/manipulating/add/ 53 | */ 54 | 55 | const addends = args.shift() 56 | .split(',') 57 | .map(Function.prototype.call, String.prototype.trim); 58 | const obj = {}; 59 | 60 | for (let n = 0; n < addends.length; n++) { 61 | const addend = addends[n].split(' '); 62 | obj[addend[1]] = addend[0]; 63 | } 64 | date.add(obj); 65 | break; 66 | } 67 | 68 | case 'subtract': { 69 | /* 70 | * Mutates the original moment by subtracting time. 71 | * http://momentjs.com/docs/#/manipulating/subtract/ 72 | */ 73 | 74 | const subtrahends = args.shift() 75 | .split(',') 76 | .map(Function.prototype.call, String.prototype.trim); 77 | const obj = {}; 78 | 79 | for (let n = 0; n < subtrahends.length; n++) { 80 | const subtrahend = subtrahends[n].split(' '); 81 | obj[subtrahend[1]] = subtrahend[0]; 82 | } 83 | date.subtract(obj); 84 | break; 85 | } 86 | 87 | case 'from': { 88 | /* 89 | * Display a moment in relative time, either from now or from a specified date. 90 | * http://momentjs.com/docs/#/displaying/fromnow/ 91 | */ 92 | 93 | let from = 'now'; 94 | let removeSuffix = false; 95 | 96 | if (args[0] === 'now') args.shift(); 97 | // If valid, assume it is a date we want the output computed against. 98 | if (moment(args[0]).isValid()) from = moment(args.shift()); 99 | 100 | if (args[0] === true) { 101 | args.shift(); 102 | removeSuffix = true; 103 | } 104 | 105 | if (from !== 'now') { 106 | date = date.from(from, removeSuffix); 107 | } else { 108 | date = date.fromNow(removeSuffix); 109 | } 110 | break; 111 | } 112 | 113 | case 'diff': { 114 | /* 115 | * Mutates the original moment by doing a difference with another date. 116 | * http://momentjs.com/docs/#/displaying/difference/ 117 | */ 118 | 119 | let referenceTime = moment(); 120 | let units = ''; 121 | let float = false; 122 | 123 | if (moment(args[0]).isValid()) { 124 | // If valid, assume it is a date we want the output computed against. 125 | referenceTime = moment(args.shift()); 126 | } else if (args[0] === null || args[0] === 'now') { 127 | // If null or 'now', remove argument and proceed with default referenceTime. 128 | args.shift(); 129 | } 130 | 131 | if (args[0]) units = args.shift(); 132 | 133 | if (args[0] === true) float = args.shift(); 134 | 135 | date = date.diff(referenceTime, units, float); 136 | break; 137 | } 138 | 139 | case 'calendar': { 140 | /* 141 | * Formats a date with different strings depending on how close 142 | * to a certain date (today by default) the date is. 143 | * http://momentjs.com/docs/#/displaying/calendar-time/ 144 | */ 145 | 146 | let referenceTime = moment(); 147 | let formats = {}; 148 | 149 | if (moment(args[0]).isValid()) { 150 | // If valid, assume it is a date we want the output computed against. 151 | referenceTime = moment(args.shift()); 152 | } else if (args[0] === null || args[0] === 'now') { 153 | // If null or 'now', remove argument and proceed with default referenceTime. 154 | args.shift(); 155 | } 156 | 157 | if (typeof args[0] === 'object') formats = args.shift(); 158 | 159 | date = date.calendar(referenceTime, formats); 160 | break; 161 | } 162 | 163 | case 'utc': { 164 | /* 165 | * Mutates the original moment by converting to UTC 166 | * https://momentjs.com/docs/#/manipulating/utc/ 167 | */ 168 | date.utc(); 169 | break; 170 | } 171 | 172 | case 'timezone': { 173 | /* 174 | * Mutates the original moment by converting to a new timezone. 175 | * https://momentjs.com/timezone/docs/#/using-timezones/converting-to-zone/ 176 | */ 177 | date.tz(args.shift()); 178 | break; 179 | } 180 | 181 | default: { 182 | /* 183 | * Formats a date by taking a string of tokens and replacing 184 | * them with their corresponding values. 185 | * http://momentjs.com/docs/#/displaying/format/ 186 | */ 187 | 188 | const format = method; 189 | date = date.format(format); 190 | } 191 | } 192 | 193 | if (args.length) parse.apply(parse, args); 194 | } 195 | 196 | parse.apply(parse, args); 197 | 198 | return date; 199 | }); 200 | 201 | Vue.filter('duration', (...args) => { 202 | /* 203 | * Basic pass-through filter for leveraging moment.js's ability 204 | * to manipulate and display durations. 205 | * https://momentjs.com/docs/#/durations/ 206 | */ 207 | args = Array.prototype.slice.call(args); 208 | const input = args.shift(); 209 | const method = args.shift(); 210 | 211 | function createDuration(time) { 212 | if (!Array.isArray(time)) time = [time]; 213 | const result = moment.duration(...time); 214 | if (!result.isValid()) console.warn('Could not build a valid `duration` object from input.'); 215 | return result; 216 | } 217 | let duration = createDuration(input); 218 | 219 | if (method === 'add' || method === 'subtract') { 220 | // Generates a duration object and either adds or subtracts it 221 | // from our original duration. 222 | const durationChange = createDuration(args); 223 | duration[method](durationChange); 224 | } else if (duration && duration[method]) { 225 | // This gives a full proxy to moment.duration functions. 226 | duration = duration[method](...args); 227 | } 228 | 229 | return duration; 230 | }); 231 | }, 232 | }; 233 | --------------------------------------------------------------------------------