[400] | 1 | // moment.js |
---|
| 2 | // version : 2.0.0 |
---|
| 3 | // author : Tim Wood |
---|
| 4 | // license : MIT |
---|
| 5 | // momentjs.com |
---|
| 6 | |
---|
| 7 | (function (undefined) { |
---|
| 8 | |
---|
| 9 | /************************************ |
---|
| 10 | Constants |
---|
| 11 | ************************************/ |
---|
| 12 | |
---|
| 13 | var moment, |
---|
| 14 | VERSION = "2.0.0", |
---|
| 15 | round = Math.round, i, |
---|
| 16 | // internal storage for language config files |
---|
| 17 | languages = {}, |
---|
| 18 | |
---|
| 19 | // check for nodeJS |
---|
| 20 | hasModule = (typeof module !== 'undefined' && module.exports), |
---|
| 21 | |
---|
| 22 | // ASP.NET json date format regex |
---|
| 23 | aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, |
---|
| 24 | |
---|
| 25 | // format tokens |
---|
| 26 | formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g, |
---|
| 27 | localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, |
---|
| 28 | |
---|
| 29 | // parsing tokens |
---|
| 30 | parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi, |
---|
| 31 | |
---|
| 32 | // parsing token regexes |
---|
| 33 | parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 |
---|
| 34 | parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 |
---|
| 35 | parseTokenThreeDigits = /\d{3}/, // 000 - 999 |
---|
| 36 | parseTokenFourDigits = /\d{1,4}/, // 0 - 9999 |
---|
| 37 | parseTokenSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 |
---|
| 38 | parseTokenWord = /[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i, // any word (or two) characters or numbers including two word month in arabic. |
---|
| 39 | parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z |
---|
| 40 | parseTokenT = /T/i, // T (ISO seperator) |
---|
| 41 | parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 |
---|
| 42 | |
---|
| 43 | // preliminary iso regex |
---|
| 44 | // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 |
---|
| 45 | isoRegex = /^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/, |
---|
| 46 | isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', |
---|
| 47 | |
---|
| 48 | // iso time formats and regexes |
---|
| 49 | isoTimes = [ |
---|
| 50 | ['HH:mm:ss.S', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/], |
---|
| 51 | ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], |
---|
| 52 | ['HH:mm', /(T| )\d\d:\d\d/], |
---|
| 53 | ['HH', /(T| )\d\d/] |
---|
| 54 | ], |
---|
| 55 | |
---|
| 56 | // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"] |
---|
| 57 | parseTimezoneChunker = /([\+\-]|\d\d)/gi, |
---|
| 58 | |
---|
| 59 | // getter and setter names |
---|
| 60 | proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), |
---|
| 61 | unitMillisecondFactors = { |
---|
| 62 | 'Milliseconds' : 1, |
---|
| 63 | 'Seconds' : 1e3, |
---|
| 64 | 'Minutes' : 6e4, |
---|
| 65 | 'Hours' : 36e5, |
---|
| 66 | 'Days' : 864e5, |
---|
| 67 | 'Months' : 2592e6, |
---|
| 68 | 'Years' : 31536e6 |
---|
| 69 | }, |
---|
| 70 | |
---|
| 71 | // format function strings |
---|
| 72 | formatFunctions = {}, |
---|
| 73 | |
---|
| 74 | // tokens to ordinalize and pad |
---|
| 75 | ordinalizeTokens = 'DDD w W M D d'.split(' '), |
---|
| 76 | paddedTokens = 'M D H h m s w W'.split(' '), |
---|
| 77 | |
---|
| 78 | formatTokenFunctions = { |
---|
| 79 | M : function () { |
---|
| 80 | return this.month() + 1; |
---|
| 81 | }, |
---|
| 82 | MMM : function (format) { |
---|
| 83 | return this.lang().monthsShort(this, format); |
---|
| 84 | }, |
---|
| 85 | MMMM : function (format) { |
---|
| 86 | return this.lang().months(this, format); |
---|
| 87 | }, |
---|
| 88 | D : function () { |
---|
| 89 | return this.date(); |
---|
| 90 | }, |
---|
| 91 | DDD : function () { |
---|
| 92 | return this.dayOfYear(); |
---|
| 93 | }, |
---|
| 94 | d : function () { |
---|
| 95 | return this.day(); |
---|
| 96 | }, |
---|
| 97 | dd : function (format) { |
---|
| 98 | return this.lang().weekdaysMin(this, format); |
---|
| 99 | }, |
---|
| 100 | ddd : function (format) { |
---|
| 101 | return this.lang().weekdaysShort(this, format); |
---|
| 102 | }, |
---|
| 103 | dddd : function (format) { |
---|
| 104 | return this.lang().weekdays(this, format); |
---|
| 105 | }, |
---|
| 106 | w : function () { |
---|
| 107 | return this.week(); |
---|
| 108 | }, |
---|
| 109 | W : function () { |
---|
| 110 | return this.isoWeek(); |
---|
| 111 | }, |
---|
| 112 | YY : function () { |
---|
| 113 | return leftZeroFill(this.year() % 100, 2); |
---|
| 114 | }, |
---|
| 115 | YYYY : function () { |
---|
| 116 | return leftZeroFill(this.year(), 4); |
---|
| 117 | }, |
---|
| 118 | YYYYY : function () { |
---|
| 119 | return leftZeroFill(this.year(), 5); |
---|
| 120 | }, |
---|
| 121 | a : function () { |
---|
| 122 | return this.lang().meridiem(this.hours(), this.minutes(), true); |
---|
| 123 | }, |
---|
| 124 | A : function () { |
---|
| 125 | return this.lang().meridiem(this.hours(), this.minutes(), false); |
---|
| 126 | }, |
---|
| 127 | H : function () { |
---|
| 128 | return this.hours(); |
---|
| 129 | }, |
---|
| 130 | h : function () { |
---|
| 131 | return this.hours() % 12 || 12; |
---|
| 132 | }, |
---|
| 133 | m : function () { |
---|
| 134 | return this.minutes(); |
---|
| 135 | }, |
---|
| 136 | s : function () { |
---|
| 137 | return this.seconds(); |
---|
| 138 | }, |
---|
| 139 | S : function () { |
---|
| 140 | return ~~(this.milliseconds() / 100); |
---|
| 141 | }, |
---|
| 142 | SS : function () { |
---|
| 143 | return leftZeroFill(~~(this.milliseconds() / 10), 2); |
---|
| 144 | }, |
---|
| 145 | SSS : function () { |
---|
| 146 | return leftZeroFill(this.milliseconds(), 3); |
---|
| 147 | }, |
---|
| 148 | Z : function () { |
---|
| 149 | var a = -this.zone(), |
---|
| 150 | b = "+"; |
---|
| 151 | if (a < 0) { |
---|
| 152 | a = -a; |
---|
| 153 | b = "-"; |
---|
| 154 | } |
---|
| 155 | return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2); |
---|
| 156 | }, |
---|
| 157 | ZZ : function () { |
---|
| 158 | var a = -this.zone(), |
---|
| 159 | b = "+"; |
---|
| 160 | if (a < 0) { |
---|
| 161 | a = -a; |
---|
| 162 | b = "-"; |
---|
| 163 | } |
---|
| 164 | return b + leftZeroFill(~~(10 * a / 6), 4); |
---|
| 165 | }, |
---|
| 166 | X : function () { |
---|
| 167 | return this.unix(); |
---|
| 168 | } |
---|
| 169 | }; |
---|
| 170 | |
---|
| 171 | function padToken(func, count) { |
---|
| 172 | return function (a) { |
---|
| 173 | return leftZeroFill(func.call(this, a), count); |
---|
| 174 | }; |
---|
| 175 | } |
---|
| 176 | function ordinalizeToken(func) { |
---|
| 177 | return function (a) { |
---|
| 178 | return this.lang().ordinal(func.call(this, a)); |
---|
| 179 | }; |
---|
| 180 | } |
---|
| 181 | |
---|
| 182 | while (ordinalizeTokens.length) { |
---|
| 183 | i = ordinalizeTokens.pop(); |
---|
| 184 | formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]); |
---|
| 185 | } |
---|
| 186 | while (paddedTokens.length) { |
---|
| 187 | i = paddedTokens.pop(); |
---|
| 188 | formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); |
---|
| 189 | } |
---|
| 190 | formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); |
---|
| 191 | |
---|
| 192 | |
---|
| 193 | /************************************ |
---|
| 194 | Constructors |
---|
| 195 | ************************************/ |
---|
| 196 | |
---|
| 197 | function Language() { |
---|
| 198 | |
---|
| 199 | } |
---|
| 200 | |
---|
| 201 | // Moment prototype object |
---|
| 202 | function Moment(config) { |
---|
| 203 | extend(this, config); |
---|
| 204 | } |
---|
| 205 | |
---|
| 206 | // Duration Constructor |
---|
| 207 | function Duration(duration) { |
---|
| 208 | var data = this._data = {}, |
---|
| 209 | years = duration.years || duration.year || duration.y || 0, |
---|
| 210 | months = duration.months || duration.month || duration.M || 0, |
---|
| 211 | weeks = duration.weeks || duration.week || duration.w || 0, |
---|
| 212 | days = duration.days || duration.day || duration.d || 0, |
---|
| 213 | hours = duration.hours || duration.hour || duration.h || 0, |
---|
| 214 | minutes = duration.minutes || duration.minute || duration.m || 0, |
---|
| 215 | seconds = duration.seconds || duration.second || duration.s || 0, |
---|
| 216 | milliseconds = duration.milliseconds || duration.millisecond || duration.ms || 0; |
---|
| 217 | |
---|
| 218 | // representation for dateAddRemove |
---|
| 219 | this._milliseconds = milliseconds + |
---|
| 220 | seconds * 1e3 + // 1000 |
---|
| 221 | minutes * 6e4 + // 1000 * 60 |
---|
| 222 | hours * 36e5; // 1000 * 60 * 60 |
---|
| 223 | // Because of dateAddRemove treats 24 hours as different from a |
---|
| 224 | // day when working around DST, we need to store them separately |
---|
| 225 | this._days = days + |
---|
| 226 | weeks * 7; |
---|
| 227 | // It is impossible translate months into days without knowing |
---|
| 228 | // which months you are are talking about, so we have to store |
---|
| 229 | // it separately. |
---|
| 230 | this._months = months + |
---|
| 231 | years * 12; |
---|
| 232 | |
---|
| 233 | // The following code bubbles up values, see the tests for |
---|
| 234 | // examples of what that means. |
---|
| 235 | data.milliseconds = milliseconds % 1000; |
---|
| 236 | seconds += absRound(milliseconds / 1000); |
---|
| 237 | |
---|
| 238 | data.seconds = seconds % 60; |
---|
| 239 | minutes += absRound(seconds / 60); |
---|
| 240 | |
---|
| 241 | data.minutes = minutes % 60; |
---|
| 242 | hours += absRound(minutes / 60); |
---|
| 243 | |
---|
| 244 | data.hours = hours % 24; |
---|
| 245 | days += absRound(hours / 24); |
---|
| 246 | |
---|
| 247 | days += weeks * 7; |
---|
| 248 | data.days = days % 30; |
---|
| 249 | |
---|
| 250 | months += absRound(days / 30); |
---|
| 251 | |
---|
| 252 | data.months = months % 12; |
---|
| 253 | years += absRound(months / 12); |
---|
| 254 | |
---|
| 255 | data.years = years; |
---|
| 256 | } |
---|
| 257 | |
---|
| 258 | |
---|
| 259 | /************************************ |
---|
| 260 | Helpers |
---|
| 261 | ************************************/ |
---|
| 262 | |
---|
| 263 | |
---|
| 264 | function extend(a, b) { |
---|
| 265 | for (var i in b) { |
---|
| 266 | if (b.hasOwnProperty(i)) { |
---|
| 267 | a[i] = b[i]; |
---|
| 268 | } |
---|
| 269 | } |
---|
| 270 | return a; |
---|
| 271 | } |
---|
| 272 | |
---|
| 273 | function absRound(number) { |
---|
| 274 | if (number < 0) { |
---|
| 275 | return Math.ceil(number); |
---|
| 276 | } else { |
---|
| 277 | return Math.floor(number); |
---|
| 278 | } |
---|
| 279 | } |
---|
| 280 | |
---|
| 281 | // left zero fill a number |
---|
| 282 | // see http://jsperf.com/left-zero-filling for performance comparison |
---|
| 283 | function leftZeroFill(number, targetLength) { |
---|
| 284 | var output = number + ''; |
---|
| 285 | while (output.length < targetLength) { |
---|
| 286 | output = '0' + output; |
---|
| 287 | } |
---|
| 288 | return output; |
---|
| 289 | } |
---|
| 290 | |
---|
| 291 | // helper function for _.addTime and _.subtractTime |
---|
| 292 | function addOrSubtractDurationFromMoment(mom, duration, isAdding) { |
---|
| 293 | var ms = duration._milliseconds, |
---|
| 294 | d = duration._days, |
---|
| 295 | M = duration._months, |
---|
| 296 | currentDate; |
---|
| 297 | |
---|
| 298 | if (ms) { |
---|
| 299 | mom._d.setTime(+mom + ms * isAdding); |
---|
| 300 | } |
---|
| 301 | if (d) { |
---|
| 302 | mom.date(mom.date() + d * isAdding); |
---|
| 303 | } |
---|
| 304 | if (M) { |
---|
| 305 | currentDate = mom.date(); |
---|
| 306 | mom.date(1) |
---|
| 307 | .month(mom.month() + M * isAdding) |
---|
| 308 | .date(Math.min(currentDate, mom.daysInMonth())); |
---|
| 309 | } |
---|
| 310 | } |
---|
| 311 | |
---|
| 312 | // check if is an array |
---|
| 313 | function isArray(input) { |
---|
| 314 | return Object.prototype.toString.call(input) === '[object Array]'; |
---|
| 315 | } |
---|
| 316 | |
---|
| 317 | // compare two arrays, return the number of differences |
---|
| 318 | function compareArrays(array1, array2) { |
---|
| 319 | var len = Math.min(array1.length, array2.length), |
---|
| 320 | lengthDiff = Math.abs(array1.length - array2.length), |
---|
| 321 | diffs = 0, |
---|
| 322 | i; |
---|
| 323 | for (i = 0; i < len; i++) { |
---|
| 324 | if (~~array1[i] !== ~~array2[i]) { |
---|
| 325 | diffs++; |
---|
| 326 | } |
---|
| 327 | } |
---|
| 328 | return diffs + lengthDiff; |
---|
| 329 | } |
---|
| 330 | |
---|
| 331 | |
---|
| 332 | /************************************ |
---|
| 333 | Languages |
---|
| 334 | ************************************/ |
---|
| 335 | |
---|
| 336 | |
---|
| 337 | Language.prototype = { |
---|
| 338 | set : function (config) { |
---|
| 339 | var prop, i; |
---|
| 340 | for (i in config) { |
---|
| 341 | prop = config[i]; |
---|
| 342 | if (typeof prop === 'function') { |
---|
| 343 | this[i] = prop; |
---|
| 344 | } else { |
---|
| 345 | this['_' + i] = prop; |
---|
| 346 | } |
---|
| 347 | } |
---|
| 348 | }, |
---|
| 349 | |
---|
| 350 | _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), |
---|
| 351 | months : function (m) { |
---|
| 352 | return this._months[m.month()]; |
---|
| 353 | }, |
---|
| 354 | |
---|
| 355 | _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), |
---|
| 356 | monthsShort : function (m) { |
---|
| 357 | return this._monthsShort[m.month()]; |
---|
| 358 | }, |
---|
| 359 | |
---|
| 360 | monthsParse : function (monthName) { |
---|
| 361 | var i, mom, regex, output; |
---|
| 362 | |
---|
| 363 | if (!this._monthsParse) { |
---|
| 364 | this._monthsParse = []; |
---|
| 365 | } |
---|
| 366 | |
---|
| 367 | for (i = 0; i < 12; i++) { |
---|
| 368 | // make the regex if we don't have it already |
---|
| 369 | if (!this._monthsParse[i]) { |
---|
| 370 | mom = moment([2000, i]); |
---|
| 371 | regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); |
---|
| 372 | this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); |
---|
| 373 | } |
---|
| 374 | // test the regex |
---|
| 375 | if (this._monthsParse[i].test(monthName)) { |
---|
| 376 | return i; |
---|
| 377 | } |
---|
| 378 | } |
---|
| 379 | }, |
---|
| 380 | |
---|
| 381 | _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), |
---|
| 382 | weekdays : function (m) { |
---|
| 383 | return this._weekdays[m.day()]; |
---|
| 384 | }, |
---|
| 385 | |
---|
| 386 | _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), |
---|
| 387 | weekdaysShort : function (m) { |
---|
| 388 | return this._weekdaysShort[m.day()]; |
---|
| 389 | }, |
---|
| 390 | |
---|
| 391 | _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), |
---|
| 392 | weekdaysMin : function (m) { |
---|
| 393 | return this._weekdaysMin[m.day()]; |
---|
| 394 | }, |
---|
| 395 | |
---|
| 396 | _longDateFormat : { |
---|
| 397 | LT : "h:mm A", |
---|
| 398 | L : "MM/DD/YYYY", |
---|
| 399 | LL : "MMMM D YYYY", |
---|
| 400 | LLL : "MMMM D YYYY LT", |
---|
| 401 | LLLL : "dddd, MMMM D YYYY LT" |
---|
| 402 | }, |
---|
| 403 | longDateFormat : function (key) { |
---|
| 404 | var output = this._longDateFormat[key]; |
---|
| 405 | if (!output && this._longDateFormat[key.toUpperCase()]) { |
---|
| 406 | output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { |
---|
| 407 | return val.slice(1); |
---|
| 408 | }); |
---|
| 409 | this._longDateFormat[key] = output; |
---|
| 410 | } |
---|
| 411 | return output; |
---|
| 412 | }, |
---|
| 413 | |
---|
| 414 | meridiem : function (hours, minutes, isLower) { |
---|
| 415 | if (hours > 11) { |
---|
| 416 | return isLower ? 'pm' : 'PM'; |
---|
| 417 | } else { |
---|
| 418 | return isLower ? 'am' : 'AM'; |
---|
| 419 | } |
---|
| 420 | }, |
---|
| 421 | |
---|
| 422 | _calendar : { |
---|
| 423 | sameDay : '[Today at] LT', |
---|
| 424 | nextDay : '[Tomorrow at] LT', |
---|
| 425 | nextWeek : 'dddd [at] LT', |
---|
| 426 | lastDay : '[Yesterday at] LT', |
---|
| 427 | lastWeek : '[last] dddd [at] LT', |
---|
| 428 | sameElse : 'L' |
---|
| 429 | }, |
---|
| 430 | calendar : function (key, mom) { |
---|
| 431 | var output = this._calendar[key]; |
---|
| 432 | return typeof output === 'function' ? output.apply(mom) : output; |
---|
| 433 | }, |
---|
| 434 | |
---|
| 435 | _relativeTime : { |
---|
| 436 | future : "in %s", |
---|
| 437 | past : "%s ago", |
---|
| 438 | s : "a few seconds", |
---|
| 439 | m : "a minute", |
---|
| 440 | mm : "%d minutes", |
---|
| 441 | h : "an hour", |
---|
| 442 | hh : "%d hours", |
---|
| 443 | d : "a day", |
---|
| 444 | dd : "%d days", |
---|
| 445 | M : "a month", |
---|
| 446 | MM : "%d months", |
---|
| 447 | y : "a year", |
---|
| 448 | yy : "%d years" |
---|
| 449 | }, |
---|
| 450 | relativeTime : function (number, withoutSuffix, string, isFuture) { |
---|
| 451 | var output = this._relativeTime[string]; |
---|
| 452 | return (typeof output === 'function') ? |
---|
| 453 | output(number, withoutSuffix, string, isFuture) : |
---|
| 454 | output.replace(/%d/i, number); |
---|
| 455 | }, |
---|
| 456 | pastFuture : function (diff, output) { |
---|
| 457 | var format = this._relativeTime[diff > 0 ? 'future' : 'past']; |
---|
| 458 | return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); |
---|
| 459 | }, |
---|
| 460 | |
---|
| 461 | ordinal : function (number) { |
---|
| 462 | return this._ordinal.replace("%d", number); |
---|
| 463 | }, |
---|
| 464 | _ordinal : "%d", |
---|
| 465 | |
---|
| 466 | preparse : function (string) { |
---|
| 467 | return string; |
---|
| 468 | }, |
---|
| 469 | |
---|
| 470 | postformat : function (string) { |
---|
| 471 | return string; |
---|
| 472 | }, |
---|
| 473 | |
---|
| 474 | week : function (mom) { |
---|
| 475 | return weekOfYear(mom, this._week.dow, this._week.doy); |
---|
| 476 | }, |
---|
| 477 | _week : { |
---|
| 478 | dow : 0, // Sunday is the first day of the week. |
---|
| 479 | doy : 6 // The week that contains Jan 1st is the first week of the year. |
---|
| 480 | } |
---|
| 481 | }; |
---|
| 482 | |
---|
| 483 | // Loads a language definition into the `languages` cache. The function |
---|
| 484 | // takes a key and optionally values. If not in the browser and no values |
---|
| 485 | // are provided, it will load the language file module. As a convenience, |
---|
| 486 | // this function also returns the language values. |
---|
| 487 | function loadLang(key, values) { |
---|
| 488 | values.abbr = key; |
---|
| 489 | if (!languages[key]) { |
---|
| 490 | languages[key] = new Language(); |
---|
| 491 | } |
---|
| 492 | languages[key].set(values); |
---|
| 493 | return languages[key]; |
---|
| 494 | } |
---|
| 495 | |
---|
| 496 | // Determines which language definition to use and returns it. |
---|
| 497 | // |
---|
| 498 | // With no parameters, it will return the global language. If you |
---|
| 499 | // pass in a language key, such as 'en', it will return the |
---|
| 500 | // definition for 'en', so long as 'en' has already been loaded using |
---|
| 501 | // moment.lang. |
---|
| 502 | function getLangDefinition(key) { |
---|
| 503 | if (!key) { |
---|
| 504 | return moment.fn._lang; |
---|
| 505 | } |
---|
| 506 | if (!languages[key] && hasModule) { |
---|
| 507 | require('./lang/' + key); |
---|
| 508 | } |
---|
| 509 | return languages[key]; |
---|
| 510 | } |
---|
| 511 | |
---|
| 512 | |
---|
| 513 | /************************************ |
---|
| 514 | Formatting |
---|
| 515 | ************************************/ |
---|
| 516 | |
---|
| 517 | |
---|
| 518 | function removeFormattingTokens(input) { |
---|
| 519 | if (input.match(/\[.*\]/)) { |
---|
| 520 | return input.replace(/^\[|\]$/g, ""); |
---|
| 521 | } |
---|
| 522 | return input.replace(/\\/g, ""); |
---|
| 523 | } |
---|
| 524 | |
---|
| 525 | function makeFormatFunction(format) { |
---|
| 526 | var array = format.match(formattingTokens), i, length; |
---|
| 527 | |
---|
| 528 | for (i = 0, length = array.length; i < length; i++) { |
---|
| 529 | if (formatTokenFunctions[array[i]]) { |
---|
| 530 | array[i] = formatTokenFunctions[array[i]]; |
---|
| 531 | } else { |
---|
| 532 | array[i] = removeFormattingTokens(array[i]); |
---|
| 533 | } |
---|
| 534 | } |
---|
| 535 | |
---|
| 536 | return function (mom) { |
---|
| 537 | var output = ""; |
---|
| 538 | for (i = 0; i < length; i++) { |
---|
| 539 | output += typeof array[i].call === 'function' ? array[i].call(mom, format) : array[i]; |
---|
| 540 | } |
---|
| 541 | return output; |
---|
| 542 | }; |
---|
| 543 | } |
---|
| 544 | |
---|
| 545 | // format date using native date object |
---|
| 546 | function formatMoment(m, format) { |
---|
| 547 | var i = 5; |
---|
| 548 | |
---|
| 549 | function replaceLongDateFormatTokens(input) { |
---|
| 550 | return m.lang().longDateFormat(input) || input; |
---|
| 551 | } |
---|
| 552 | |
---|
| 553 | while (i-- && localFormattingTokens.test(format)) { |
---|
| 554 | format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); |
---|
| 555 | } |
---|
| 556 | |
---|
| 557 | if (!formatFunctions[format]) { |
---|
| 558 | formatFunctions[format] = makeFormatFunction(format); |
---|
| 559 | } |
---|
| 560 | |
---|
| 561 | return formatFunctions[format](m); |
---|
| 562 | } |
---|
| 563 | |
---|
| 564 | |
---|
| 565 | /************************************ |
---|
| 566 | Parsing |
---|
| 567 | ************************************/ |
---|
| 568 | |
---|
| 569 | |
---|
| 570 | // get the regex to find the next token |
---|
| 571 | function getParseRegexForToken(token) { |
---|
| 572 | switch (token) { |
---|
| 573 | case 'DDDD': |
---|
| 574 | return parseTokenThreeDigits; |
---|
| 575 | case 'YYYY': |
---|
| 576 | return parseTokenFourDigits; |
---|
| 577 | case 'YYYYY': |
---|
| 578 | return parseTokenSixDigits; |
---|
| 579 | case 'S': |
---|
| 580 | case 'SS': |
---|
| 581 | case 'SSS': |
---|
| 582 | case 'DDD': |
---|
| 583 | return parseTokenOneToThreeDigits; |
---|
| 584 | case 'MMM': |
---|
| 585 | case 'MMMM': |
---|
| 586 | case 'dd': |
---|
| 587 | case 'ddd': |
---|
| 588 | case 'dddd': |
---|
| 589 | case 'a': |
---|
| 590 | case 'A': |
---|
| 591 | return parseTokenWord; |
---|
| 592 | case 'X': |
---|
| 593 | return parseTokenTimestampMs; |
---|
| 594 | case 'Z': |
---|
| 595 | case 'ZZ': |
---|
| 596 | return parseTokenTimezone; |
---|
| 597 | case 'T': |
---|
| 598 | return parseTokenT; |
---|
| 599 | case 'MM': |
---|
| 600 | case 'DD': |
---|
| 601 | case 'YY': |
---|
| 602 | case 'HH': |
---|
| 603 | case 'hh': |
---|
| 604 | case 'mm': |
---|
| 605 | case 'ss': |
---|
| 606 | case 'M': |
---|
| 607 | case 'D': |
---|
| 608 | case 'd': |
---|
| 609 | case 'H': |
---|
| 610 | case 'h': |
---|
| 611 | case 'm': |
---|
| 612 | case 's': |
---|
| 613 | return parseTokenOneOrTwoDigits; |
---|
| 614 | default : |
---|
| 615 | return new RegExp(token.replace('\\', '')); |
---|
| 616 | } |
---|
| 617 | } |
---|
| 618 | |
---|
| 619 | // function to convert string input to date |
---|
| 620 | function addTimeToArrayFromToken(token, input, config) { |
---|
| 621 | var a, b, |
---|
| 622 | datePartArray = config._a; |
---|
| 623 | |
---|
| 624 | switch (token) { |
---|
| 625 | // MONTH |
---|
| 626 | case 'M' : // fall through to MM |
---|
| 627 | case 'MM' : |
---|
| 628 | datePartArray[1] = (input == null) ? 0 : ~~input - 1; |
---|
| 629 | break; |
---|
| 630 | case 'MMM' : // fall through to MMMM |
---|
| 631 | case 'MMMM' : |
---|
| 632 | a = getLangDefinition(config._l).monthsParse(input); |
---|
| 633 | // if we didn't find a month name, mark the date as invalid. |
---|
| 634 | if (a != null) { |
---|
| 635 | datePartArray[1] = a; |
---|
| 636 | } else { |
---|
| 637 | config._isValid = false; |
---|
| 638 | } |
---|
| 639 | break; |
---|
| 640 | // DAY OF MONTH |
---|
| 641 | case 'D' : // fall through to DDDD |
---|
| 642 | case 'DD' : // fall through to DDDD |
---|
| 643 | case 'DDD' : // fall through to DDDD |
---|
| 644 | case 'DDDD' : |
---|
| 645 | if (input != null) { |
---|
| 646 | datePartArray[2] = ~~input; |
---|
| 647 | } |
---|
| 648 | break; |
---|
| 649 | // YEAR |
---|
| 650 | case 'YY' : |
---|
| 651 | datePartArray[0] = ~~input + (~~input > 68 ? 1900 : 2000); |
---|
| 652 | break; |
---|
| 653 | case 'YYYY' : |
---|
| 654 | case 'YYYYY' : |
---|
| 655 | datePartArray[0] = ~~input; |
---|
| 656 | break; |
---|
| 657 | // AM / PM |
---|
| 658 | case 'a' : // fall through to A |
---|
| 659 | case 'A' : |
---|
| 660 | config._isPm = ((input + '').toLowerCase() === 'pm'); |
---|
| 661 | break; |
---|
| 662 | // 24 HOUR |
---|
| 663 | case 'H' : // fall through to hh |
---|
| 664 | case 'HH' : // fall through to hh |
---|
| 665 | case 'h' : // fall through to hh |
---|
| 666 | case 'hh' : |
---|
| 667 | datePartArray[3] = ~~input; |
---|
| 668 | break; |
---|
| 669 | // MINUTE |
---|
| 670 | case 'm' : // fall through to mm |
---|
| 671 | case 'mm' : |
---|
| 672 | datePartArray[4] = ~~input; |
---|
| 673 | break; |
---|
| 674 | // SECOND |
---|
| 675 | case 's' : // fall through to ss |
---|
| 676 | case 'ss' : |
---|
| 677 | datePartArray[5] = ~~input; |
---|
| 678 | break; |
---|
| 679 | // MILLISECOND |
---|
| 680 | case 'S' : |
---|
| 681 | case 'SS' : |
---|
| 682 | case 'SSS' : |
---|
| 683 | datePartArray[6] = ~~ (('0.' + input) * 1000); |
---|
| 684 | break; |
---|
| 685 | // UNIX TIMESTAMP WITH MS |
---|
| 686 | case 'X': |
---|
| 687 | config._d = new Date(parseFloat(input) * 1000); |
---|
| 688 | break; |
---|
| 689 | // TIMEZONE |
---|
| 690 | case 'Z' : // fall through to ZZ |
---|
| 691 | case 'ZZ' : |
---|
| 692 | config._useUTC = true; |
---|
| 693 | a = (input + '').match(parseTimezoneChunker); |
---|
| 694 | if (a && a[1]) { |
---|
| 695 | config._tzh = ~~a[1]; |
---|
| 696 | } |
---|
| 697 | if (a && a[2]) { |
---|
| 698 | config._tzm = ~~a[2]; |
---|
| 699 | } |
---|
| 700 | // reverse offsets |
---|
| 701 | if (a && a[0] === '+') { |
---|
| 702 | config._tzh = -config._tzh; |
---|
| 703 | config._tzm = -config._tzm; |
---|
| 704 | } |
---|
| 705 | break; |
---|
| 706 | } |
---|
| 707 | |
---|
| 708 | // if the input is null, the date is not valid |
---|
| 709 | if (input == null) { |
---|
| 710 | config._isValid = false; |
---|
| 711 | } |
---|
| 712 | } |
---|
| 713 | |
---|
| 714 | // convert an array to a date. |
---|
| 715 | // the array should mirror the parameters below |
---|
| 716 | // note: all values past the year are optional and will default to the lowest possible value. |
---|
| 717 | // [year, month, day , hour, minute, second, millisecond] |
---|
| 718 | function dateFromArray(config) { |
---|
| 719 | var i, date, input = []; |
---|
| 720 | |
---|
| 721 | if (config._d) { |
---|
| 722 | return; |
---|
| 723 | } |
---|
| 724 | |
---|
| 725 | for (i = 0; i < 7; i++) { |
---|
| 726 | config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; |
---|
| 727 | } |
---|
| 728 | |
---|
| 729 | // add the offsets to the time to be parsed so that we can have a clean array for checking isValid |
---|
| 730 | input[3] += config._tzh || 0; |
---|
| 731 | input[4] += config._tzm || 0; |
---|
| 732 | |
---|
| 733 | date = new Date(0); |
---|
| 734 | |
---|
| 735 | if (config._useUTC) { |
---|
| 736 | date.setUTCFullYear(input[0], input[1], input[2]); |
---|
| 737 | date.setUTCHours(input[3], input[4], input[5], input[6]); |
---|
| 738 | } else { |
---|
| 739 | date.setFullYear(input[0], input[1], input[2]); |
---|
| 740 | date.setHours(input[3], input[4], input[5], input[6]); |
---|
| 741 | } |
---|
| 742 | |
---|
| 743 | config._d = date; |
---|
| 744 | } |
---|
| 745 | |
---|
| 746 | // date from string and format string |
---|
| 747 | function makeDateFromStringAndFormat(config) { |
---|
| 748 | // This array is used to make a Date, either with `new Date` or `Date.UTC` |
---|
| 749 | var tokens = config._f.match(formattingTokens), |
---|
| 750 | string = config._i, |
---|
| 751 | i, parsedInput; |
---|
| 752 | |
---|
| 753 | config._a = []; |
---|
| 754 | |
---|
| 755 | for (i = 0; i < tokens.length; i++) { |
---|
| 756 | parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0]; |
---|
| 757 | if (parsedInput) { |
---|
| 758 | string = string.slice(string.indexOf(parsedInput) + parsedInput.length); |
---|
| 759 | } |
---|
| 760 | // don't parse if its not a known token |
---|
| 761 | if (formatTokenFunctions[tokens[i]]) { |
---|
| 762 | addTimeToArrayFromToken(tokens[i], parsedInput, config); |
---|
| 763 | } |
---|
| 764 | } |
---|
| 765 | // handle am pm |
---|
| 766 | if (config._isPm && config._a[3] < 12) { |
---|
| 767 | config._a[3] += 12; |
---|
| 768 | } |
---|
| 769 | // if is 12 am, change hours to 0 |
---|
| 770 | if (config._isPm === false && config._a[3] === 12) { |
---|
| 771 | config._a[3] = 0; |
---|
| 772 | } |
---|
| 773 | // return |
---|
| 774 | dateFromArray(config); |
---|
| 775 | } |
---|
| 776 | |
---|
| 777 | // date from string and array of format strings |
---|
| 778 | function makeDateFromStringAndArray(config) { |
---|
| 779 | var tempConfig, |
---|
| 780 | tempMoment, |
---|
| 781 | bestMoment, |
---|
| 782 | |
---|
| 783 | scoreToBeat = 99, |
---|
| 784 | i, |
---|
| 785 | currentDate, |
---|
| 786 | currentScore; |
---|
| 787 | |
---|
| 788 | while (config._f.length) { |
---|
| 789 | tempConfig = extend({}, config); |
---|
| 790 | tempConfig._f = config._f.pop(); |
---|
| 791 | makeDateFromStringAndFormat(tempConfig); |
---|
| 792 | tempMoment = new Moment(tempConfig); |
---|
| 793 | |
---|
| 794 | if (tempMoment.isValid()) { |
---|
| 795 | bestMoment = tempMoment; |
---|
| 796 | break; |
---|
| 797 | } |
---|
| 798 | |
---|
| 799 | currentScore = compareArrays(tempConfig._a, tempMoment.toArray()); |
---|
| 800 | |
---|
| 801 | if (currentScore < scoreToBeat) { |
---|
| 802 | scoreToBeat = currentScore; |
---|
| 803 | bestMoment = tempMoment; |
---|
| 804 | } |
---|
| 805 | } |
---|
| 806 | |
---|
| 807 | extend(config, bestMoment); |
---|
| 808 | } |
---|
| 809 | |
---|
| 810 | // date from iso format |
---|
| 811 | function makeDateFromString(config) { |
---|
| 812 | var i, |
---|
| 813 | string = config._i; |
---|
| 814 | if (isoRegex.exec(string)) { |
---|
| 815 | config._f = 'YYYY-MM-DDT'; |
---|
| 816 | for (i = 0; i < 4; i++) { |
---|
| 817 | if (isoTimes[i][1].exec(string)) { |
---|
| 818 | config._f += isoTimes[i][0]; |
---|
| 819 | break; |
---|
| 820 | } |
---|
| 821 | } |
---|
| 822 | if (parseTokenTimezone.exec(string)) { |
---|
| 823 | config._f += " Z"; |
---|
| 824 | } |
---|
| 825 | makeDateFromStringAndFormat(config); |
---|
| 826 | } else { |
---|
| 827 | config._d = new Date(string); |
---|
| 828 | } |
---|
| 829 | } |
---|
| 830 | |
---|
| 831 | function makeDateFromInput(config) { |
---|
| 832 | var input = config._i, |
---|
| 833 | matched = aspNetJsonRegex.exec(input); |
---|
| 834 | |
---|
| 835 | if (input === undefined) { |
---|
| 836 | config._d = new Date(); |
---|
| 837 | } else if (matched) { |
---|
| 838 | config._d = new Date(+matched[1]); |
---|
| 839 | } else if (typeof input === 'string') { |
---|
| 840 | makeDateFromString(config); |
---|
| 841 | } else if (isArray(input)) { |
---|
| 842 | config._a = input.slice(0); |
---|
| 843 | dateFromArray(config); |
---|
| 844 | } else { |
---|
| 845 | config._d = input instanceof Date ? new Date(+input) : new Date(input); |
---|
| 846 | } |
---|
| 847 | } |
---|
| 848 | |
---|
| 849 | |
---|
| 850 | /************************************ |
---|
| 851 | Relative Time |
---|
| 852 | ************************************/ |
---|
| 853 | |
---|
| 854 | |
---|
| 855 | // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize |
---|
| 856 | function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { |
---|
| 857 | return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture); |
---|
| 858 | } |
---|
| 859 | |
---|
| 860 | function relativeTime(milliseconds, withoutSuffix, lang) { |
---|
| 861 | var seconds = round(Math.abs(milliseconds) / 1000), |
---|
| 862 | minutes = round(seconds / 60), |
---|
| 863 | hours = round(minutes / 60), |
---|
| 864 | days = round(hours / 24), |
---|
| 865 | years = round(days / 365), |
---|
| 866 | args = seconds < 45 && ['s', seconds] || |
---|
| 867 | minutes === 1 && ['m'] || |
---|
| 868 | minutes < 45 && ['mm', minutes] || |
---|
| 869 | hours === 1 && ['h'] || |
---|
| 870 | hours < 22 && ['hh', hours] || |
---|
| 871 | days === 1 && ['d'] || |
---|
| 872 | days <= 25 && ['dd', days] || |
---|
| 873 | days <= 45 && ['M'] || |
---|
| 874 | days < 345 && ['MM', round(days / 30)] || |
---|
| 875 | years === 1 && ['y'] || ['yy', years]; |
---|
| 876 | args[2] = withoutSuffix; |
---|
| 877 | args[3] = milliseconds > 0; |
---|
| 878 | args[4] = lang; |
---|
| 879 | return substituteTimeAgo.apply({}, args); |
---|
| 880 | } |
---|
| 881 | |
---|
| 882 | |
---|
| 883 | /************************************ |
---|
| 884 | Week of Year |
---|
| 885 | ************************************/ |
---|
| 886 | |
---|
| 887 | |
---|
| 888 | // firstDayOfWeek 0 = sun, 6 = sat |
---|
| 889 | // the day of the week that starts the week |
---|
| 890 | // (usually sunday or monday) |
---|
| 891 | // firstDayOfWeekOfYear 0 = sun, 6 = sat |
---|
| 892 | // the first week is the week that contains the first |
---|
| 893 | // of this day of the week |
---|
| 894 | // (eg. ISO weeks use thursday (4)) |
---|
| 895 | function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { |
---|
| 896 | var end = firstDayOfWeekOfYear - firstDayOfWeek, |
---|
| 897 | daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(); |
---|
| 898 | |
---|
| 899 | |
---|
| 900 | if (daysToDayOfWeek > end) { |
---|
| 901 | daysToDayOfWeek -= 7; |
---|
| 902 | } |
---|
| 903 | |
---|
| 904 | if (daysToDayOfWeek < end - 7) { |
---|
| 905 | daysToDayOfWeek += 7; |
---|
| 906 | } |
---|
| 907 | |
---|
| 908 | return Math.ceil(moment(mom).add('d', daysToDayOfWeek).dayOfYear() / 7); |
---|
| 909 | } |
---|
| 910 | |
---|
| 911 | |
---|
| 912 | /************************************ |
---|
| 913 | Top Level Functions |
---|
| 914 | ************************************/ |
---|
| 915 | |
---|
| 916 | function makeMoment(config) { |
---|
| 917 | var input = config._i, |
---|
| 918 | format = config._f; |
---|
| 919 | |
---|
| 920 | if (input === null || input === '') { |
---|
| 921 | return null; |
---|
| 922 | } |
---|
| 923 | |
---|
| 924 | if (typeof input === 'string') { |
---|
| 925 | config._i = input = getLangDefinition().preparse(input); |
---|
| 926 | } |
---|
| 927 | |
---|
| 928 | if (moment.isMoment(input)) { |
---|
| 929 | config = extend({}, input); |
---|
| 930 | config._d = new Date(+input._d); |
---|
| 931 | } else if (format) { |
---|
| 932 | if (isArray(format)) { |
---|
| 933 | makeDateFromStringAndArray(config); |
---|
| 934 | } else { |
---|
| 935 | makeDateFromStringAndFormat(config); |
---|
| 936 | } |
---|
| 937 | } else { |
---|
| 938 | makeDateFromInput(config); |
---|
| 939 | } |
---|
| 940 | |
---|
| 941 | return new Moment(config); |
---|
| 942 | } |
---|
| 943 | |
---|
| 944 | moment = function (input, format, lang) { |
---|
| 945 | return makeMoment({ |
---|
| 946 | _i : input, |
---|
| 947 | _f : format, |
---|
| 948 | _l : lang, |
---|
| 949 | _isUTC : false |
---|
| 950 | }); |
---|
| 951 | }; |
---|
| 952 | |
---|
| 953 | // creating with utc |
---|
| 954 | moment.utc = function (input, format, lang) { |
---|
| 955 | return makeMoment({ |
---|
| 956 | _useUTC : true, |
---|
| 957 | _isUTC : true, |
---|
| 958 | _l : lang, |
---|
| 959 | _i : input, |
---|
| 960 | _f : format |
---|
| 961 | }); |
---|
| 962 | }; |
---|
| 963 | |
---|
| 964 | // creating with unix timestamp (in seconds) |
---|
| 965 | moment.unix = function (input) { |
---|
| 966 | return moment(input * 1000); |
---|
| 967 | }; |
---|
| 968 | |
---|
| 969 | // duration |
---|
| 970 | moment.duration = function (input, key) { |
---|
| 971 | var isDuration = moment.isDuration(input), |
---|
| 972 | isNumber = (typeof input === 'number'), |
---|
| 973 | duration = (isDuration ? input._data : (isNumber ? {} : input)), |
---|
| 974 | ret; |
---|
| 975 | |
---|
| 976 | if (isNumber) { |
---|
| 977 | if (key) { |
---|
| 978 | duration[key] = input; |
---|
| 979 | } else { |
---|
| 980 | duration.milliseconds = input; |
---|
| 981 | } |
---|
| 982 | } |
---|
| 983 | |
---|
| 984 | ret = new Duration(duration); |
---|
| 985 | |
---|
| 986 | if (isDuration && input.hasOwnProperty('_lang')) { |
---|
| 987 | ret._lang = input._lang; |
---|
| 988 | } |
---|
| 989 | |
---|
| 990 | return ret; |
---|
| 991 | }; |
---|
| 992 | |
---|
| 993 | // version number |
---|
| 994 | moment.version = VERSION; |
---|
| 995 | |
---|
| 996 | // default format |
---|
| 997 | moment.defaultFormat = isoFormat; |
---|
| 998 | |
---|
| 999 | // This function will load languages and then set the global language. If |
---|
| 1000 | // no arguments are passed in, it will simply return the current global |
---|
| 1001 | // language key. |
---|
| 1002 | moment.lang = function (key, values) { |
---|
| 1003 | var i; |
---|
| 1004 | |
---|
| 1005 | if (!key) { |
---|
| 1006 | return moment.fn._lang._abbr; |
---|
| 1007 | } |
---|
| 1008 | if (values) { |
---|
| 1009 | loadLang(key, values); |
---|
| 1010 | } else if (!languages[key]) { |
---|
| 1011 | getLangDefinition(key); |
---|
| 1012 | } |
---|
| 1013 | moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key); |
---|
| 1014 | }; |
---|
| 1015 | |
---|
| 1016 | // returns language data |
---|
| 1017 | moment.langData = function (key) { |
---|
| 1018 | if (key && key._lang && key._lang._abbr) { |
---|
| 1019 | key = key._lang._abbr; |
---|
| 1020 | } |
---|
| 1021 | return getLangDefinition(key); |
---|
| 1022 | }; |
---|
| 1023 | |
---|
| 1024 | // compare moment object |
---|
| 1025 | moment.isMoment = function (obj) { |
---|
| 1026 | return obj instanceof Moment; |
---|
| 1027 | }; |
---|
| 1028 | |
---|
| 1029 | // for typechecking Duration objects |
---|
| 1030 | moment.isDuration = function (obj) { |
---|
| 1031 | return obj instanceof Duration; |
---|
| 1032 | }; |
---|
| 1033 | |
---|
| 1034 | |
---|
| 1035 | /************************************ |
---|
| 1036 | Moment Prototype |
---|
| 1037 | ************************************/ |
---|
| 1038 | |
---|
| 1039 | |
---|
| 1040 | moment.fn = Moment.prototype = { |
---|
| 1041 | |
---|
| 1042 | clone : function () { |
---|
| 1043 | return moment(this); |
---|
| 1044 | }, |
---|
| 1045 | |
---|
| 1046 | valueOf : function () { |
---|
| 1047 | return +this._d; |
---|
| 1048 | }, |
---|
| 1049 | |
---|
| 1050 | unix : function () { |
---|
| 1051 | return Math.floor(+this._d / 1000); |
---|
| 1052 | }, |
---|
| 1053 | |
---|
| 1054 | toString : function () { |
---|
| 1055 | return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); |
---|
| 1056 | }, |
---|
| 1057 | |
---|
| 1058 | toDate : function () { |
---|
| 1059 | return this._d; |
---|
| 1060 | }, |
---|
| 1061 | |
---|
| 1062 | toJSON : function () { |
---|
| 1063 | return moment.utc(this).format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); |
---|
| 1064 | }, |
---|
| 1065 | |
---|
| 1066 | toArray : function () { |
---|
| 1067 | var m = this; |
---|
| 1068 | return [ |
---|
| 1069 | m.year(), |
---|
| 1070 | m.month(), |
---|
| 1071 | m.date(), |
---|
| 1072 | m.hours(), |
---|
| 1073 | m.minutes(), |
---|
| 1074 | m.seconds(), |
---|
| 1075 | m.milliseconds() |
---|
| 1076 | ]; |
---|
| 1077 | }, |
---|
| 1078 | |
---|
| 1079 | isValid : function () { |
---|
| 1080 | if (this._isValid == null) { |
---|
| 1081 | if (this._a) { |
---|
| 1082 | this._isValid = !compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()); |
---|
| 1083 | } else { |
---|
| 1084 | this._isValid = !isNaN(this._d.getTime()); |
---|
| 1085 | } |
---|
| 1086 | } |
---|
| 1087 | return !!this._isValid; |
---|
| 1088 | }, |
---|
| 1089 | |
---|
| 1090 | utc : function () { |
---|
| 1091 | this._isUTC = true; |
---|
| 1092 | return this; |
---|
| 1093 | }, |
---|
| 1094 | |
---|
| 1095 | local : function () { |
---|
| 1096 | this._isUTC = false; |
---|
| 1097 | return this; |
---|
| 1098 | }, |
---|
| 1099 | |
---|
| 1100 | format : function (inputString) { |
---|
| 1101 | var output = formatMoment(this, inputString || moment.defaultFormat); |
---|
| 1102 | return this.lang().postformat(output); |
---|
| 1103 | }, |
---|
| 1104 | |
---|
| 1105 | add : function (input, val) { |
---|
| 1106 | var dur; |
---|
| 1107 | // switch args to support add('s', 1) and add(1, 's') |
---|
| 1108 | if (typeof input === 'string') { |
---|
| 1109 | dur = moment.duration(+val, input); |
---|
| 1110 | } else { |
---|
| 1111 | dur = moment.duration(input, val); |
---|
| 1112 | } |
---|
| 1113 | addOrSubtractDurationFromMoment(this, dur, 1); |
---|
| 1114 | return this; |
---|
| 1115 | }, |
---|
| 1116 | |
---|
| 1117 | subtract : function (input, val) { |
---|
| 1118 | var dur; |
---|
| 1119 | // switch args to support subtract('s', 1) and subtract(1, 's') |
---|
| 1120 | if (typeof input === 'string') { |
---|
| 1121 | dur = moment.duration(+val, input); |
---|
| 1122 | } else { |
---|
| 1123 | dur = moment.duration(input, val); |
---|
| 1124 | } |
---|
| 1125 | addOrSubtractDurationFromMoment(this, dur, -1); |
---|
| 1126 | return this; |
---|
| 1127 | }, |
---|
| 1128 | |
---|
| 1129 | diff : function (input, units, asFloat) { |
---|
| 1130 | var that = this._isUTC ? moment(input).utc() : moment(input).local(), |
---|
| 1131 | zoneDiff = (this.zone() - that.zone()) * 6e4, |
---|
| 1132 | diff, output; |
---|
| 1133 | |
---|
| 1134 | if (units) { |
---|
| 1135 | // standardize on singular form |
---|
| 1136 | units = units.replace(/s$/, ''); |
---|
| 1137 | } |
---|
| 1138 | |
---|
| 1139 | if (units === 'year' || units === 'month') { |
---|
| 1140 | diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 |
---|
| 1141 | output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); |
---|
| 1142 | output += ((this - moment(this).startOf('month')) - (that - moment(that).startOf('month'))) / diff; |
---|
| 1143 | if (units === 'year') { |
---|
| 1144 | output = output / 12; |
---|
| 1145 | } |
---|
| 1146 | } else { |
---|
| 1147 | diff = (this - that) - zoneDiff; |
---|
| 1148 | output = units === 'second' ? diff / 1e3 : // 1000 |
---|
| 1149 | units === 'minute' ? diff / 6e4 : // 1000 * 60 |
---|
| 1150 | units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 |
---|
| 1151 | units === 'day' ? diff / 864e5 : // 1000 * 60 * 60 * 24 |
---|
| 1152 | units === 'week' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7 |
---|
| 1153 | diff; |
---|
| 1154 | } |
---|
| 1155 | return asFloat ? output : absRound(output); |
---|
| 1156 | }, |
---|
| 1157 | |
---|
| 1158 | from : function (time, withoutSuffix) { |
---|
| 1159 | return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); |
---|
| 1160 | }, |
---|
| 1161 | |
---|
| 1162 | fromNow : function (withoutSuffix) { |
---|
| 1163 | return this.from(moment(), withoutSuffix); |
---|
| 1164 | }, |
---|
| 1165 | |
---|
| 1166 | calendar : function () { |
---|
| 1167 | var diff = this.diff(moment().startOf('day'), 'days', true), |
---|
| 1168 | format = diff < -6 ? 'sameElse' : |
---|
| 1169 | diff < -1 ? 'lastWeek' : |
---|
| 1170 | diff < 0 ? 'lastDay' : |
---|
| 1171 | diff < 1 ? 'sameDay' : |
---|
| 1172 | diff < 2 ? 'nextDay' : |
---|
| 1173 | diff < 7 ? 'nextWeek' : 'sameElse'; |
---|
| 1174 | return this.format(this.lang().calendar(format, this)); |
---|
| 1175 | }, |
---|
| 1176 | |
---|
| 1177 | isLeapYear : function () { |
---|
| 1178 | var year = this.year(); |
---|
| 1179 | return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; |
---|
| 1180 | }, |
---|
| 1181 | |
---|
| 1182 | isDST : function () { |
---|
| 1183 | return (this.zone() < moment([this.year()]).zone() || |
---|
| 1184 | this.zone() < moment([this.year(), 5]).zone()); |
---|
| 1185 | }, |
---|
| 1186 | |
---|
| 1187 | day : function (input) { |
---|
| 1188 | var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); |
---|
| 1189 | return input == null ? day : |
---|
| 1190 | this.add({ d : input - day }); |
---|
| 1191 | }, |
---|
| 1192 | |
---|
| 1193 | startOf: function (units) { |
---|
| 1194 | units = units.replace(/s$/, ''); |
---|
| 1195 | // the following switch intentionally omits break keywords |
---|
| 1196 | // to utilize falling through the cases. |
---|
| 1197 | switch (units) { |
---|
| 1198 | case 'year': |
---|
| 1199 | this.month(0); |
---|
| 1200 | /* falls through */ |
---|
| 1201 | case 'month': |
---|
| 1202 | this.date(1); |
---|
| 1203 | /* falls through */ |
---|
| 1204 | case 'week': |
---|
| 1205 | case 'day': |
---|
| 1206 | this.hours(0); |
---|
| 1207 | /* falls through */ |
---|
| 1208 | case 'hour': |
---|
| 1209 | this.minutes(0); |
---|
| 1210 | /* falls through */ |
---|
| 1211 | case 'minute': |
---|
| 1212 | this.seconds(0); |
---|
| 1213 | /* falls through */ |
---|
| 1214 | case 'second': |
---|
| 1215 | this.milliseconds(0); |
---|
| 1216 | /* falls through */ |
---|
| 1217 | } |
---|
| 1218 | |
---|
| 1219 | // weeks are a special case |
---|
| 1220 | if (units === 'week') { |
---|
| 1221 | this.day(0); |
---|
| 1222 | } |
---|
| 1223 | |
---|
| 1224 | return this; |
---|
| 1225 | }, |
---|
| 1226 | |
---|
| 1227 | endOf: function (units) { |
---|
| 1228 | return this.startOf(units).add(units.replace(/s?$/, 's'), 1).subtract('ms', 1); |
---|
| 1229 | }, |
---|
| 1230 | |
---|
| 1231 | isAfter: function (input, units) { |
---|
| 1232 | units = typeof units !== 'undefined' ? units : 'millisecond'; |
---|
| 1233 | return +this.clone().startOf(units) > +moment(input).startOf(units); |
---|
| 1234 | }, |
---|
| 1235 | |
---|
| 1236 | isBefore: function (input, units) { |
---|
| 1237 | units = typeof units !== 'undefined' ? units : 'millisecond'; |
---|
| 1238 | return +this.clone().startOf(units) < +moment(input).startOf(units); |
---|
| 1239 | }, |
---|
| 1240 | |
---|
| 1241 | isSame: function (input, units) { |
---|
| 1242 | units = typeof units !== 'undefined' ? units : 'millisecond'; |
---|
| 1243 | return +this.clone().startOf(units) === +moment(input).startOf(units); |
---|
| 1244 | }, |
---|
| 1245 | |
---|
| 1246 | zone : function () { |
---|
| 1247 | return this._isUTC ? 0 : this._d.getTimezoneOffset(); |
---|
| 1248 | }, |
---|
| 1249 | |
---|
| 1250 | daysInMonth : function () { |
---|
| 1251 | return moment.utc([this.year(), this.month() + 1, 0]).date(); |
---|
| 1252 | }, |
---|
| 1253 | |
---|
| 1254 | dayOfYear : function (input) { |
---|
| 1255 | var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; |
---|
| 1256 | return input == null ? dayOfYear : this.add("d", (input - dayOfYear)); |
---|
| 1257 | }, |
---|
| 1258 | |
---|
| 1259 | isoWeek : function (input) { |
---|
| 1260 | var week = weekOfYear(this, 1, 4); |
---|
| 1261 | return input == null ? week : this.add("d", (input - week) * 7); |
---|
| 1262 | }, |
---|
| 1263 | |
---|
| 1264 | week : function (input) { |
---|
| 1265 | var week = this.lang().week(this); |
---|
| 1266 | return input == null ? week : this.add("d", (input - week) * 7); |
---|
| 1267 | }, |
---|
| 1268 | |
---|
| 1269 | // If passed a language key, it will set the language for this |
---|
| 1270 | // instance. Otherwise, it will return the language configuration |
---|
| 1271 | // variables for this instance. |
---|
| 1272 | lang : function (key) { |
---|
| 1273 | if (key === undefined) { |
---|
| 1274 | return this._lang; |
---|
| 1275 | } else { |
---|
| 1276 | this._lang = getLangDefinition(key); |
---|
| 1277 | return this; |
---|
| 1278 | } |
---|
| 1279 | } |
---|
| 1280 | }; |
---|
| 1281 | |
---|
| 1282 | // helper for adding shortcuts |
---|
| 1283 | function makeGetterAndSetter(name, key) { |
---|
| 1284 | moment.fn[name] = moment.fn[name + 's'] = function (input) { |
---|
| 1285 | var utc = this._isUTC ? 'UTC' : ''; |
---|
| 1286 | if (input != null) { |
---|
| 1287 | this._d['set' + utc + key](input); |
---|
| 1288 | return this; |
---|
| 1289 | } else { |
---|
| 1290 | return this._d['get' + utc + key](); |
---|
| 1291 | } |
---|
| 1292 | }; |
---|
| 1293 | } |
---|
| 1294 | |
---|
| 1295 | // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds) |
---|
| 1296 | for (i = 0; i < proxyGettersAndSetters.length; i ++) { |
---|
| 1297 | makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]); |
---|
| 1298 | } |
---|
| 1299 | |
---|
| 1300 | // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear') |
---|
| 1301 | makeGetterAndSetter('year', 'FullYear'); |
---|
| 1302 | |
---|
| 1303 | // add plural methods |
---|
| 1304 | moment.fn.days = moment.fn.day; |
---|
| 1305 | moment.fn.weeks = moment.fn.week; |
---|
| 1306 | moment.fn.isoWeeks = moment.fn.isoWeek; |
---|
| 1307 | |
---|
| 1308 | /************************************ |
---|
| 1309 | Duration Prototype |
---|
| 1310 | ************************************/ |
---|
| 1311 | |
---|
| 1312 | |
---|
| 1313 | moment.duration.fn = Duration.prototype = { |
---|
| 1314 | weeks : function () { |
---|
| 1315 | return absRound(this.days() / 7); |
---|
| 1316 | }, |
---|
| 1317 | |
---|
| 1318 | valueOf : function () { |
---|
| 1319 | return this._milliseconds + |
---|
| 1320 | this._days * 864e5 + |
---|
| 1321 | this._months * 2592e6; |
---|
| 1322 | }, |
---|
| 1323 | |
---|
| 1324 | humanize : function (withSuffix) { |
---|
| 1325 | var difference = +this, |
---|
| 1326 | output = relativeTime(difference, !withSuffix, this.lang()); |
---|
| 1327 | |
---|
| 1328 | if (withSuffix) { |
---|
| 1329 | output = this.lang().pastFuture(difference, output); |
---|
| 1330 | } |
---|
| 1331 | |
---|
| 1332 | return this.lang().postformat(output); |
---|
| 1333 | }, |
---|
| 1334 | |
---|
| 1335 | lang : moment.fn.lang |
---|
| 1336 | }; |
---|
| 1337 | |
---|
| 1338 | function makeDurationGetter(name) { |
---|
| 1339 | moment.duration.fn[name] = function () { |
---|
| 1340 | return this._data[name]; |
---|
| 1341 | }; |
---|
| 1342 | } |
---|
| 1343 | |
---|
| 1344 | function makeDurationAsGetter(name, factor) { |
---|
| 1345 | moment.duration.fn['as' + name] = function () { |
---|
| 1346 | return +this / factor; |
---|
| 1347 | }; |
---|
| 1348 | } |
---|
| 1349 | |
---|
| 1350 | for (i in unitMillisecondFactors) { |
---|
| 1351 | if (unitMillisecondFactors.hasOwnProperty(i)) { |
---|
| 1352 | makeDurationAsGetter(i, unitMillisecondFactors[i]); |
---|
| 1353 | makeDurationGetter(i.toLowerCase()); |
---|
| 1354 | } |
---|
| 1355 | } |
---|
| 1356 | |
---|
| 1357 | makeDurationAsGetter('Weeks', 6048e5); |
---|
| 1358 | |
---|
| 1359 | |
---|
| 1360 | /************************************ |
---|
| 1361 | Default Lang |
---|
| 1362 | ************************************/ |
---|
| 1363 | |
---|
| 1364 | |
---|
| 1365 | // Set default language, other languages will inherit from English. |
---|
| 1366 | moment.lang('en', { |
---|
| 1367 | ordinal : function (number) { |
---|
| 1368 | var b = number % 10, |
---|
| 1369 | output = (~~ (number % 100 / 10) === 1) ? 'th' : |
---|
| 1370 | (b === 1) ? 'st' : |
---|
| 1371 | (b === 2) ? 'nd' : |
---|
| 1372 | (b === 3) ? 'rd' : 'th'; |
---|
| 1373 | return number + output; |
---|
| 1374 | } |
---|
| 1375 | }); |
---|
| 1376 | |
---|
| 1377 | |
---|
| 1378 | /************************************ |
---|
| 1379 | Exposing Moment |
---|
| 1380 | ************************************/ |
---|
| 1381 | |
---|
| 1382 | |
---|
| 1383 | // CommonJS module is defined |
---|
| 1384 | if (hasModule) { |
---|
| 1385 | module.exports = moment; |
---|
| 1386 | } |
---|
| 1387 | /*global ender:false */ |
---|
| 1388 | if (typeof ender === 'undefined') { |
---|
| 1389 | // here, `this` means `window` in the browser, or `global` on the server |
---|
| 1390 | // add `moment` as a global object via a string identifier, |
---|
| 1391 | // for Closure Compiler "advanced" mode |
---|
| 1392 | this['moment'] = moment; |
---|
| 1393 | } |
---|
| 1394 | /*global define:false */ |
---|
| 1395 | if (typeof define === "function" && define.amd) { |
---|
| 1396 | define("moment", [], function () { |
---|
| 1397 | return moment; |
---|
| 1398 | }); |
---|
| 1399 | } |
---|
| 1400 | }).call(this); |
---|