Date.humanize returns a human readable string for a Date based on the format string that was passed in.
var date = new Date(2010, 1, 14, 15, 25, 50, 125);
- date.humanize("w, l D1 Y, h:m2:s2 a"); // "Sunday, February 14th 2010, 3:25:50 pm"
- date.humanize("w1, hA"); // "Sun, 3PM"
+ date.humanize("dddd, MMMM Do YYYY, h:mm:ss a"); // "Sunday, February 14th 2010, 3:25:50 pm"
+ date.humanize("ddd, hA"); // "Sun, 3PM"
-The formats are created by creating a string of replacable characters with optional flags.
-
-For numerical outputs, appending 1 will add an ordinal, appending 2 will zero fill, and appending 3 will both zero fill and add an ordinal.
-
-For string outputs, appending 1 will return a 3 character shortening of the string.
+The formats are created by creating a string of replacable characters.
### Month
<table>
<tr>
<th>Input</th>
- <td>L</td>
- <td>L1</td>
- <td>L2</td>
- <td>L3</td>
+ <th>Output</th>
</tr>
<tr>
- <th>Output</th>
+ <td colspan="2" align="center">Month</td>
+ </tr>
+ <tr>
+ <td>M</td>
<td>1 2 ... 11 12</td>
+ </tr>
+ <tr>
+ <td>Mo</td>
<td>1st 2nd ... 11th 12th</td>
+ </tr>
+ <tr>
+ <td>MM</td>
<td>01 02 ... 11 12</td>
- <td>01st 02nd ... 11th 12th</td>
</tr>
-</table>
-The string month names use lowercase L
-<table>
<tr>
- <th>Input</th>
- <td>l</td>
- <td>l1</td>
+ <td>MMM</td>
+ <td>Jan Feb ... Nov Dec</td>
</tr>
<tr>
- <th>Output</th>
+ <td>MMMM</td>
<td>January February ... November December</td>
- <td>Jan Feb ... Nov Dec</td>
</tr>
-</table>
-
-### Day of Month
-<table>
<tr>
- <th>Input</th>
+ <td colspan="2" align="center">Day of Month</td>
+ </tr>
+ <tr>
<td>D</td>
- <td>D1</td>
- <td>D2</td>
- <td>D3</td>
+ <td>1 2 ... 30 30</td>
</tr>
<tr>
- <th>Output</th>
- <td>1 2 ... 30 31</td>
+ <td>Do</td>
<td>1st 2nd ... 30th 31st</td>
+ </tr>
+ <tr>
+ <td>DD</td>
<td>01 02 ... 30 31</td>
- <td>01st 02nd ... 30th 31st</td>
</tr>
-</table>
-
-### Day of Year
-<table>
<tr>
- <th>Input</th>
- <td>D</td>
- <td>D1</td>
- <td>D2</td>
- <td>D3</td>
+ <td colspan="2" align="center">Day of Year</td>
</tr>
<tr>
- <th>Output</th>
+ <td>DDD</td>
<td>1 2 ... 364 365</td>
+ </tr>
+ <tr>
+ <td>DDDo</td>
<td>1st 2nd ... 364th 365th</td>
+ </tr>
+ <tr>
+ <td>DDDD</td>
<td>001 002 ... 364 365</td>
- <td>001st 002nd ... 364th 365th</td>
</tr>
-</table>
-
-### Weekday
-<table>
<tr>
- <th>Input</th>
- <td>W</td>
- <td>W1</td>
- <td>W2</td>
- <td>W3</td>
+ <td colspan="2" align="center">Day of Week</td>
</tr>
<tr>
- <th>Output</th>
- <td>1 2 ... 6 7</td>
- <td>1st 2nd ... 6th 7th</td>
- <td>1 2 ... 6 7</td>
- <td>1st 2nd ... 6th 7th</td>
+ <td>d</td>
+ <td>0 1 ... 5 6</td>
</tr>
-</table>
-<table>
<tr>
- <th>Input</th>
- <td>w</td>
- <td>w1</td>
+ <td>do</td>
+ <td>0th 1st ... 5th 6th</td>
</tr>
<tr>
- <th>Output</th>
- <td>Sunday Monday ... Friday Saturday</td>
+ <td>ddd</td>
<td>Sun Mon ... Fri Sat</td>
</tr>
-</table>
-
-### Week of Year
-<table>
<tr>
- <th>Input</th>
- <td>K</td>
- <td>K1</td>
- <td>K2</td>
- <td>K3</td>
+ <td>dddd</td>
+ <td>Sunday Monday ... Friday Saturday</td>
</tr>
<tr>
- <th>Output</th>
+ <td colspan="2" align="center">Week of Year</td>
+ </tr>
+ <tr>
+ <td>w</td>
<td>1 2 ... 52 53</td>
+ </tr>
+ <tr>
+ <td>wo</td>
<td>1st 2nd ... 52nd 53rd</td>
+ </tr>
+ <tr>
+ <td>ww</td>
<td>01 02 ... 52 53</td>
- <td>01st 02nd ... 52nd 53rd</td>
</tr>
-</table>
-
-### Year
-Returns the 4 digit year for `Y`, and the last 2 digits for `Y1`.
-<table>
<tr>
- <th>Input</th>
- <td>Y</td>
- <td>Y1</td>
+ <td colspan="2" align="center">Year</td>
</tr>
<tr>
- <th>Output</th>
- <td>1970 1971 ... 2029 2030</td>
+ <td>YY</td>
<td>70 71 ... 29 30</td>
</tr>
-</table>
-
-### AM/PM
-Returns uppercase `AM || PM` for uppercase `A` and lowercase `am || pm` for lowercase `a`.
-<table>
<tr>
- <th>Input</th>
- <td>A</td>
- <td>a</td>
+ <td>YYYY</td>
+ <td>1970 1971 ... 2029 2030</td>
</tr>
<tr>
- <th>Output</th>
+ <td colspan="2" align="center">AM/PM</td>
+ </tr>
+ <tr>
+ <td>A</td>
<td>AM PM</td>
+ </tr>
+ <tr>
+ <td>a</td>
<td>am pm</td>
</tr>
-</table>
-
-### Hour
-Returns 24 hour for uppercase `H` and 12 hour for lowercase `h`.
-<table>
<tr>
- <th>Input</th>
- <td>H</td>
- <td>H1</td>
- <td>H2</td>
- <td>H3</td>
- <td>h</td>
- <td>h1</td>
- <td>h2</td>
- <td>h3</td>
+ <td colspan="2" align="center">Hour</td>
</tr>
<tr>
- <th>Output</th>
+ <td>H</td>
<td>0 1 ... 22 23</td>
- <td>0th 1st ... 22nd 23rd</td>
+ </tr>
+ <tr>
+ <td>HH</td>
<td>00 01 ... 22 23</td>
- <td>00th 01st ... 22nd 23rd</td>
+ </tr>
+ <tr>
+ <td>h</td>
<td>1 2 ... 11 12</td>
- <td>1st 2nd ... 11th 12th</td>
+ </tr>
+ <tr>
+ <td>hh</td>
<td>01 02 ... 11 12</td>
- <td>01st 02nd ... 11th 12th</td>
</tr>
-</table>
-
-### Minute
-<table>
<tr>
- <th>Input</th>
- <td>m</td>
- <td>m1</td>
- <td>m2</td>
- <td>m3</td>
+ <td colspan="2" align="center">Minute</td>
</tr>
<tr>
- <th>Output</th>
+ <td>m</td>
<td>0 1 ... 58 59</td>
- <td>0th 1st ... 58th 59th</td>
+ </tr>
+ <tr>
+ <td>mm</td>
<td>00 01 ... 58 59</td>
- <td>00th 01st ... 58th 59th</td>
</tr>
-</table>
-
-### Second
-<table>
<tr>
- <th>Input</th>
- <td>s</td>
- <td>s1</td>
- <td>s2</td>
- <td>s3</td>
+ <td colspan="2" align="center">Second</td>
</tr>
<tr>
- <th>Output</th>
+ <td>s</td>
<td>0 1 ... 58 59</td>
- <td>0th 1st ... 58th 59th</td>
+ </tr>
+ <tr>
+ <td>ss</td>
<td>00 01 ... 58 59</td>
- <td>00th 01st ... 58th 59th</td>
</tr>
</table>
-
Underscore mixin functions
==========================
// (c) 2011 Tim Wood
// Underscore.date is freely distributable under the terms of the MIT license.
//
-// Version 0.2.0
+// Version 0.3.0
/*global _:false */
(function(Date, _, undefined){
// assign variables here so they can be overwritten for i18n or customization
- var self = this, _d,
- wordsMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
- wordsWeekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
- wordsTimeAgo = {
- future: "in %s",
- past: "%s ago",
- s: "less than a minute",
- m: "about a minute",
- mm: "%d minutes",
- h: "about an hour",
- hh: "about %d hours",
- d: "a day",
- dd: "%d days",
- M: "about a month",
- MM: "%d months",
- y: "about a year",
- yy: "%d years"
- };
-
- // add ordinal to number
- function createOrdinal(number) {
- return ((number / 10 | 0) === 1) ? 'th' :
- (number % 10 === 1) ? 'st' :
- (number % 10 === 2) ? 'nd' :
- (number % 10 === 3) ? 'rd' : 'th';
- }
-
- // left zero fill a number
- function leftZeroFill(number, targetLength) {
- var output = number + '';
- while (output.length < targetLength) {
- output = '0' + output;
- }
- return output;
- }
-
- // Date.prototype.humanize
- function humanize(inputString) {
- // shortcuts to this and getting time functions
- // done to save bytes in minification
- var self = this,
- currentMonth = self.getMonth(),
- currentDate = self.getDate(),
- currentYear = self.getFullYear(),
- currentDay = self.getDay(),
- currentHours = self.getHours(),
- currentMinutes = self.getMinutes(),
- currentSeconds = self.getSeconds(),
- charactersToReplace = /Mo|MM?M?M?|Do|DDDo|DD?D?D?|do|dd?d?d?|w[o|w]?|YYYY|YY|[aA]|hh?|HH?|mm?|ss?/g,
- formatFunctions = {
- // MONTH
- M : function() {
- return currentMonth + 1;
- },
- Mo : function() {
- return (currentMonth + 1) + createOrdinal(currentMonth + 1);
- },
- MM : function() {
- return leftZeroFill(currentMonth + 1, 2);
- },
- MMM : function() {
- return wordsMonths[currentMonth].slice(0, 3);
-
- },
- MMMM : function() {
- return wordsMonths[currentMonth];
-
- },
-
- // DAY OF MONTH
- D : function() {
- return currentDate;
- },
- Do : function() {
- return currentDate + createOrdinal(currentDate);
- },
- DD : function() {
- return leftZeroFill(currentDate, 2);
- },
-
- // DAY OF YEAR
- DDD : function() {
- var a = new Date(currentYear, currentMonth, currentDate),
- b = new Date(currentYear, 0, 1);
- return ((a - b) / 864e5) + 1.5 | 0;
- },
- DDDo : function() {
- var DDD = formatFunctions.DDD();
- return DDD + createOrdinal(DDD);
- },
- DDDD : function() {
- return leftZeroFill(formatFunctions.DDD(), 3);
- },
-
- // WEEKDAY
- d : function() {
- return currentDay;
- },
- do : function() {
- return currentDay + createOrdinal(currentDay);
- },
- dd : function() {
- return leftZeroFill(currentDay, 2);
- },
- ddd : function() {
- return wordsWeekdays[currentDay].slice(0, 3);
- },
- dddd : function() {
- return wordsWeekdays[currentDay];
- },
-
- // WEEK OF YEAR
- w : function() {
- var a = new Date(currentYear, currentMonth, currentDate - currentDay + 5),
- b = new Date(a.getFullYear(), 0, 4);
- return (a - b) / 864e5 / 7 + 1.5 | 0;
- },
- wo : function() {
- var w = formatFunctions.w();
- return w + createOrdinal(w);
- },
- ww : function() {
- return leftZeroFill(formatFunctions.w(), 2);
- },
-
- // YEAR
- YY : function() {
- return (currentYear + '').slice(-2);
- },
- YYYY : function(shorthand) {
- return currentYear;
- },
-
- // AM / PM
- a : function() {
- return currentHours > 11 ? 'pm' : 'am';
- },
- A : function() {
- return currentHours > 11 ? 'PM' : 'AM';
- },
-
- // 24 HOUR
- H : function() {
- return currentHours;
- },
- HH : function() {
- return leftZeroFill(currentHours, 2);
- },
-
- // 12 HOUR
- h : function() {
- return currentHours % 12 || 12;
- },
- hh : function() {
- return leftZeroFill(currentHours % 12 || 12, 2);
- },
-
- // MINUTE
- m : function() {
- return currentMinutes;
- },
- mm : function() {
- return leftZeroFill(currentMinutes, 2);
- },
-
- // SECOND
- s : function() {
- return currentSeconds;
- },
- ss : function() {
- return leftZeroFill(currentSeconds, 2);
- }
- };
-
- // check if the character is a format
- // return formatted string or non string.
- function replaceFunction(input) {
- return formatFunctions[input] ? formatFunctions[input]() : input;
- }
-
- return inputString.replace(charactersToReplace, replaceFunction);
- }
-
- /*
- * Underscore mixins
- */
- function makeInputMilliseconds(input){
- return input === undefined ? _d.now(true) :
- input instanceof Date ? input.getTime() : input;
- }
-
- function substituteTimeAgo(string, number) {
+ var self = this, _d,
+ wordsMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ wordsWeekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ wordsTimeAgo = {
+ future: "in %s",
+ past: "%s ago",
+ s: "less than a minute",
+ m: "about a minute",
+ mm: "%d minutes",
+ h: "about an hour",
+ hh: "about %d hours",
+ d: "a day",
+ dd: "%d days",
+ M: "about a month",
+ MM: "%d months",
+ y: "about a year",
+ yy: "%d years"
+ };
+
+ // add ordinal to number
+ function createOrdinal(number) {
+ return ((number / 10 | 0) === 1) ? 'th' :
+ (number % 10 === 1) ? 'st' :
+ (number % 10 === 2) ? 'nd' :
+ (number % 10 === 3) ? 'rd' : 'th';
+ }
+
+ // left zero fill a number
+ function leftZeroFill(number, targetLength) {
+ var output = number + '';
+ while (output.length < targetLength) {
+ output = '0' + output;
+ }
+ return output;
+ }
+
+ // Date.prototype.humanize
+ function humanize(inputString) {
+ // shortcuts to this and getting time functions
+ // done to save bytes in minification
+ var self = this,
+ currentMonth = self.getMonth(),
+ currentDate = self.getDate(),
+ currentYear = self.getFullYear(),
+ currentDay = self.getDay(),
+ currentHours = self.getHours(),
+ currentMinutes = self.getMinutes(),
+ currentSeconds = self.getSeconds(),
+ charactersToReplace = /Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?/g,
+ formatFunctions = {
+ // MONTH
+ M : function() {
+ return currentMonth + 1;
+ },
+ Mo : function() {
+ return (currentMonth + 1) + createOrdinal(currentMonth + 1);
+ },
+ MM : function() {
+ return leftZeroFill(currentMonth + 1, 2);
+ },
+ MMM : function() {
+ return wordsMonths[currentMonth].slice(0, 3);
+
+ },
+ MMMM : function() {
+ return wordsMonths[currentMonth];
+
+ },
+
+ // DAY OF MONTH
+ D : function() {
+ return currentDate;
+ },
+ Do : function() {
+ return currentDate + createOrdinal(currentDate);
+ },
+ DD : function() {
+ return leftZeroFill(currentDate, 2);
+ },
+
+ // DAY OF YEAR
+ DDD : function() {
+ var a = new Date(currentYear, currentMonth, currentDate),
+ b = new Date(currentYear, 0, 1);
+ return ((a - b) / 864e5) + 1.5 | 0;
+ },
+ DDDo : function() {
+ var DDD = formatFunctions.DDD();
+ return DDD + createOrdinal(DDD);
+ },
+ DDDD : function() {
+ return leftZeroFill(formatFunctions.DDD(), 3);
+ },
+
+ // WEEKDAY
+ d : function() {
+ return currentDay;
+ },
+ 'do' : function() {
+ return currentDay + createOrdinal(currentDay);
+ },
+ ddd : function() {
+ return wordsWeekdays[currentDay].slice(0, 3);
+ },
+ dddd : function() {
+ return wordsWeekdays[currentDay];
+ },
+
+ // WEEK OF YEAR
+ w : function() {
+ var a = new Date(currentYear, currentMonth, currentDate - currentDay + 5),
+ b = new Date(a.getFullYear(), 0, 4);
+ return (a - b) / 864e5 / 7 + 1.5 | 0;
+ },
+ wo : function() {
+ var w = formatFunctions.w();
+ return w + createOrdinal(w);
+ },
+ ww : function() {
+ return leftZeroFill(formatFunctions.w(), 2);
+ },
+
+ // YEAR
+ YY : function() {
+ return (currentYear + '').slice(-2);
+ },
+ YYYY : function(shorthand) {
+ return currentYear;
+ },
+
+ // AM / PM
+ a : function() {
+ return currentHours > 11 ? 'pm' : 'am';
+ },
+ A : function() {
+ return currentHours > 11 ? 'PM' : 'AM';
+ },
+
+ // 24 HOUR
+ H : function() {
+ return currentHours;
+ },
+ HH : function() {
+ return leftZeroFill(currentHours, 2);
+ },
+
+ // 12 HOUR
+ h : function() {
+ return currentHours % 12 || 12;
+ },
+ hh : function() {
+ return leftZeroFill(currentHours % 12 || 12, 2);
+ },
+
+ // MINUTE
+ m : function() {
+ return currentMinutes;
+ },
+ mm : function() {
+ return leftZeroFill(currentMinutes, 2);
+ },
+
+ // SECOND
+ s : function() {
+ return currentSeconds;
+ },
+ ss : function() {
+ return leftZeroFill(currentSeconds, 2);
+ }
+ };
+
+ // check if the character is a format
+ // return formatted string or non string.
+ function replaceFunction(input) {
+ return formatFunctions[input] ? formatFunctions[input]() : input;
+ }
+
+ return inputString.replace(charactersToReplace, replaceFunction);
+ }
+
+ /*
+ * Underscore mixins
+ */
+ function makeInputMilliseconds(input){
+ return input === undefined ? _d.now(true) :
+ input instanceof Date ? input.getTime() : input;
+ }
+
+ function substituteTimeAgo(string, number) {
return wordsTimeAgo[string].replace(/%d/i, number || 1);
}
-
- _d = {
- now : function(asTimestamp) {
- return asTimestamp ? new Date().getTime() : new Date();
- },
- relativetime : function(milliseconds) {
- var seconds = Math.abs(makeInputMilliseconds(milliseconds)) / 1000,
- minutes = seconds / 60,
- hours = minutes / 60,
- days = hours / 24,
- years = days / 365;
- return seconds < 45 && substituteTimeAgo('s', seconds | 0) ||
- seconds < 90 && substituteTimeAgo('m') ||
- minutes < 45 && substituteTimeAgo('mm', minutes | 0) ||
- minutes < 90 && substituteTimeAgo('h') ||
- hours < 24 && substituteTimeAgo('hh', hours | 0) ||
- hours < 48 && substituteTimeAgo('d') ||
- days < 30 && substituteTimeAgo('dd', days | 0) ||
- days < 60 && substituteTimeAgo('M') ||
- days < 350 && substituteTimeAgo('MM', days / 30 | 0) ||
- years < 2 && substituteTimeAgo('y') ||
- substituteTimeAgo('yy', years | 0);
- },
- msapart : function(time, now) {
- return makeInputMilliseconds(time) - makeInputMilliseconds(now);
- },
- fromnow : function(time, now) {
- var difference = _d.msapart(time, now),
- string = difference < 0 ? wordsTimeAgo.past : wordsTimeAgo.future;
- return string.replace(/%s/i, _d.relativetime(difference));
- },
- customizedate : function(input) {
- if (input.weekdays && _.isArray(input.weekdays) && input.weekdays.length === 7) {
- wordsWeekdays = input.weekdays;
- }
- if (input.months && _.isArray(input.months) && input.months.length === 12) {
- wordsMonths = input.months;
- }
- if (input.timeago) {
- _.extend(wordsTimeAgo, input.timeago);
- }
- if (input.ordinal && _.isFunction(input.ordinal)) {
- createOrdinal = input.ordinal;
- }
- }
- };
-
- // assign to prototype
- Date.prototype.humanize = humanize;
-
- // assign to global
- self._d = _d;
-
- // integrate with underscore.js
- if (self._) {
- self._.mixin(_d);
+
+ _d = {
+ now : function(asTimestamp) {
+ return asTimestamp ? new Date().getTime() : new Date();
+ },
+ relativetime : function(milliseconds) {
+ var seconds = Math.abs(makeInputMilliseconds(milliseconds)) / 1000,
+ minutes = seconds / 60,
+ hours = minutes / 60,
+ days = hours / 24,
+ years = days / 365;
+ return seconds < 45 && substituteTimeAgo('s', seconds | 0) ||
+ seconds < 90 && substituteTimeAgo('m') ||
+ minutes < 45 && substituteTimeAgo('mm', minutes | 0) ||
+ minutes < 90 && substituteTimeAgo('h') ||
+ hours < 24 && substituteTimeAgo('hh', hours | 0) ||
+ hours < 48 && substituteTimeAgo('d') ||
+ days < 30 && substituteTimeAgo('dd', days | 0) ||
+ days < 60 && substituteTimeAgo('M') ||
+ days < 350 && substituteTimeAgo('MM', days / 30 | 0) ||
+ years < 2 && substituteTimeAgo('y') ||
+ substituteTimeAgo('yy', years | 0);
+ },
+ msapart : function(time, now) {
+ return makeInputMilliseconds(time) - makeInputMilliseconds(now);
+ },
+ fromnow : function(time, now) {
+ var difference = _d.msapart(time, now),
+ string = difference < 0 ? wordsTimeAgo.past : wordsTimeAgo.future;
+ return string.replace(/%s/i, _d.relativetime(difference));
+ },
+ customizedate : function(input) {
+ if (input.weekdays && _.isArray(input.weekdays) && input.weekdays.length === 7) {
+ wordsWeekdays = input.weekdays;
+ }
+ if (input.months && _.isArray(input.months) && input.months.length === 12) {
+ wordsMonths = input.months;
+ }
+ if (input.timeago) {
+ _.extend(wordsTimeAgo, input.timeago);
+ }
+ if (input.ordinal && _.isFunction(input.ordinal)) {
+ createOrdinal = input.ordinal;
+ }
+ }
+ };
+
+ // assign to prototype
+ Date.prototype.humanize = humanize;
+
+ // assign to global
+ self._d = _d;
+
+ // integrate with underscore.js
+ if (_ && _.mixin) {
+ _.mixin(_d);
}
}(Date, _));
// (c) 2011 Tim Wood
// Underscore.date is freely distributable under the terms of the MIT license.
//
-// Version 0.2.0
+// Version 0.3.0
-function(a,b,c){function n(a,b){return h[a].replace(/%d/i,b||1)}function m(b){return b===c?e.now(!0):b instanceof a?b.getTime():b}function l(b){function p(a){var b=a.charAt(0),c=a.charAt(1)||0;return o[b]?o[b](c&1,c>>1):a}var c=this,d=c.getMonth(),e=c.getDate(),h=c.getFullYear(),i=c.getDay(),j=c.getHours(),l=c.getMinutes(),m=c.getSeconds(),n=/[a-z][0-9]?/gi,o={L:function(a,b){return k(d+1,b?2:0,a)},l:function(a){var b=f[d];return a?b.slice(0,3):b},D:function(a,b){return k(e,b?2:0,a)},d:function(b,c){var f=new a(h,d,e),g=new a(h,0,1);return k((f-g)/864e5+1.5|0,c?3:0,b)},W:function(a,b){return k(i,b?2:0,a)},w:function(a){var b=g[i];return a?b.slice(0,3):b},K:function(b,c){var f=new a(h,d,e-i+5),g=new a(f.getFullYear(),0,4);return k((f-g)/864e5/7+1.5|0,c?2:0,b)},Y:function(a){return a?(h+"").slice(-2):h},a:function(){return j>11?"pm":"am"},A:function(){return j>11?"PM":"AM"},H:function(a,b){return k(j,b?2:0,a)},h:function(a,b){return k(j%12||12,b?2:0,a)},m:function(a,b){return k(l,b?2:0,a)},s:function(a,b){return k(m,b?2:0,a)}};return b.replace(n,p)}function k(a,b,c){var d=b?j(a,b):a;return c?d+i(a):d}function j(a,b){var c=a+"";while(c.length<b)c="0"+c;return c}function i(a){return(a/10|0)===1?"th":a%10===1?"st":a%10===2?"nd":a%10===3?"rd":"th"}var d=this,e,f=["January","February","March","April","May","June","July","August","September","October","November","December"],g=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],h={future:"in %s",past:"%s ago",S:"less than a minute",m:"about a minute",M:"%d minutes",h:"about an hour",H:"about %d hours",d:"a day",D:"%d days",l:"about a month",L:"%d months",y:"about a year",Y:"%d years"};e={now:function(b){return b?(new a).getTime():new a},relativetime:function(a){var b=Math.abs(m(a))/1e3,c=b/60,d=c/60,e=d/24,f=e/365;return b<45&&n("S",b|0)||b<90&&n("m")||c<45&&n("M",c|0)||c<90&&n("h")||d<24&&n("H",d|0)||d<48&&n("d")||e<30&&n("D",e|0)||e<60&&n("l")||e<350&&n("L",e/30|0)||f<2&&n("y")||n("Y",f|0)},msapart:function(a,b){return m(a)-m(b)},fromnow:function(a,b){var c=e.msapart(a,b),d=c<0?h.past:h.future;return d.replace(/%s/i,e.relativetime(c))},customizedate:function(a){a.weekdays&&b.isArray(a.weekdays)&&a.weekdays.length===7&&(g=a.weekdays),a.months&&b.isArray(a.months)&&a.months.length===12&&(f=a.months),a.timeago&&b.extend(h,a.timeago),a.ordinal&&b.isFunction(a.ordinal)&&(i=a.ordinal)}},a.prototype.humanize=l,d._d=e,d._&&d._.mixin(e)})(Date,_)
+(function(a,b,c){function m(a,b){return h[a].replace(/%d/i,b||1)}function l(b){return b===c?e.now(!0):b instanceof a?b.getTime():b}function k(b){function q(a){return p[a]?p[a]():a}var c=this,d=c.getMonth(),e=c.getDate(),h=c.getFullYear(),k=c.getDay(),l=c.getHours(),m=c.getMinutes(),n=c.getSeconds(),o=/Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?/g,p={M:function(){return d+1},Mo:function(){return d+1+i(d+1)},MM:function(){return j(d+1,2)},MMM:function(){return f[d].slice(0,3)},MMMM:function(){return f[d]},D:function(){return e},Do:function(){return e+i(e)},DD:function(){return j(e,2)},DDD:function(){var b=new a(h,d,e),c=new a(h,0,1);return(b-c)/864e5+1.5|0},DDDo:function(){var a=p.DDD();return a+i(a)},DDDD:function(){return j(p.DDD(),3)},d:function(){return k},"do":function(){return k+i(k)},ddd:function(){return g[k].slice(0,3)},dddd:function(){return g[k]},w:function(){var b=new a(h,d,e-k+5),c=new a(b.getFullYear(),0,4);return(b-c)/864e5/7+1.5|0},wo:function(){var a=p.w();return a+i(a)},ww:function(){return j(p.w(),2)},YY:function(){return(h+"").slice(-2)},YYYY:function(a){return h},a:function(){return l>11?"pm":"am"},A:function(){return l>11?"PM":"AM"},H:function(){return l},HH:function(){return j(l,2)},h:function(){return l%12||12},hh:function(){return j(l%12||12,2)},m:function(){return m},mm:function(){return j(m,2)},s:function(){return n},ss:function(){return j(n,2)}};return b.replace(o,q)}function j(a,b){var c=a+"";while(c.length<b)c="0"+c;return c}function i(a){return(a/10|0)===1?"th":a%10===1?"st":a%10===2?"nd":a%10===3?"rd":"th"}var d=this,e,f=["January","February","March","April","May","June","July","August","September","October","November","December"],g=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],h={future:"in %s",past:"%s ago",s:"less than a minute",m:"about a minute",mm:"%d minutes",h:"about an hour",hh:"about %d hours",d:"a day",dd:"%d days",M:"about a month",MM:"%d months",y:"about a year",yy:"%d years"};e={now:function(b){return b?(new a).getTime():new a},relativetime:function(a){var b=Math.abs(l(a))/1e3,c=b/60,d=c/60,e=d/24,f=e/365;return b<45&&m("s",b|0)||b<90&&m("m")||c<45&&m("mm",c|0)||c<90&&m("h")||d<24&&m("hh",d|0)||d<48&&m("d")||e<30&&m("dd",e|0)||e<60&&m("M")||e<350&&m("MM",e/30|0)||f<2&&m("y")||m("yy",f|0)},msapart:function(a,b){return l(a)-l(b)},fromnow:function(a,b){var c=e.msapart(a,b),d=c<0?h.past:h.future;return d.replace(/%s/i,e.relativetime(c))},customizedate:function(a){a.weekdays&&b.isArray(a.weekdays)&&a.weekdays.length===7&&(g=a.weekdays),a.months&&b.isArray(a.months)&&a.months.length===12&&(f=a.months),a.timeago&&b.extend(h,a.timeago),a.ordinal&&b.isFunction(a.ordinal)&&(i=a.ordinal)}},a.prototype.humanize=k,d._d=e,b&&b.mixin&&b.mixin(e)})(Date,_)