Date API wrapper around Moment.js
/*jshint asi: false, bitwise: true, boss: false, curly: true, eqeqeq: true, eqnull: false, evil: false, forin: false, immed: true, laxbreak: false, newcap: true, noarg: true, noempty: true, nonew: false, nomen: false, onevar: true, plusplus: false, regexp: false, undef: true, sub: false, strict: false, white: false */ | |
/*jshint browser: true, maxerr: 50, passfail: false */ | |
/*global createModule: false */ | |
/** | |
* A set of utilities for working with Moments and Durations, which are | |
* sugar wrappers around Date and ms, respectively. | |
* | |
* This module calls out to vendor.moment, which provides the logic for working | |
* with dates and durations, but has a poor API. This wraps that API to be more | |
* to Gilt's library standards. | |
* | |
* @module common.date_utils | |
*/ | |
createModule( | |
'common.date_utils', | |
[ | |
'vendor.moment' | |
], | |
function (moment) { | |
var | |
Moment, | |
Duration, | |
addDurations, | |
subtractDurations, | |
diffDurations, | |
addToMoment, | |
subtractFromMoment, | |
diffMoments, | |
utcFilter, | |
mutateDuration, | |
makeMoment, | |
makeDuration; | |
/** | |
* Constructs a wrapper around a fixed "moment" in time. | |
* | |
* @constructor Moment | |
* @public | |
* | |
* @param {Mixed} [d] Any of: 1. ms from the epoch; 2. Date object; 3. A Date object parseable string; 4. subset of ISO-8601 String; 5. nothing | |
* | |
* @example | |
* new Moment(); | |
* new Moment(443768400000); | |
* new Moment(new Date(443768400000)); | |
* new Moment('Fri, 12 Oct 2012 19:15:56 UTC'); | |
* new Moment('1984-01-24'); | |
* new Moment('1984-01-24T00:00:00'); | |
* new Moment('1984-01-24T00:00:00 Z-08:00'); | |
*/ | |
Moment = function (d) { | |
if (!d) { | |
/* it is nothing */ | |
this._moment = moment(); | |
} else if (typeof d === 'number' || Object.prototype.toString.call(d) === '[object Date]') { | |
/* it is a ms number or a date object */ | |
this._moment = moment(d); | |
} else if (typeof d === 'string' && d.match(/\d{4}\-\d{2}\-\d{2}(T{2}:{2}:{2})?([\s\w\-\:]+)?/)) { | |
/* it is a string YYYY-MM-DDTHH:mm:ss z */ | |
this._moment = moment(d); | |
} else if (typeof d === 'string') { | |
/* We'll try date parsing it as a last resort */ | |
this._moment = moment(new Date(d)); | |
} | |
}; | |
Moment.prototype = { | |
/** | |
* Returns a clone of a given Moment instance. | |
* | |
* @method clone | |
* @public | |
* | |
* @return {Moment} A new Moment instance cloning the original | |
* | |
* @example | |
* m = new Moment(); | |
* n = m.clone(); | |
*/ | |
clone : function () { | |
return new Moment(this.toDate().valueOf()); | |
}, | |
/** | |
* Adds a Duration to the Moment instance. | |
* | |
* @method add | |
* @public | |
* | |
* @param {Duration|Mixed} duration A Duration object to add, or something that can construct a Duration | |
* | |
* @return {Moment} The same Moment instance, adjusted with the added Duration | |
* | |
* @example | |
* m = new Moment(); | |
* m.add(new Duration(1000)); // The moment is now 1 second in the future | |
* m.add(1000); // The moment is now 1 second in the future | |
*/ | |
add : function (duration) { | |
duration = makeDuration(duration); | |
this._moment.add(duration.getAsMilliseconds()); | |
return this; | |
}, | |
/** | |
* Subtracts a Duration from the Moment instance. | |
* | |
* @method subtract | |
* @public | |
* | |
* @param {Duration|Mixed} duration A Duration object to subtract, or something that can construct a Duration | |
* | |
* @return {Moment} The same Moment instance, adjusted with the subtracted Duration | |
* | |
* @example | |
* m = new Moment(); | |
* m.subtract(new Duration(1000)); // The moment is now 1 second in the past | |
* m.subtract(1000); // The moment is now 1 second in the past | |
*/ | |
subtract : function (duration) { | |
duration = makeDuration(duration); | |
this._moment.subtract(duration.getAsMilliseconds()); | |
return this; | |
}, | |
/** | |
* Converts the current Moment instance to its JS Date representation. | |
* | |
* @method toDate | |
* @public | |
* | |
* @return {Date} The JS Date representation of this Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.toDate(); // Date object for now | |
*/ | |
toDate : function () { | |
return new Date(this._moment.valueOf()); | |
}, | |
/** | |
* The timezone offset of this Moment instance in minutes. | |
* | |
* @method getTimezoneOffset | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the timezone offset in UTC (which of course would be 0) | |
* | |
* @return {Number} The offset of this Moment's time in minutes, opposite negative symbol of the UTC offset (360 = '-06:00') | |
* | |
* @example | |
* m = new Moment(); | |
* m.getTimezoneOffset(); // e.g. 360 (equal to -06:00) | |
* m.getTimezoneOffset({ utc : true }); // 0 | |
*/ | |
getTimezoneOffset : function (opts) { | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.zone(); | |
}); | |
}, | |
/** | |
* Whether or not this Moment instance is in daylight saving time. | |
* | |
* @method isDst | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the DST status in UTC (because UTC could bump it into a date outside the local date's DST) | |
* | |
* @return {Boolean} Whether this Moment instance is in daylight saving time | |
* | |
* @example | |
* m = new Moment(); | |
* m.isDst(); // True, it's October 2 now! | |
* m.isDst({ utc : true }); // Might push time to non-dst if converted to utc | |
*/ | |
isDst : function (opts) { | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.isDST(); | |
}); | |
}, | |
/** | |
* Whether or not this Moment instance is in a leap year. | |
* | |
* @method isLeapYear | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the leap year status in UTC (because UTC could bump it into a different year) | |
* | |
* @return {Boolean} Whether this Moment instance is in a leap year | |
* | |
* @example | |
* m = new Moment(); | |
* m.isLeapYear(); // True, it's 2012 now! | |
* m.isLeapYear({ utc : true }); // Could push the time to a non-leap year | |
*/ | |
isLeapYear : function (opts) { | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.isLeapYear(); | |
}); | |
}, | |
/** | |
* Gets the days in the current Moment instance's month. | |
* | |
* @method getDaysInMonth | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the days in this month in UTC (because UTC could bump it into a different month) | |
* | |
* @return {Number} The days of the month for this Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.getDaysInMonth(); // 31, it's October now! | |
* m.getDaysInMonth({ utc : true }); // Could bump to the next month | |
*/ | |
getDaysInMonth : function (opts) { | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.daysInMonth(); | |
}); | |
}, | |
/** | |
* Returns the milliseconds (0-9999) of a given Moment instance (Not | |
* passing through UTC filter because the result will not change). | |
* | |
* @method getMilliseconds | |
* @public | |
* | |
* @return {Number} The milliseconds of this Moment instance | |
* | |
* @example | |
* m = new Moment(1234567890); | |
* m.getMilliseconds(); // 890 | |
*/ | |
getMilliseconds : function () { | |
return this._moment.milliseconds(); | |
}, | |
/** | |
* Sets the milliseconds (0-9999) of a given Moment instance. | |
* | |
* @method setMilliseconds | |
* @public | |
* | |
* @param {Number} ms The milliseconds (0-9999) to set | |
* | |
* @return {Moment} The Moment instance | |
* | |
* @example | |
* m = new Moment(1234567890); | |
* m.setMilliseconds(999); // 1234567999 | |
*/ | |
setMilliseconds : function (ms) { | |
this._moment.milliseconds(ms); | |
return this; | |
}, | |
/** | |
* Returns the seconds (0-59) of a given Moment instance (Not passing | |
* through UTC filter because the result will not change). | |
* | |
* @method getSeconds | |
* | |
* @return {Number} The seconds of this Moment instance | |
* | |
* @example | |
* m = new Moment('2012-10-02'); | |
* m.getSeconds(); // 0 | |
*/ | |
getSeconds : function () { | |
return this._moment.seconds(); | |
}, | |
/** | |
* Sets the seconds (0-59) of a given Moment instance. | |
* | |
* @method setSeconds | |
* @public | |
* | |
* @param {Number} s The seconds (0-59) to set | |
* | |
* @return {Moment} The Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.setSeconds(59); | |
*/ | |
setSeconds : function (s) { | |
this._moment.seconds(s); | |
return this; | |
}, | |
/** | |
* Returns the minutes (0-59) of a given Moment instance. Yes, UTC is | |
* relevant in the case of Newfoundland and other off-by-half-hour | |
* timezones. | |
* | |
* @method getMinutes | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the minutes in UTC | |
* | |
* @return {Number} The minutes of this Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.getMinutes(); // 30, assume we are in Newfoundland | |
* m.getMinutes({ utc : true }); // 0 | |
*/ | |
getMinutes : function (opts) { | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.minutes(); | |
}); | |
}, | |
/** | |
* Sets the minutes (0-59) of a given Moment instance. | |
* | |
* @method setMinutes | |
* @public | |
* | |
* @param {Number} m The minutes (0-59) to set | |
* | |
* @return {Moment} The Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.setMinutes(59); | |
*/ | |
setMinutes : function (m) { | |
this._moment.minutes(m); | |
return this; | |
}, | |
/** | |
* Returns the time hour (0-23) of a given Moment instance. | |
* | |
* @method getHours | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the hours in UTC | |
* | |
* @return {Number} The hour (0-23) of this Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.getHours(); | |
* m.getHours({ utc : true }); | |
*/ | |
getHours : function (opts) { | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.hours(); | |
}); | |
}, | |
/** | |
* Sets the hours (0-23) of a given Moment instance. | |
* | |
* @method setHours | |
* @public | |
* | |
* @param {Number} h The hours (0-23) to set | |
* | |
* @return {Moment} The Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.setHours(23); | |
*/ | |
setHours : function (h) { | |
this._moment.hours(h); | |
return this; | |
}, | |
/** | |
* Returns the day of the week (0-6) of a given Moment instance. | |
* | |
* @method getDay | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the day in UTC | |
* | |
* @return {Number} The day of the week (0-6) of this Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.getDay(); // 0 through 6 | |
* m.getDay({ utc : true }); // UTC can move it into a different day | |
*/ | |
getDay : function (opts) { // Sunday 0, Saturday 6 | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.day(); | |
}); | |
}, | |
/** | |
* Returns the date (1-31) of a given Moment instance. | |
* | |
* @method getDate | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the date in UTC | |
* | |
* @return {Number} The date (1-31) of this Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.getDate(); // 1 through 31 | |
* m.getDate({ utc : true }); // UTC could move it into the next date | |
*/ | |
getDate : function (opts) { | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.date(); | |
}); | |
}, | |
/** | |
* Sets the date (1-31) of a given Moment instance. Note that moment.js | |
* will set Feb 31 to be Mar 2. We choose to allow this as a side effect | |
* rather than suppressing this behavior, allowing setDate to work without | |
* concerning itself with the end of the month. | |
* | |
* @method setDate | |
* @public | |
* | |
* @param {Number} d The date (1-31) to set | |
* | |
* @return {Moment} The Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.setDate(23); | |
* m.setDate(29 + n); // In September, if n is 2, the new date will be October 1. | |
*/ | |
setDate : function (d) { | |
this._moment.date(d); | |
return this; | |
}, | |
/** | |
* Returns the month of a given Moment instance. | |
* | |
* @method getMonth | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the month in UTC | |
* | |
* @return {Number} The month of this Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.getMonth(); // 0 through 11 | |
* m.getMonth({ utc : true }); // UTC could move it to the next month | |
*/ | |
getMonth : function (opts) { | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.month(); | |
}); | |
}, | |
/** | |
* Sets the month (0-11) of a given Moment instance. If the month is | |
* greater than 11, the Moment will switch over to the next year, for | |
* convenience and because moment.js has this behavior natively. | |
* | |
* @method setMonth | |
* @public | |
* | |
* @param {Number} m The month (0-11) to set, or greater than 11 to roll over to the next year | |
* | |
* @return {Moment} The Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.setMonth(0); | |
* m.setMonth(11); | |
*/ | |
setMonth : function (m) { | |
this._moment.month(m); | |
return this; | |
}, | |
/** | |
* Returns the year of a given Moment instance. | |
* | |
* @method getYear | |
* @public | |
* | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether or not to return the year in UTC | |
* | |
* @return {Number} The year of this Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.getYear(); | |
* m.getYear({ utc : true }); // UTC could move it to the next year | |
*/ | |
getYear : function (opts) { | |
var that = this; | |
return utcFilter(that._moment, opts, function () { | |
return that._moment.year(); | |
}); | |
}, | |
/** | |
* Sets the year of the current Moment instance. | |
* | |
* @method setYear | |
* @public | |
* | |
* @param {Number} y A year to set | |
* | |
* @return {Moment} The Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.setYear(1984); | |
*/ | |
setYear : function (y) { | |
this._moment.year(y); | |
return this; | |
}, | |
/** | |
* Sets the current Moment instance to the start of a time period. | |
* | |
* @method setToStartOf | |
* @public | |
* | |
* @param {String} param Any of 'day', 'month', 'year', 'minute', 'second', 'hour' | |
* | |
* @return {Moment} The Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.setToStartOf('year'); // first millisecond in year | |
*/ | |
setToStartOf : function (param) { // 'day', 'month', 'year', etc | |
this._moment.startOf(param); | |
return this; | |
}, | |
/** | |
* Sets the current Moment instance to the end of a time period. | |
* | |
* @method setToEndOf | |
* @public | |
* | |
* @param {String} param Any of 'day', 'month', 'year', 'minute', 'second', 'hour' | |
* | |
* @return {Moment} The Moment instance | |
* | |
* @example | |
* m = new Moment(); | |
* m.setToEndOf('month'); // last millisecond in month | |
*/ | |
setToEndOf : function (param) { // 'day', 'month', 'year' | |
this._moment.endOf(param); | |
return this; | |
} | |
}; | |
/** | |
* A wrapper around a length of time. Getters intentionally do not provide | |
* weeks, since weeks and days overlap. If you need weeks, do the math | |
* yourself. Also, you can construct a negative Duration with a number of ms, | |
* but not with an ISO string. | |
* | |
* @constructor Duration | |
* @public | |
* | |
* @param {Mixed} d Any of: 1. ms to wrap; 2. subset of ISO-8601 duration (but allowing spaces) | |
* | |
* @todo Optimize the regexes for matching durations. | |
*/ | |
Duration = function (d) { | |
var | |
p, | |
t, | |
durationMatches = {}; | |
if (typeof d === 'number') { | |
/* It's a number, hopefully a number of milliseconds, because that's what we're assuming */ | |
this._duration = moment.duration(d); | |
} else if (typeof d === 'string' && d.match(/^P/)) { | |
/* It's a string, hopefully iso P3Y6M4DT12H30M5S P 3Y 6M 4D T 12H 30M 5S */ | |
d = d.split('T'); | |
p = d[0].substring(1); /* can be empty string */ | |
t = d[1] || ''; /* can be empty string */ | |
durationMatches = { | |
seconds : t.match(/(\d+)S/) || [], | |
minutes : t.match(/(\d+)M/) || [], | |
hours : t.match(/(\d+)H/) || [], | |
days : p.match(/(\d+)D/) || [], | |
months : p.match(/(\d+)M/) || [], | |
years : p.match(/(\d+)Y/) || [] | |
}; | |
this._duration = moment.duration({ | |
seconds : parseInt(durationMatches.seconds[1], 10) || 0, | |
minutes : parseInt(durationMatches.minutes[1], 10) || 0, | |
hours : parseInt(durationMatches.hours[1], 10) || 0, | |
days : parseInt(durationMatches.days[1], 10) || 0, | |
months : parseInt(durationMatches.months[1], 10) || 0, | |
years : parseInt(durationMatches.years[1], 10) || 0 | |
}); | |
} | |
}; | |
Duration.prototype = { | |
/** | |
* Returns a clone of a given Duration instance. | |
* | |
* @method clone | |
* @public | |
* | |
* @return {Duration} A new Duration instance cloning the original | |
* | |
* @example | |
* d = new Duration(1000); dd = d.clone(); | |
*/ | |
clone : function () { | |
return new Duration(this.getAsMilliseconds()); | |
}, | |
/** | |
* Adds a Duration to this Duration. | |
* | |
* @method add | |
* @public | |
* | |
* @param {Duration|Mixed} duration A Duration to add to this one, or something that can construct a Duration | |
* | |
* @return {Duration} This Duration | |
* | |
* @example | |
* d = new Duration(1000); d.add(new Duration(2000)); | |
* d.getAsMilliseconds(); // 3000 | |
* d.add('PT 2S'); | |
* d.getAsMilliseconds(); // 5000 | |
*/ | |
add : function (duration) { | |
duration = makeDuration(duration); | |
var ms = duration.getAsMilliseconds(); | |
return mutateDuration(this, (this.getAsMilliseconds() + ms)); | |
}, | |
/** | |
* Subtracts a Duration from this Duration. | |
* | |
* @method subtract | |
* @public | |
* | |
* @param {Duration|Mixed} duration A Duration to subtract from this one, or something that can construct a Duration | |
* | |
* @return {Duration} This Duration | |
* | |
* @example | |
* d = new Duration(2000); d.subtract(new Duration(1000)); | |
* d.getAsMilliseconds(); // 1000 | |
* d.subtract(500); | |
* d.getAsMilliseconds(); // 500 | |
*/ | |
subtract : function (duration) { | |
duration = makeDuration(duration); | |
var ms = duration.getAsMilliseconds(); | |
return mutateDuration(this, (this.getAsMilliseconds() - ms)); | |
}, | |
/** | |
* Returns the milliseconds (0-9999) of a given Duration instance. | |
* | |
* @method getMilliseconds | |
* @public | |
* | |
* @return {Number} The milliseconds of this Duration instance | |
* | |
* @example | |
* d = new Duration(1000); e = new Duration(1002); | |
* d.getMilliseconds(); // 0 | |
* e.getMilliseconds(); // 2 | |
*/ | |
getMilliseconds : function () { | |
return this._duration.milliseconds(); | |
}, | |
/** | |
* Returns the given Duration instance expressed as milliseconds. | |
* | |
* @method getAsMilliseconds | |
* @public | |
* | |
* @return {Number} This Duration instance in milliseconds | |
* | |
* @example | |
* d = new Duration(1000); e = new Duration(1002); | |
* d.getAsMilliseconds(); // 1000 | |
* e.getAsMilliseconds(); // 1002 | |
*/ | |
getAsMilliseconds : function () { | |
return this._duration.asMilliseconds(); | |
}, | |
/** | |
* Returns the seconds (0-59) of a given Duration instance. | |
* | |
* @method getSeconds | |
* @public | |
* | |
* @return {Number} The seconds of this Duration instance | |
* | |
* @example | |
* d = new Duration('PT3M 22S'); e = new Duration('PT1M'); | |
* d.getSeconds(); // 22 | |
* e.getSeconds(); // 0 | |
*/ | |
getSeconds : function () { | |
return this._duration.seconds(); | |
}, | |
/** | |
* This Duration instance expressed as seconds. | |
* | |
* @method getAsSeconds | |
* @public | |
* | |
* @return {Number} This Duration instance in seconds | |
* | |
* @example | |
* d = new Duration('PT3M 22S'); e = new Duration('PT1M'); | |
* d.getAsSeconds(); // 202 | |
* e.getAsSeconds(); // 60 | |
*/ | |
getAsSeconds : function () { | |
return this._duration.asSeconds(); | |
}, | |
/** | |
* Returns the minutes (0-59) of a given Duration instance. | |
* | |
* @method getMinutes | |
* @public | |
* | |
* @return {Number} The minutes of this Duration instance | |
* | |
* @example | |
* d = new Duration('PT2H 3M'); e = new Duration('PT2H'); | |
* d.getMinutes(); // 3 | |
* e.getMinutes(); // 0 | |
*/ | |
getMinutes : function () { | |
return this._duration.minutes(); | |
}, | |
/** | |
* This Duration instance expressed as minutes. | |
* | |
* @method getAsMinutes | |
* @public | |
* | |
* @return {Number} This Duration instance in minutes | |
* | |
* @example | |
* d = new Duration('PT2H 3M'); e = new Duration('PT2H'); | |
* d.getAsMinutes(); // 123 | |
* e.getAsMinutes(); // 120 | |
*/ | |
getAsMinutes : function () { | |
return this._duration.asMinutes(); | |
}, | |
/** | |
* Returns the time hour (0-23) of a given Duration instance. | |
* | |
* @method getHours | |
* @public | |
* | |
* @return {Number} The hours (0-23) of this Duration instance | |
* | |
* @example | |
* d = new Duration('P1DT3H'); e = new Duration('P1D'); | |
* d.getHours(); // 3 | |
* e.getHours(); // 0 | |
*/ | |
getHours : function () { | |
return this._duration.hours(); | |
}, | |
/** | |
* This Duration instance expressed as hours. | |
* | |
* @method getAsHours | |
* @public | |
* | |
* @return {Number} This Duration instance in hours | |
* | |
* @example | |
* d = new Duration('P1DT3H'); e = new Duration('P1D'); | |
* d.getAsHours(); // 27 | |
* e.getAsHours(); // 24 | |
*/ | |
getAsHours : function () { | |
return this._duration.asHours(); | |
}, | |
/** | |
* The days in this Duration instance. | |
* | |
* @method getDays | |
* @public | |
* | |
* @return {Number} The days in this Duration instance | |
* | |
* @example | |
* d = new Duration('P1M 3D'); e = new Duration('P1M'); | |
* d.getDays(); // 3 | |
* e.getDays(); // 0 | |
*/ | |
getDays : function () { | |
return this._duration.days(); | |
}, | |
/** | |
* This Duration instance expressed as days. | |
* | |
* @method getAsDays | |
* @public | |
* | |
* @return {Number} This Duration instance as days | |
* | |
* @example | |
* d = new Duration('P1M 3D'); e = new Duration('P1M'); | |
* d.getAsDays(); // 33 | |
* e.getAsDays(); // 30 | |
*/ | |
getAsDays : function () { | |
return this._duration.asDays(); | |
}, | |
/** | |
* Returns the months in this Duration instance. | |
* | |
* @method getMonths | |
* @public | |
* | |
* @return {Number} The months of this Duration instance | |
* | |
* @example | |
* d = new Duration('P1Y 4M'); e = new Duration('P1Y'); | |
* d.getMonths(); // 4 | |
* e.getMonths(); // 0 | |
*/ | |
getMonths : function () { | |
return this._duration.months(); | |
}, | |
/** | |
* Returns this Duration instance expressed as months. | |
* | |
* @method getAsMonths | |
* @public | |
* | |
* @return {Number} This Duration instance in months | |
* | |
* @example | |
* d = new Duration('P1Y 4M'); e = new Duration('P1Y'); | |
* d.getAsMonths(); // 16 | |
* e.getAsMonths(); // 12 | |
*/ | |
getAsMonths : function () { | |
return this._duration.asMonths(); | |
}, | |
/** | |
* Returns the years of this Duration instance. | |
* | |
* @method getYears | |
* @public | |
* | |
* @return {Number} The years in this Duration instance | |
* | |
* @example | |
* d = new Duration('P3Y 3M'); e = new Duration('P10Y'); | |
* d.getYears(); // 3 | |
* e.getYears(); // 10 | |
*/ | |
getYears : function () { | |
return this._duration.years(); | |
}, | |
/** | |
* This Duration instance expressed as years. | |
* | |
* @method getAsYears | |
* @public | |
* | |
* @return {Number} This Duration instance in years | |
* | |
* @example | |
* d = new Duration('P3Y 3M'); e = new Duration('P10Y'); | |
* d.getAsYears(); // 3.25 | |
* e.getAsYears(); // 10 | |
*/ | |
getAsYears : function () { | |
return this._duration.asYears(); | |
} | |
}; | |
/** | |
* Runs the requested function while temporarily setting the Moment instance | |
* to UTC. This is not public, so there's no param shifting. If there are no | |
* opts, the callback still needs to be the third param. | |
* | |
* @method utcFilter | |
* @private | |
* | |
* @param {Moment} m The current Moment instance | |
* @param {Object} [opts] Options hash | |
* @param {Boolean} [opts.utc] Whether to run the provided function in utc mode | |
* @param {Function} callback The function to run on the given Moment instance | |
* | |
* @return {Mixed} The result of the callback function in the requested UTC or local mode | |
*/ | |
utcFilter = function (m, opts, callback) { | |
var ret = ''; | |
if (opts && opts.utc) { | |
m.utc(); | |
ret = callback(); | |
m.local(); | |
} else { | |
ret = callback(); | |
} | |
return ret; | |
}; | |
/** | |
* Changes the properties of a moment.js Duration object, to allow it to be | |
* mutated. | |
* | |
* @method mutateDuration | |
* @private | |
* | |
* @param {Duration} duration A Duration object to change the ms of | |
* @param {Number} newMs The new number for the Duration's ms | |
* | |
* @return {Duration} The provided duration, mutated to a new value | |
*/ | |
mutateDuration = function (duration, newMs) { | |
var | |
toSet = duration._duration._data, | |
tmpDuration = new Duration(newMs), | |
toGet = tmpDuration._duration; | |
duration._duration._milliseconds = newMs; | |
toSet.days = toGet.days(); | |
toSet.hours = toGet.hours(); | |
toSet.milliseconds = toGet.milliseconds(); | |
toSet.minutes = toGet.minutes(); | |
toSet.months = toGet.months(); | |
toSet.seconds = toGet.seconds(); | |
toSet.years = toGet.years(); | |
tmpDuration = null; | |
return duration; | |
}; | |
/** | |
* Returns a Duration, given either a Duration or something that can be used | |
* to construct a Duration | |
* | |
* @method makeDuration | |
* @private | |
* | |
* @param {Mixed} d Anything that can be used to make a Duration, or a Duration itself | |
* | |
* @return {Duration} A Duration instance | |
*/ | |
makeDuration = function (d) { | |
if (!d.getAsMilliseconds) { | |
d = new Duration(d); | |
} | |
return d; | |
}; | |
/** | |
* Returns a Moment, given either a Moment or something that can be used to | |
* construct a Moment. | |
* | |
* @method makeMoment | |
* @private | |
* | |
* @param {Mixed} m Anything that can be used to make a Moment, or a Moment itself | |
* | |
* @return {Moment} A Moment instance | |
*/ | |
makeMoment = function (m) { | |
if (!m.add) { | |
m = new Moment(m); | |
} | |
return m; | |
}; | |
/** | |
* Adds two durations, for now does not overload to create durations if the | |
* params are not Duration instances already. Commutative. | |
* | |
* @method addDurations | |
* @public | |
* | |
* @param {Duration|Mixed} left One Duration instance, or something that can construct a Duration | |
* @param {Duration|Mixed} right Another Duration instance, or something that can construct a Duration, to be added to the first | |
* | |
* @return {Duration} The sum of the params, as a new Duration | |
* | |
* @example | |
* addDurations(new Duration(1000), new Duration(3000)); // Duration representing 4s | |
* addDurations(new Duration(2000), new Duration(-3000)); // Duration representing -1s | |
* addDurations(1000, 4000); // Duration representing 5s | |
* addDurations(1000, new Duration(1000)); // Duration representing 2s | |
*/ | |
addDurations = function (left, right) { | |
left = makeDuration(left); | |
right = makeDuration(right); | |
var res = left.getAsMilliseconds() + right.getAsMilliseconds(); | |
return new Duration(res); | |
}; | |
/** | |
* Subtracts two durations, for now does not overload to create durations if | |
* the params are not Duration instances already. | |
* | |
* @method subtractDurations | |
* @public | |
* | |
* @param {Duration|Mixed} left One Duration instance, or something that can construct a Duration | |
* @param {Duration|Mixed} right Another Duration instance, or something that can construct a Duration, to be subtracted from the first | |
* | |
* @return {Duration} The result of subtraction on the params | |
* | |
* @example | |
* subtractDurations(new Duration(1000), new Duration(2000)); // Duration representing -1s | |
* subtractDurations(new Duration(3000), new Duration(1000)); // Duration representing 2s | |
* subtractDurations(1000, 2000); // Duration representing -1s | |
* subtractDurations(new Duration(3000), 1000); // Duration representing 2s | |
*/ | |
subtractDurations = function (left, right) { | |
left = makeDuration(left); | |
right = makeDuration(right); | |
var res = left.getAsMilliseconds() - right.getAsMilliseconds(); | |
return new Duration(res); | |
}; | |
/** | |
* Finds the absolute value difference between two Durations, | |
* a commutative operation. | |
* | |
* @method diffDurations | |
* @public | |
* | |
* @param {Duration|Mixed} first One Duration instance | |
* @param {Duration|Mixed} second Another duration instance | |
* | |
* @return {Duration} A new Duration representing the difference between the params | |
* | |
* @example | |
* diffDurations(new Duration(1000), new Duration(2000)); // Duration representing 1000ms | |
* diffDurations(new Duration(2000), new Duration(-4000)); // Duration representing 6000ms | |
* diffDurations('PT 2S', 'PT 4S'); // Duration representing 6000ms | |
* diffDurations(3000, 'PT 2S'); // Duration representing 1000ms | |
*/ | |
diffDurations = function (first, second) { | |
first = makeDuration(first); | |
second = makeDuration(second); | |
var res = first.getAsMilliseconds() - second.getAsMilliseconds(); | |
return new Duration(Math.abs(res)); | |
}; | |
/** | |
* Adds a Duration to a provided Moment object, returning a new Moment. | |
* Because of readability, it is preferable to use the constructors | |
* explicitly, but the overloading is provided for situations where a | |
* service response is providing something constructable; in this case | |
* it is hoped that the var with the server response is readable. | |
* | |
* @method addToMoment | |
* @public | |
* | |
* @param {Moment|Mixed} moment A Moment object to start from, or something that can construct a Moment | |
* @param {Duration|Mixed} duration A Duration object, or something that can construct a Duration, to add to the Moment | |
* | |
* @return {Moment} The resulting new Moment | |
* | |
* @example | |
* addToMoment(new Moment(), new Duration(1000)); // Moment one second in the future | |
* addToMoment(new Moment(), 1000); // Moment one second in the future | |
* // Try to avoid using constructable args, for readability, unless: | |
* addToMoment(expirationTime, 'PT 10M'); // assuming expirationTime is a Moment-parsable string, date, etc | |
*/ | |
addToMoment = function (moment, duration) { | |
moment = makeMoment(moment); | |
duration = makeDuration(duration); | |
var res = moment.clone(); | |
res._moment.add('ms', duration.getAsMilliseconds()); | |
return res; | |
}; | |
/** | |
* Subtracts a Duration from a provided Moment object, returning a new | |
* Moment. | |
* | |
* @method subtractFromMoment | |
* @public | |
* | |
* @param {Moment|Mixed} moment A Moment object to start from, or something that can construct a Moment | |
* @param {Duration|Mixed} duration A Duration object, or something that can construct a Duration, to subtract from the Moment | |
* @return {Moment} The resulting new Moment | |
* | |
* @example | |
* subtractFromMoment(new Moment(), new Duration(1000)); // Moment one second ago | |
* subtractFromMoment(new Moment(), 1000); // Moment one second in the past | |
* // Try to avoid using constructable args, for readability, unless: | |
* subtractFromMoment(expirationTime, 'PT 10M'); // assuming expirationTime is a Moment-parsable string, date, etc | |
*/ | |
subtractFromMoment = function (moment, duration) { | |
moment = makeMoment(moment); | |
duration = makeDuration(duration); | |
var res = moment.clone(); | |
res._moment.subtract('ms', duration.getAsMilliseconds()); | |
return res; | |
}; | |
/** | |
* Finds the Duration between two Moments. This is not commutative, since the | |
* diff will be positive or negative in terms of the first Moment. | |
* If the second moment is after the first, the diff will be negative. | |
* (18,19 === -1; 19,18 === 1) | |
* | |
* @method diffMoments | |
* @public | |
* | |
* @param {Moment|Mixed} first A Moment object to start from, or something that can construct a Moment | |
* @param {Moment|Mixed} second Another Moment object, or something that can construct a Moment, to find the diff from the first | |
* | |
* @return {Duration} The Duration diff between the two provided Moments | |
* | |
* @example | |
* diffMoments(new Moment(), new Moment()); // Duration of (probably) 0 | |
* diffMoments(momentYesterday, momentToday); // Duration of negative one day | |
* diffMoments(momentToday, momentYesterday); // Duration of one day | |
* diffMoments('2012-01-03', '2012-01-01'); // Duration of plus two days | |
* diffMoments('2012-01-01', '2012-01-03'); // Duration of minus two days | |
*/ | |
diffMoments = function (first, second) { | |
first = makeMoment(first); | |
second = makeMoment(second); | |
var res = first.clone()._moment.diff(second._moment, true); | |
return new Duration(res); | |
}; | |
return { | |
version : '$$PACKAGE_VERSION$$', | |
Moment : Moment, | |
Duration : Duration, | |
addDurations : addDurations, | |
subtractDurations : subtractDurations, | |
diffDurations : diffDurations, | |
addToMoment : addToMoment, | |
subtractFromMoment : subtractFromMoment, | |
diffMoments : diffMoments | |
}; | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment