// helper function for _.addTime and _.subtractTime
function dateAddRemove(_this, input, adding){
var self = _this.date,
- ms = (input.ms || input[6] || 0) +
- (input.s || input[5] || 0) * 1e3 + // 1000
- (input.m || input[4] || 0) * 6e4 + // 1000 * 60
- (input.h || input[3] || 0) * 36e5 + // 1000 * 60 * 60
- (input.d || input[2] || 0) * 864e5 + // 1000 * 60 * 60 * 24
- (input.w || 0) * 6048e5, // 1000 * 60 * 60 * 24 * 7
- M = (input.M || input[1] || 0) +
- (input.y || input[0] || 0) * 12,
+ ms = (input.ms || 0) +
+ (input.s || 0) * 1e3 + // 1000
+ (input.m || 0) * 6e4 + // 1000 * 60
+ (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) +
+ (input.y || 0) * 12,
currentDate;
if (ms) {
self.setMilliseconds(self.getMilliseconds() + ms * adding);
// array = new Date(array).getTime()
// string = new Date(string).getTime()
function makeInputMilliseconds(input){
- return input === undefined ? _d.now(true) :
+ return input === undefined ? new Date().getTime() :
!isNaN(input) ? input :
+ input instanceof _Date ? input.date.getTime() :
_.isDate(input) ? input.getTime() :
_.isArray(input) && input.length > 2 ? dateFromArray(input).getTime() :
new Date(input).getTime();
// number = new Date(number)
// string = new Date(string)
function makeInputDate(input){
- return input === undefined ? _d.now() :
+ return input === undefined ? new Date() :
+ input instanceof _Date ? input.date :
_.isDate(input) ? input :
_.isArray(input) && input.length > 2 ? dateFromArray(input) :
new Date(input);
return this;
}
- // cache prototype for minification
- _Date.prototype = new Date;
-
_Date.prototype.format = function(inputString) {
// shortcuts to this and getting time functions
// done to save bytes in minification
return makeInputMilliseconds(time) - makeInputMilliseconds(now);
}
- _Date.prototype.from = function(time, asMilliseconds) {
- var difference = msApart(this.date, time),
- string = difference < 0 ? wordsTimeAgo.past : wordsTimeAgo.future;
- return asMilliseconds ? difference : string.replace(/%s/i, this.relative(difference));
- }
-
- _Date.prototype.fromNow = function(asMilliseconds) {
- return this.from(_.now, asMilliseconds);
- }
-
- _Date.prototype.isLeapYear = function() {
- return _.isLeapYear(this.date.getFullYear());
- }
-
- _Date.prototype.relative = function(milliseconds) {
- var seconds = Math.abs(makeInputMilliseconds(milliseconds)) / 1000,
+ function relativeTime(milliseconds) {
+ var seconds = Math.abs(milliseconds) / 1000,
minutes = seconds / 60,
hours = minutes / 60,
days = hours / 24,
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) ||
+ days < 25 && substituteTimeAgo('dd', days | 0) ||
+ days < 45 && substituteTimeAgo('M') ||
+ days < 350 && substituteTimeAgo('MM', (days + 15) / 30 | 0) ||
years < 2 && substituteTimeAgo('y') ||
substituteTimeAgo('yy', years | 0);
}
+ _Date.prototype.from = function(time, withoutSuffix, asMilliseconds) {
+ var difference = msApart(this.date, time),
+ string = difference < 0 ? wordsTimeAgo.past : wordsTimeAgo.future;
+ return asMilliseconds ? difference :
+ withoutSuffix ? relativeTime(difference) :
+ string.replace(/%s/i, relativeTime(difference));
+ }
+
+ _Date.prototype.fromNow = function(withoutSuffix, asMilliseconds) {
+ return this.from(_.now(), withoutSuffix, asMilliseconds);
+ }
+
+ _Date.prototype.isLeapYear = function() {
+ return _.isLeapYear(this.date.getFullYear());
+ }
+
// underscore mixins
_d = {
date : function(input) {
return new _Date(input);
},
now : function(asTimestamp) {
- return asTimestamp ? new Date().getTime() : new Date();
+ return asTimestamp ? new Date().getTime() : _d.date();
},
isLeapYear : function(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
});
test("_.date().relative()", 11, function() {
- equal(_.date().relative(1000 * 30), "seconds");
- equal(_.date().relative(1000 * 60), "a minute");
- equal(_.date().relative(1000 * 60 * 5), "5 minutes");
- equal(_.date().relative(1000 * 60 * 60), "an hour");
- equal(_.date().relative(1000 * 60 * 60 * 5), "5 hours");
- equal(_.date().relative(1000 * 60 * 60 * 24), "a day");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 5), "5 days");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 30), "a month");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 30 * 5), "5 months");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 30 * 12), "a year");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 365 * 5), "5 years");
+ var start = _.date([2007, 1, 28]);
+ equal(start.from(_.date([2007, 1, 28]).add({s:30}), true), "seconds");
+ equal(start.from(_.date([2007, 1, 28]).add({s:60}), true), "a minute");
+ equal(start.from(_.date([2007, 1, 28]).add({m:5}), true), "5 minutes");
+ equal(start.from(_.date([2007, 1, 28]).add({h:1}), true), "an hour");
+ equal(start.from(_.date([2007, 1, 28]).add({h:5}), true), "5 hours");
+ equal(start.from(_.date([2007, 1, 28]).add({d:1}), true), "a day");
+ equal(start.from(_.date([2007, 1, 28]).add({d:5}), true), "5 days");
+ equal(start.from(_.date([2007, 1, 28]).add({M:1}), true), "a month");
+ equal(start.from(_.date([2007, 1, 28]).add({M:5}), true), "5 months");
+ equal(start.from(_.date([2007, 1, 28]).add({y:1}), true), "a year");
+ equal(start.from(_.date([2007, 1, 28]).add({y:5}), true), "5 years");
});
test("_.fromNow()", 2, function() {
$(function() {
module("Date");
+
+ test("_.date()", 6, function() {
+ ok(_.isDate(_.date([2010, 1, 12]).date), "[2010, 1, 12]");
+ ok(_.isDate(_.date([2010, 1, 12, 1]).date), "[2010, 1, 12, 1]");
+ ok(_.isDate(_.date().date), "undefined");
+ ok(_.isDate(_.date("Aug 9, 1995").date), "Aug 9, 1995");
+ ok(_.isDate(_.date("Mon, 25 Dec 1995 13:30:00 GMT").date), "Mon, 25 Dec 1995 13:30:00 GMT");
+ deepEqual(_.date(new Date(2010, 1, 14, 15, 25, 50, 125)), _.date([2010, 1, 14, 15, 25, 50, 125]), "constructing with array === constructing with new Date()");
+ });
+
+ test("_.now()", 1, function() {
+ deepEqual(_.date(), _.now(), "_.now returns wrapped date");
+ });
- test("_.formatDate()", 14, function() {
+ test("_.date().format()", 14, function() {
var dateTest = new Date(2010, 1, 14, 15, 25, 50, 125);
var _date = _.date(dateTest);
equal(_date.format("a A"), "pm PM");
equal(_date.format("t\\he DDDo \\d\\ay of t\\he ye\\ar"), "the 45th day of the year");
});
-
- test("_.date()", 6, function() {
- ok(_.isDate(_.date([2010, 1, 12])), "[2010, 1, 12]");
- ok(_.isDate(_.date([2010, 1, 12, 1])), "[2010, 1, 12, 1]");
- ok(_.isDate(_.date()), "undefined");
- ok(_.isDate(_.date("Aug 9, 1995")), "Aug 9, 1995");
- ok(_.isDate(_.date("Mon, 25 Dec 1995 13:30:00 GMT")), "Mon, 25 Dec 1995 13:30:00 GMT");
- deepEqual(_.date(new Date(2010, 1, 14, 15, 25, 50, 125)), _.date([2010, 1, 14, 15, 25, 50, 125]), "native date constructor === _.date([]);");
- });
- test("_.addTime() + _.subtractTime()", 5, function() {
+ test("_.date().add() + _.date().subtract()", 5, function() {
equal(_([2010, 1, 14, 15, 25, 50, 125]).date().add({ms:200,s:10,m:10,h:2,d:3,M:2,y:3}).format("MMMM Do YYYY, h:mm:ss a"), "April 17th 2013, 5:36:00 pm");
equal(_([2010, 0, 31]).date().format("MMMM Do YYYY"), "January 31st 2010");
equal(_([2010, 0, 31]).date().add({M:1}).format("MMMM Do YYYY"), "February 28th 2010");
- equal(_([2007, 1, 28]).date().format("MMMM Do YYYY"), "February 28th 2007");
- equal(_([2007, 1, 28]).date().subtract({M:1}).format("MMMM Do YYYY"), "January 28th 2007");
+ equal(_.date([2007, 1, 28]).format("MMMM Do YYYY"), "February 28th 2007");
+ equal(_.date([2007, 1, 28]).subtract({M:1}).format("MMMM Do YYYY"), "January 28th 2007");
});
- test("_.relativeTime()", 11, function() {
- equal(_.date().relative(1000 * 30), "less than a minute");
- equal(_.date().relative(1000 * 60), "about a minute");
- equal(_.date().relative(1000 * 60 * 5), "5 minutes");
- equal(_.date().relative(1000 * 60 * 60), "about an hour");
- equal(_.date().relative(1000 * 60 * 60 * 5), "about 5 hours");
- equal(_.date().relative(1000 * 60 * 60 * 24), "a day");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 5), "5 days");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 30), "about a month");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 30 * 5), "5 months");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 30 * 12), "about a year");
- equal(_.date().relative(1000 * 60 * 60 * 24 * 365 * 5), "5 years");
+ test("_.date().from() -- suffixless", 11, function() {
+ var start = _.date([2007, 1, 28]);
+ equal(start.from(_.date([2007, 1, 28]).add({s:30}), true), "less than a minute");
+ equal(start.from(_.date([2007, 1, 28]).add({s:60}), true), "about a minute");
+ equal(start.from(_.date([2007, 1, 28]).add({m:5}), true), "5 minutes");
+ equal(start.from(_.date([2007, 1, 28]).add({h:1}), true), "about an hour");
+ equal(start.from(_.date([2007, 1, 28]).add({h:5}), true), "about 5 hours");
+ equal(start.from(_.date([2007, 1, 28]).add({d:1}), true), "a day");
+ equal(start.from(_.date([2007, 1, 28]).add({d:5}), true), "5 days");
+ equal(start.from(_.date([2007, 1, 28]).add({M:1}), true), "about a month");
+ equal(start.from(_.date([2007, 1, 28]).add({M:5}), true), "5 months");
+ equal(start.from(_.date([2007, 1, 28]).add({y:1}), true), "about a year");
+ equal(start.from(_.date([2007, 1, 28]).add({y:5}), true), "5 years");
});
- test("_.msApart()", 5, function() {
- equal(_.date(1000).from(0, true), 1000, "1 second (ms) - 0 = 1000");
- equal(_.date(1000).from(500, true), 500, "1 second (ms) - .5 second (ms) = -500");
- equal(_.date(0).from(1000, true), -1000, "0 - 1 second (ms) = -1000");
- equal(_.date(new Date(1000)).from(1000, true), 0, "1 second (date) - 1 second (ms) = 0");
+ test("_.date().from() -- asMilliseconds", 5, function() {
+ equal(_.date(1000).from(0, true, true), 1000, "1 second (ms) - 0 = 1000");
+ equal(_.date(1000).from(500, false, true), 500, "1 second (ms) - .5 second (ms) = -500");
+ equal(_.date(0).from(1000, false, true), -1000, "0 - 1 second (ms) = -1000");
+ equal(_.date(new Date(1000)).from(1000, false, true), 0, "1 second (date) - 1 second (ms) = 0");
var oneHourDate = new Date(),
nowDate = new Date();
oneHourDate.setHours(oneHourDate.getHours() + 1);
- equal(_.date(oneHourDate).from(nowDate, true), 60 * 60 * 1000, "1 hour from now = 360000");
+ equal(_.date(oneHourDate).from(nowDate, false, true), 60 * 60 * 1000, "1 hour from now = 360000");
});
- test("_.fromNow()", 2, function() {
+ test("_.date().from() -- with suffix", 2, function() {
equal(_.date(30000).from(0), "in less than a minute");
equal(_.date(0).from(30000), "less than a minute ago");
});
+
+ test("_.date().fromNow()", 2, function() {
+ equal(_.now().add({s:30}).fromNow(), "in less than a minute");
+ equal(_.now().add({d:5}).fromNow(), "in 5 days");
+ });
test("_.isLeapYear()", function() {
expect(7);