Create a gist now

Instantly share code, notes, and snippets.

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