From: Tim Wood Date: Thu, 1 Sep 2011 17:44:11 +0000 (-0700) Subject: made some filesize and speed improvements on _date(string, format) X-Git-Tag: 0.6.0~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=01550adf37399d4ace450939ea30d4e0a6c293a9;p=thirdparty%2Fmoment.git made some filesize and speed improvements on _date(string, format) _date(string, format) is now 33% faster and cut out a few kbs in the process. cleaned up the css styles for the unit tests --- diff --git a/test/speed.js b/test/speed.js index 8055d587f..91641e346 100755 --- a/test/speed.js +++ b/test/speed.js @@ -1,9 +1,14 @@ -var date = new Date(); +var date = new Date(), + new_date = _date(); JSLitmus.test('create from date', function() { return _date(date); }); +JSLitmus.test('create from _date', function() { + return _date(new_date); +}); + JSLitmus.test('create from undefined', function() { return _date(); }); diff --git a/test/test.css b/test/test.css new file mode 100755 index 000000000..02b7f81f4 --- /dev/null +++ b/test/test.css @@ -0,0 +1,238 @@ +/** + * html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline) + * v1.6.1 2010-09-17 | Authors: Eric Meyer & Richard Clark + * html5doctor.com/html-5-reset-stylesheet/ + */ + +html, body, div, span, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, +small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, figcaption, figure, +footer, header, hgroup, menu, nav, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +blockquote, q { quotes: none; } + +blockquote:before, blockquote:after, +q:before, q:after { content: ""; content: none; } + +ins { background-color: #ff9; color: #000; text-decoration: none; } + +mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; } + +del { text-decoration: line-through; } + +abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; } + +table { border-collapse: collapse; border-spacing: 0; } + +hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } + +input, select { vertical-align: middle; } + +/** + * base styles + */ + + +html { background:#AFBAC4 url(../site/bg.png); text-align:center; color:#445; } + +a { color:#09489A; } + +h1, h2, h3, h4, h5, h6, th { font-family:Oswald, sans-serif; line-height:1.5em; margin-bottom:20px; text-shadow:1px 1px 0 rgba(255, 255, 255, .4); } + +h1 { font-size:48px; padding-top:40px; } +h2 { font-size:36px; padding-top:20px; } +h3 { font-size:24px; padding-top:10px; } +h4 { font-size:21px; } +h5 { font-size:18px; } +h6 { font-size:16px; } + +h1 a { color:#445; } + +body, p { font-size:18px; line-height:1.5em; font-family:"Hoefler Text", Constantia, Palatino, "Palatino Linotype", "Book Antiqua", Georgia, serif; } +p { margin-bottom:20px; } + +pre, code { font-size:18px; line-height:1.5em; font-family:Consolas, "Courier New", Courier, monospace; } + +pre { background:rgba(0, 0, 0, .05); display:block; padding:5px 10px; white-space:pre; white-space:pre-wrap; word-wrap:break-word; } + +p code { background:rgba(0, 0, 0, .05); padding:0 5px; } + +table { margin-bottom:20px; width:100%; } + +th { font-size:21px; padding:10px 20px; } +td + td { background:rgba(255, 255, 255, .2); } + +b, strong { font-weight:bold; } + + +/* + * special + */ + +.logo { text-align:center; border-bottom:#313749 10px solid; } + + +/** + * layout + */ + + +#container { background:url(../site/bg-body.png); margin:0 auto; width:960px; padding:20px 40px; text-align:left; } +.footer { text-align:center; padding:50px 0 200px; } + + +/** Header */ + + +#qunit-banner { + height:20px; +} + +#qunit-testrunner-toolbar { + padding: 0.5em 0 0.5em 2em; + color: #5E740B; + background-color: #eee; +} + + +/** Tests: Pass/Fail */ + +#qunit-tests { + list-style-position: inside; + padding-bottom:20px; + border-bottom:#313749 10px solid; + margin-bottom:20px; +} + +#qunit-tests li { + padding:5px 10px; + list-style-position: inside; +} + +#qunit-tests th, +#qunit-tests pre { font-size:14px; } + +#qunit-tests.hidepass li.pass { + display: none; +} + +#qunit-tests li strong { + cursor: pointer; +} + +#qunit-tests ol { + margin-top: 0.5em; + padding: 0.5em; + background-color: #fff; +} + +#qunit-tests table { + border-collapse: collapse; + margin-top: .2em; +} + +#qunit-tests th { + text-align: right; + vertical-align: top; + padding: 0 .5em 0 0; +} + +#qunit-tests td { + vertical-align: top; +} + +#qunit-tests pre { + margin: 0; + white-space: pre-wrap; + word-wrap: break-word; +} + +#qunit-tests del { + background-color: #e0f2be; + color: #374e0c; + text-decoration: none; +} + +#qunit-tests ins { + background-color: #ffcaca; + color: #500; + text-decoration: none; +} + +/*** Test Counts */ + +#qunit-tests b.counts { color: black; } +#qunit-tests b.passed { color: #5E740B; } +#qunit-tests b.failed { color: #710909; } + +#qunit-tests li li { + margin: 0.5em; + padding: 0.4em 0.5em 0.4em 0.5em; + background-color: #fff; + border-bottom: none; + list-style-position: inside; +} + +/*** Passing Styles */ + +#qunit-tests li li.pass { + color: #5E740B; + background-color: #fff; + border-left: 26px solid #C6E746; +} + +#qunit-tests .pass { color: #528CE0; } +#qunit-tests .pass .test-name { color: #366097; } + +#qunit-tests .pass .test-actual, +#qunit-tests .pass .test-expected { color: #999999; } + +#qunit-banner.qunit-pass { background-color: #C6E746; } + +/*** Failing Styles */ + +#qunit-tests li li.fail { + color: #710909; + background-color: #fff; + border-left: 26px solid #EE5757; +} + +#qunit-tests .fail { color: #000000; background-color: #EE5757; } +#qunit-tests .fail .test-name, +#qunit-tests .fail .module-name { color: #000000; } + +#qunit-tests .fail .test-actual { color: #EE5757; } +#qunit-tests .fail .test-expected { color: green; } + +#qunit-banner.qunit-fail { background-color: #EE5757; } + + +/** Result */ + +.test-expected th { width:100px; } + + +/** Fixture */ + +#qunit-fixture { + position: absolute; + top: -10000px; + left: -10000px; +} \ No newline at end of file diff --git a/test/test.html b/test/test.html index e2b8a6ff4..8a3d04d2b 100755 --- a/test/test.html +++ b/test/test.html @@ -1,20 +1,24 @@ - Uunderscore.date unit test suite - - - - - - - - + underscore.date unit test suite + + + + + + + + + -

underscore.date unit test suite

-

-

-
    +
    +

    underscore.date unit test suite

    +

    +

    +
      +
      +
      diff --git a/test/vendor/qunit.css b/test/vendor/qunit.css deleted file mode 100755 index 65d7cbae6..000000000 --- a/test/vendor/qunit.css +++ /dev/null @@ -1,196 +0,0 @@ -/** Font Family and Sizes */ - -#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { - font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; -} - -#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } -#qunit-tests { font-size: smaller; } - - -/** Resets */ - -#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { - margin: 0; - padding: 0; -} - - -/** Header */ - -#qunit-header { - padding: 0.5em 0 0.5em 1em; - - color: #8699a4; - background-color: #0d3349; - - font-size: 1.5em; - line-height: 1em; - font-weight: normal; - - border-radius: 15px 15px 0 0; - -moz-border-radius: 15px 15px 0 0; - -webkit-border-top-right-radius: 15px; - -webkit-border-top-left-radius: 15px; -} - -#qunit-header a { - text-decoration: none; - color: #c2ccd1; -} - -#qunit-header a:hover, -#qunit-header a:focus { - color: #fff; -} - -#qunit-banner { - height: 5px; -} - -#qunit-testrunner-toolbar { - padding: 0.5em 0 0.5em 2em; - color: #5E740B; - background-color: #eee; -} - -#qunit-userAgent { - padding: 0.5em 0 0.5em 2.5em; - background-color: #2b81af; - color: #fff; - text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; -} - - -/** Tests: Pass/Fail */ - -#qunit-tests { - list-style-position: inside; -} - -#qunit-tests li { - padding: 0.4em 0.5em 0.4em 2.5em; - border-bottom: 1px solid #fff; - list-style-position: inside; -} - -#qunit-tests.hidepass li.pass { - display: none; -} - -#qunit-tests li strong { - cursor: pointer; -} - -#qunit-tests ol { - margin-top: 0.5em; - padding: 0.5em; - background-color: #fff; -} - -#qunit-tests table { - border-collapse: collapse; - margin-top: .2em; -} - -#qunit-tests th { - text-align: right; - vertical-align: top; - padding: 0 .5em 0 0; -} - -#qunit-tests td { - vertical-align: top; -} - -#qunit-tests pre { - margin: 0; - white-space: pre-wrap; - word-wrap: break-word; -} - -#qunit-tests del { - background-color: #e0f2be; - color: #374e0c; - text-decoration: none; -} - -#qunit-tests ins { - background-color: #ffcaca; - color: #500; - text-decoration: none; -} - -/*** Test Counts */ - -#qunit-tests b.counts { color: black; } -#qunit-tests b.passed { color: #5E740B; } -#qunit-tests b.failed { color: #710909; } - -#qunit-tests li li { - margin: 0.5em; - padding: 0.4em 0.5em 0.4em 0.5em; - background-color: #fff; - border-bottom: none; - list-style-position: inside; -} - -/*** Passing Styles */ - -#qunit-tests li li.pass { - color: #5E740B; - background-color: #fff; - border-left: 26px solid #C6E746; -} - -#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } -#qunit-tests .pass .test-name { color: #366097; } - -#qunit-tests .pass .test-actual, -#qunit-tests .pass .test-expected { color: #999999; } - -#qunit-banner.qunit-pass { background-color: #C6E746; } - -/*** Failing Styles */ - -#qunit-tests li li.fail { - color: #710909; - background-color: #fff; - border-left: 26px solid #EE5757; -} - -#qunit-tests > li:last-child { - border-radius: 0 0 15px 15px; - -moz-border-radius: 0 0 15px 15px; - -webkit-border-bottom-right-radius: 15px; - -webkit-border-bottom-left-radius: 15px; -} - -#qunit-tests .fail { color: #000000; background-color: #EE5757; } -#qunit-tests .fail .test-name, -#qunit-tests .fail .module-name { color: #000000; } - -#qunit-tests .fail .test-actual { color: #EE5757; } -#qunit-tests .fail .test-expected { color: green; } - -#qunit-banner.qunit-fail { background-color: #EE5757; } - - -/** Result */ - -#qunit-testresult { - padding: 0.5em 0.5em 0.5em 2.5em; - - color: #2b81af; - background-color: #D2E0E6; - - border-bottom: 1px solid white; -} - -/** Fixture */ - -#qunit-fixture { - position: absolute; - top: -10000px; - left: -10000px; -} \ No newline at end of file diff --git a/underscore.date.js b/underscore.date.js index 8a3cf0552..53253d39b 100644 --- a/underscore.date.js +++ b/underscore.date.js @@ -19,7 +19,7 @@ } return output; } - + // helper function for _.addTime and _.subtractTime function dateAddRemove(date, input, adding) { var ms = (input.ms || 0) + @@ -28,7 +28,7 @@ (input.h || 0) * 36e5 + // 1000 * 60 * 60 (input.d || 0) * 864e5 + // 1000 * 60 * 60 * 24 (input.w || 0) * 6048e5, // 1000 * 60 * 60 * 24 * 7 - M = (input.M || 0) + + M = (input.M || 0) + (input.y || 0) * 12, currentDate; if (ms) { @@ -38,16 +38,16 @@ currentDate = date.getDate(); date.setDate(1); date.setMonth(date.getMonth() + M * adding); - date.setDate(Math.min(new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(), currentDate)); + date.setDate(Math.min(new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(), currentDate)); } return date; } - + // check if is an array function isArray(input) { return Object.prototype.toString.call(input) === '[object Array]'; } - + // convert an array to a date. // the array should mirror the parameters below // note: all values past the year are optional and will default to the lowest possible value. @@ -55,16 +55,16 @@ function dateFromArray(input) { return new Date(input[0], input[1] || 0, input[2] || 1, input[3] || 0, input[4] || 0, input[5] || 0, input[6] || 0); } - + // date from string and format string function makeDateFromStringAndFormat(string, format) { var inArray = [0], charactersToPutInArray = /[0-9a-zA-Z]+/g, - inputParts = [], - formatParts = [], + inputParts = string.match(charactersToPutInArray), + formatParts = format.match(charactersToPutInArray), i, isPm; - + // function to convert string input to date function addTime(format, input) { switch (format) { @@ -75,9 +75,9 @@ inArray[1] = ~~input - 1; break; // DAY OF MONTH - case 'D' : + case 'D' : // fall through to DDDD - case 'DD' : + case 'DD' : // fall through to DDDD case 'DDD' : // fall through to DDDD @@ -85,85 +85,74 @@ inArray[2] = ~~input; break; // YEAR - case 'YY' : + case 'YY' : input = ~~input; inArray[0] = input + (input > 70 ? 1900 : 2000); break; - case 'YYYY' : + case 'YYYY' : inArray[0] = ~~input; break; // AM / PM - case 'a' : + case 'a' : // fall through to A case 'A' : isPm = (input.toLowerCase() === 'pm'); break; - // 24 HOUR - case 'H' : + // 24 HOUR + case 'H' : // fall through to hh - case 'HH' : + case 'HH' : // fall through to hh - case 'h' : + case 'h' : // fall through to hh - case 'hh' : + case 'hh' : inArray[3] = ~~input; break; // MINUTE - case 'm' : + case 'm' : // fall through to mm - case 'mm' : + case 'mm' : inArray[4] = ~~input; break; // SECOND - case 's' : + case 's' : // fall through to ss - case 'ss' : + case 'ss' : inArray[5] = ~~input; break; } } - - // add input parts to array - string.replace(charactersToPutInArray, function (input) { - inputParts.push(input); - }); - - // add format parts to array - format.replace(charactersToPutInArray, function (input) { - formatParts.push(input); - }); - for (i = 0; i < formatParts.length; i++) { addTime(formatParts[i], inputParts[i]); } - // handle am pm if (isPm && inArray[3] < 12) { inArray[3] += 12; } - return dateFromArray(inArray); } - + // UnderscoreDate prototype object function UnderscoreDate(input, format) { + // parse UnderscoreDate object if (input && input.date instanceof Date) { this.date = input.date; + // parse string and format } else if (format) { this.date = makeDateFromStringAndFormat(input, format); + // parse everything else } else { this.date = input === undefined ? new Date() : - input instanceof Date ? input : + input instanceof Date ? input : isArray(input) ? dateFromArray(input) : new Date(input); } } - + _date = function (input, format) { return new UnderscoreDate(input, format); }; - - + _date.months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; _date.monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; _date.weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; @@ -185,26 +174,26 @@ }; _date.ordinal = function (number) { var b = number % 10; - return (~~ (number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : + return (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : (b === 3) ? 'rd' : 'th'; }; - + // convert any input to milliseconds function makeInputMilliseconds(input) { return isNaN(input) ? new UnderscoreDate(input).date.getTime() : input; } - + // helper function for _date.from() and _date.fromNow() function substituteTimeAgo(string, number) { return _date.relativeTime[string].replace(/%d/i, number || 1); } - + function msApart(time, now) { return makeInputMilliseconds(time) - makeInputMilliseconds(now); } - + function relativeTime(milliseconds) { var seconds = Math.abs(milliseconds) / 1000, minutes = seconds / 60, @@ -223,13 +212,13 @@ round(years) === 1 && substituteTimeAgo('y') || substituteTimeAgo('yy', round(years)); } - + UnderscoreDate.prototype = { - + valueOf : function () { return this.date.getTime(); }, - + format : function (inputString) { // shortcuts to this and getting time functions // done to save bytes in minification @@ -247,7 +236,7 @@ // check if the character is a format // return formatted string or non string. // - // uses switch/case instead of an object of named functions (like http://phpjs.org/functions/date:380) + // uses switch/case instead of an object of named functions (like http://phpjs.org/functions/date:380) // for minification and performance // see http://jsperf.com/object-of-functions-vs-switch for performance comparison function replaceFunction(input) { @@ -255,29 +244,29 @@ var a, b; switch (input) { // MONTH - case 'M' : + case 'M' : return currentMonth + 1; - case 'Mo' : + case 'Mo' : return (currentMonth + 1) + _date.ordinal(currentMonth + 1); case 'MM' : return leftZeroFill(currentMonth + 1, 2); - case 'MMM' : + case 'MMM' : return _date.monthsShort[currentMonth]; - case 'MMMM' : + case 'MMMM' : return _date.months[currentMonth]; // DAY OF MONTH - case 'D' : + case 'D' : return currentDate; - case 'Do' : + case 'Do' : return currentDate + _date.ordinal(currentDate); - case 'DD' : + case 'DD' : return leftZeroFill(currentDate, 2); // DAY OF YEAR case 'DDD' : a = new Date(currentYear, currentMonth, currentDate); b = new Date(currentYear, 0, 1); return ~~ (((a - b) / 864e5) + 1.5); - case 'DDDo' : + case 'DDDo' : a = replaceFunction('DDD'); return a + _date.ordinal(a); case 'DDDD' : @@ -285,56 +274,56 @@ // WEEKDAY case 'd' : return currentDay; - case 'do' : + case 'do' : return currentDay + _date.ordinal(currentDay); - case 'ddd' : + case 'ddd' : return _date.weekdaysShort[currentDay]; - case 'dddd' : + case 'dddd' : return _date.weekdays[currentDay]; // WEEK OF YEAR - case 'w' : + case 'w' : a = new Date(currentYear, currentMonth, currentDate - currentDay + 5); b = new Date(a.getFullYear(), 0, 4); return ~~ ((a - b) / 864e5 / 7 + 1.5); - case 'wo' : + case 'wo' : a = replaceFunction('w'); return a + _date.ordinal(a); - case 'ww' : + case 'ww' : return leftZeroFill(replaceFunction('w'), 2); // YEAR - case 'YY' : + case 'YY' : return (currentYear + '').slice(-2); - case 'YYYY' : + case 'YYYY' : return currentYear; // AM / PM - case 'a' : + case 'a' : return currentHours > 11 ? 'pm' : 'am'; case 'A' : return currentHours > 11 ? 'PM' : 'AM'; - // 24 HOUR - case 'H' : + // 24 HOUR + case 'H' : return currentHours; - case 'HH' : + case 'HH' : return leftZeroFill(currentHours, 2); - // 12 HOUR - case 'h' : + // 12 HOUR + case 'h' : return currentHours % 12 || 12; - case 'hh' : + case 'hh' : return leftZeroFill(currentHours % 12 || 12, 2); // MINUTE - case 'm' : + case 'm' : return currentMinutes; - case 'mm' : + case 'mm' : return leftZeroFill(currentMinutes, 2); // SECOND - case 's' : + case 's' : return currentSeconds; - case 'ss' : + case 'ss' : return leftZeroFill(currentSeconds, 2); // TIMEZONE case 'z' : return replaceFunction('zz').replace(nonuppercaseLetters, ''); - case 'zz' : + case 'zz' : a = currentString.indexOf('('); if (a > -1) { return currentString.slice(a + 1, currentString.indexOf(')')); @@ -347,40 +336,35 @@ } return inputString.replace(charactersToReplace, replaceFunction); }, - - + add : function (input) { this.date = dateAddRemove(this.date, input, 1); return this; }, - - + subtract : function (input) { this.date = dateAddRemove(this.date, input, -1); return this; }, - - + from : function (time, withoutSuffix, asMilliseconds) { var difference = msApart(this.date, time), string = difference < 0 ? _date.relativeTime.past : _date.relativeTime.future; - return asMilliseconds ? difference : + return asMilliseconds ? difference : withoutSuffix ? relativeTime(difference) : string.replace(/%s/i, relativeTime(difference)); }, - - + fromNow : function (withoutSuffix, asMilliseconds) { return this.from(new UnderscoreDate(), withoutSuffix, asMilliseconds); }, - - + isLeapYear : function () { var year = this.date.getFullYear(); return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } }; - + // CommonJS module is defined if (typeof window === 'undefined' && typeof module !== 'undefined') { // Export module @@ -392,5 +376,5 @@ } this._date = _date; } - + }()); diff --git a/underscore.date.min.js b/underscore.date.min.js index 9c57f0168..80144cadd 100755 --- a/underscore.date.min.js +++ b/underscore.date.min.js @@ -1 +1 @@ -(function(a){function m(a){var b=Math.abs(a)/1e3,d=b/60,e=d/60,f=e/24,g=f/365;return b<45&&k("s",c(b))||c(d)===1&&k("m")||d<45&&k("mm",c(d))||c(e)===1&&k("h")||e<22&&k("hh",c(e))||c(f)===1&&k("d")||f<25&&k("dd",c(f))||f<45&&k("M")||f<345&&k("MM",c(f/30))||c(g)===1&&k("y")||k("yy",c(g))}function l(a,b){return j(a)-j(b)}function k(a,c){return b.relativeTime[a].replace(/%d/i,c||1)}function j(a){return isNaN(a)?(new i(a)).date.getTime():a}function i(b,c){b&&b.date instanceof Date?this.date=b.date:c?this.date=h(b,c):this.date=b===a?new Date:b instanceof Date?b:f(b)?g(b):new Date(b)}function h(a,b){function j(a,b){switch(a){case"M":case"MM":c[1]=~~b-1;break;case"D":case"DD":case"DDD":case"DDDD":c[2]=~~b;break;case"YY":b=~~b,c[0]=b+(b>70?1900:2e3);break;case"YYYY":c[0]=~~b;break;case"a":case"A":i=b.toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b}}var c=[0],d=/[0-9a-zA-Z]+/g,e=[],f=[],h,i;a.replace(d,function(a){e.push(a)}),b.replace(d,function(a){f.push(a)});for(h=0;h11?"pm":"am";case"A":return i>11?"PM":"AM";case"H":return i;case"HH":return d(i,2);case"h":return i%12||12;case"hh":return d(i%12||12,2);case"m":return j;case"mm":return d(j,2);case"s":return k;case"ss":return d(k,2);case"z":return o("zz").replace(n,"");case"zz":c=l.indexOf("(");if(c>-1)return l.slice(c+1,l.indexOf(")"));return l.slice(l.indexOf(":")).replace(n,"");default:return a.replace("\\","")}}var c=this.date,e=c.getMonth(),f=c.getDate(),g=c.getFullYear(),h=c.getDay(),i=c.getHours(),j=c.getMinutes(),k=c.getSeconds(),l=c.toString(),m=/(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|zz?)/g,n=/[^A-Z]/g;return a.replace(m,o)},add:function(a){this.date=e(this.date,a,1);return this},subtract:function(a){this.date=e(this.date,a,-1);return this},from:function(a,c,d){var e=l(this.date,a),f=e<0?b.relativeTime.past:b.relativeTime.future;return d?e:c?m(e):f.replace(/%s/i,m(e))},fromNow:function(a,b){return this.from(new i,a,b)},isLeapYear:function(){var a=this.date.getFullYear();return a%4===0&&a%100!==0||a%400===0}},typeof window=="undefined"&&typeof module!="undefined"?module.exports=b:(this._!==a&&this._.mixin!==a&&this._.mixin({date:b}),this._date=b)})() \ No newline at end of file +(function(a){function m(a){var b=Math.abs(a)/1e3,d=b/60,e=d/60,f=e/24,g=f/365;return b<45&&k("s",c(b))||c(d)===1&&k("m")||d<45&&k("mm",c(d))||c(e)===1&&k("h")||e<22&&k("hh",c(e))||c(f)===1&&k("d")||f<25&&k("dd",c(f))||f<45&&k("M")||f<345&&k("MM",c(f/30))||c(g)===1&&k("y")||k("yy",c(g))}function l(a,b){return j(a)-j(b)}function k(a,c){return b.relativeTime[a].replace(/%d/i,c||1)}function j(a){return isNaN(a)?(new i(a)).date.getTime():a}function i(b,c){b&&b.date instanceof Date?this.date=b.date:c?this.date=h(b,c):this.date=b===a?new Date:b instanceof Date?b:f(b)?g(b):new Date(b)}function h(a,b){function j(a,b){switch(a){case"M":case"MM":c[1]=~~b-1;break;case"D":case"DD":case"DDD":case"DDDD":c[2]=~~b;break;case"YY":b=~~b,c[0]=b+(b>70?1900:2e3);break;case"YYYY":c[0]=~~b;break;case"a":case"A":i=b.toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b}}var c=[0],d=/[0-9a-zA-Z]+/g,e=a.match(d),f=b.match(d),h,i;for(h=0;h11?"pm":"am";case"A":return i>11?"PM":"AM";case"H":return i;case"HH":return d(i,2);case"h":return i%12||12;case"hh":return d(i%12||12,2);case"m":return j;case"mm":return d(j,2);case"s":return k;case"ss":return d(k,2);case"z":return o("zz").replace(n,"");case"zz":c=l.indexOf("(");if(c>-1)return l.slice(c+1,l.indexOf(")"));return l.slice(l.indexOf(":")).replace(n,"");default:return a.replace("\\","")}}var c=this.date,e=c.getMonth(),f=c.getDate(),g=c.getFullYear(),h=c.getDay(),i=c.getHours(),j=c.getMinutes(),k=c.getSeconds(),l=c.toString(),m=/(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|zz?)/g,n=/[^A-Z]/g;return a.replace(m,o)},add:function(a){this.date=e(this.date,a,1);return this},subtract:function(a){this.date=e(this.date,a,-1);return this},from:function(a,c,d){var e=l(this.date,a),f=e<0?b.relativeTime.past:b.relativeTime.future;return d?e:c?m(e):f.replace(/%s/i,m(e))},fromNow:function(a,b){return this.from(new i,a,b)},isLeapYear:function(){var a=this.date.getFullYear();return a%4===0&&a%100!==0||a%400===0}},typeof window=="undefined"&&typeof module!="undefined"?module.exports=b:(this._!==a&&this._.mixin!==a&&this._.mixin({date:b}),this._date=b)})() \ No newline at end of file