brainspan/Duration.js
/** @type {number} */
const SECONDS_PER_MINUTE = 60;
/** @type {number} */
const SECONDS_PER_HOUR = SECONDS_PER_MINUTE * 60;
/** @type {number} */
const SECONDS_PER_DAY = SECONDS_PER_HOUR * 24;
/** @type {number} */
const SECONDS_PER_WEEK = SECONDS_PER_DAY * 7;
/** @type {number} */
const SECONDS_PER_YEAR = SECONDS_PER_DAY * 365;
/** @type {number} */
const SECONDS_PER_MONTH = SECONDS_PER_YEAR / 12;
/**
* Inspired by Rails' ActiveSupport::Duration.
* Provides accurate date and time measurements.
* @example
* // Retuns a Date with the timestamp for a month before the current date and time.
* (1).month.ago
*/
class Duration {
/** @returns {Number} the number of seconds in a minute. */
static get SECONDS_PER_MINUTE() {
return SECONDS_PER_MINUTE;
}
/** @returns {Number} the number of seconds in an hour. */
static get SECONDS_PER_HOUR() {
return SECONDS_PER_HOUR;
}
/** @returns {Number} the number of seconds in a day. */
static get SECONDS_PER_DAY() {
return SECONDS_PER_DAY;
}
/** @returns {Number} the number of seconds in a week. */
static get SECONDS_PER_WEEK() {
return SECONDS_PER_WEEK;
}
/**
* @returns {Number} the number of seconds in a month.
* Note: for this purpose, a month is presumed to be 1/12th of a year.
* */
static get SECONDS_PER_MONTH() {
return SECONDS_PER_MONTH;
}
/**
* @returns {Number} the number of seconds in a month.
* Note: for this purpose, a year is presumed to be 365 days.
* */
static get SECONDS_PER_YEAR() {
return SECONDS_PER_YEAR;
}
/**
* @param {Number} seconds The number of seconds the Duration represents.
* @returns {Duration} An object representing a span of time.
*/
constructor(seconds) {
/** @type {number} The number of seconds the Duration represents. */
this.seconds = seconds;
}
/** @returns {Number} the number of millisends in this duration. */
get asMilliseconds() {
return this.seconds * 1000;
}
/** @returns {Number} the number of minutes in this duration. */
get asMinutes() {
return this.seconds / SECONDS_PER_MINUTE;
}
/** @returns {Number} the number of hours in this duration. */
get asHours() {
return this.seconds / SECONDS_PER_HOUR;
}
/** @returns {Number} the number of days in this duration. */
get asDays() {
return this.seconds / SECONDS_PER_DAY;
}
/** @returns {Number} the number of weeks in this duration. */
get asWeeks() {
return this.seconds / SECONDS_PER_WEEK;
}
/** @returns {Number} the number of months in this duration. */
get asMonths() {
return this.seconds / SECONDS_PER_MONTH;
}
/** @returns {Number} the number of years in this duration. */
get asYears() {
return this.seconds / SECONDS_PER_YEAR;
}
/**
* A Date in the future of the given Date, or new Date() if not supplied
* @param {Date} [date=new Date()]
* @returns {Date}
*/
since(date = new Date()) {
return new Date(date + this.asMilliseconds);
}
/**
* Alias of since
* @param {Date} [date=new Date()]
* @returns {Date}
*/
fromNow(date) {
return this.since(date);
}
/**
* Alias of since
* @param {Date} [date=new Date()]
* @returns {Date}
*/
after(date) {
return this.since(date);
}
/**
* A Date in the past of the given Date, or new Date() if not supplied
* @param {Date} [date=new Date()]
* @returns {Date}
*/
ago(date = new Date()) {
return new Date(date - this.asMilliseconds);
}
/**
* Alias of ago
* @param {Date} [date=new Date()]
* @returns {Date}
*/
until(date) {
return this.ago(date);
}
/**
* Alias of ago
* @param {Date} [date=new Date()]
* @returns {Date}
*/
before(date) {
return this.ago(date);
}
/**
* @returns {Number} The number of seconds represented by this Duration.
*/
valueOf() {
return this.seconds;
}
}
module.exports = Duration;