daet
Version:
Minimal immutable date class that supports relative time, calendar time, and plus/minus of different units.
327 lines (326 loc) • 13.5 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Week = exports.Day = exports.Hour = exports.Minute = exports.Second = exports.Millisecond = void 0;
var memo_1 = __importDefault(require("@bevry/memo"));
var start_of_week_1 = __importDefault(require("start-of-week"));
var startOfWeek = (0, start_of_week_1.default)();
var intl = __importStar(require("./intl.js"));
exports.Millisecond = 1;
exports.Second = exports.Millisecond * 1000;
exports.Minute = exports.Second * 60;
exports.Hour = exports.Minute * 60;
exports.Day = exports.Hour * 24;
exports.Week = exports.Day * 7;
/** A minimal immutable date class that supports relative time, calendar time, and plus/minus of different units. */
var Daet = /** @class */ (function () {
/** Create a new daet instance based on the input */
function Daet(input) {
var _this = this;
/** Get the epoch time of this daet instance. */
this.getTime = (0, memo_1.default)(function () { return _this.raw.getTime(); });
/** Return a new daet instance that is the start of the week proceeding that of this daet instance. */
this.startOfNextWeek = (0, memo_1.default)(function () {
// continue until we become the start of next week
var latest = _this.plus(1, 'day');
while (latest.raw.getDay() !== startOfWeek) {
latest = latest.plus(1, 'day');
}
// reset the time, so we become the start time of that week
return latest.reset('hour');
});
/** Return a new daet instance that is the end of the week preceeding that of this daet instance. */
this.endOfLastWeek = (0, memo_1.default)(function () {
// continue until we become the start of this week
var latest = _this;
while (latest.raw.getDay() !== startOfWeek) {
latest = latest.minus(1, 'day');
}
// reset the time, then minus a second, so we become the end of the prior week
return latest.reset('hour').minus(1, 'second');
});
/** Return the ISO string for this daet instance. */
this.toISOString = (0, memo_1.default)(function () { return _this.raw.toISOString(); });
/** Return the JSON string for this daet instance. */
this.toJSON = (0, memo_1.default)(function () { return _this.raw.toJSON(); });
this.raw =
input instanceof Daet
? new Date(input.raw)
: input
? new Date(input)
: new Date();
this.raw.setMilliseconds(0);
}
Object.defineProperty(Daet, "tiers", {
/** The tiers used for human relative date display. */
get: function () {
return [
{
// right now
limit: exports.Second,
refresh: exports.Second,
message: intl.rightNow,
},
{
// x seconds
limit: exports.Minute,
refresh: exports.Second,
message: intl.relativeDelta,
},
{
// x minutes
limit: exports.Hour,
refresh: exports.Minute,
message: intl.relativeDelta,
},
{
// x hours x minutes
limit: 12 * exports.Hour,
refresh: exports.Minute,
message: intl.relativeDelta,
},
{
// later/earlier today
when: function (_a) {
var past = _a.past;
return past
? new Daet().reset('hour').getTime()
: new Daet().plus(1, 'day').reset('hour').getTime();
},
message: intl.earlierOrLaterToday,
},
{
// yesterday or tomorrow
when: function (_a) {
var past = _a.past;
return past
? new Daet().minus(1, 'day').reset('hour').getTime()
: new Daet().plus(2, 'day').reset('hour').getTime();
},
message: intl.yesterdayOrTommorow,
},
{
// this week
when: function (_a) {
var past = _a.past;
return past
? new Daet().endOfLastWeek().getTime()
: new Daet().startOfNextWeek().getTime();
},
message: intl.relativeThisWeek,
},
{
// next or last week
when: function (_a) {
var past = _a.past;
return past
? new Daet().endOfLastWeek().endOfLastWeek().getTime()
: new Daet().startOfNextWeek().startOfNextWeek().getTime();
},
message: intl.relativeSecondWeek,
},
{
// earlier or later
limit: Infinity,
message: intl.earlierOrLater,
},
];
},
enumerable: false,
configurable: true
});
/** Create a new daet instance based on the input */
Daet.create = function (input) {
return new this(input);
};
/** Return a new daet instance that is in the past by the value amount. */
Daet.prototype.minus = function (value, unit) {
return this.plus(value * -1, unit);
};
/** Return a new daet instance that is in the future by the value amount. */
Daet.prototype.plus = function (value, unit) {
switch (unit) {
case 'millisecond': {
var next = new Date(this.raw.getTime() + value);
return new Daet(next);
}
case 'second': {
return this.plus(value * exports.Second, 'millisecond');
}
case 'minute': {
return this.plus(value * exports.Minute, 'millisecond');
}
case 'hour': {
return this.plus(value * exports.Hour, 'millisecond');
}
case 'day': {
return this.plus(value * exports.Day, 'millisecond');
}
case 'week': {
return this.plus(value * exports.Week, 'millisecond');
}
default:
// https://basarat.gitbooks.io/typescript/docs/types/discriminated-unions.html
var neverCheck = unit;
throw new Error('unknown unit');
}
};
/** Clone this daet instance based on its raw value. */
Daet.prototype.rawClone = function () {
return new Date(this.raw);
};
/** Clone this daet instance. */
Daet.prototype.clone = function () {
return new Daet(this);
};
/** Return a new daet instance that has the unit set to the desired value. */
Daet.prototype.set = function (value, unit) {
switch (unit) {
case 'millisecond': {
var next = this.rawClone().setMilliseconds(value);
return new Daet(next);
}
case 'second': {
var next = this.rawClone().setSeconds(value);
return new Daet(next);
}
case 'minute': {
var next = this.rawClone().setMinutes(value);
return new Daet(next);
}
case 'hour': {
var next = this.rawClone().setHours(value);
return new Daet(next);
}
default:
// https://basarat.gitbooks.io/typescript/docs/types/discriminated-unions.html
var neverCheck = unit;
throw new Error('unknown unit');
}
};
/** Return a new daet instance that has the desired unit reset to 0. */
Daet.prototype.reset = function (unit) {
switch (unit) {
case 'millisecond': {
var next = this.rawClone().setMilliseconds(0);
return new Daet(next);
}
case 'second': {
var next = this.rawClone().setSeconds(0, 0);
return new Daet(next);
}
case 'minute': {
var next = this.rawClone().setMinutes(0, 0, 0);
return new Daet(next);
}
case 'hour': {
var next = this.rawClone().setHours(0, 0, 0, 0);
return new Daet(next);
}
default:
// https://basarat.gitbooks.io/typescript/docs/types/discriminated-unions.html
var neverCheck = unit;
throw new Error('unknown unit');
}
};
/** Get the milliseconds from the passed daet instance to this daet instance. */
Daet.prototype.getMillisecondsFrom = function (from) {
var now = from.getTime();
var time = this.getTime();
return time - now;
};
/** Get the milliseconds from now to this daet instance */
Daet.prototype.getMillisecondsFromNow = function () {
return this.getMillisecondsFrom(new Daet());
};
/** Use https://devdocs.io/javascript/global_objects/datetimeformat to format our daet instance. */
Daet.prototype.format = function (locale, options) {
return new Intl.DateTimeFormat(locale, options).format(this.raw);
};
/** Get the human absolute date display for this daet instance. */
Daet.prototype.calendar = function () {
return this.format('en', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
});
};
/** Return the human relative display from now, as well as the millisecond delta before a refresh is needed. */
Daet.prototype.fromNowDetails = function () {
var e_1, _a;
var now = new Daet();
var nowTime = now.getTime();
var eventTime = this.getTime();
var past = nowTime > eventTime;
var delta = Math.abs(eventTime - nowTime);
var tiers = Daet.tiers;
var lastTierDelta = 0;
try {
for (var tiers_1 = __values(tiers), tiers_1_1 = tiers_1.next(); !tiers_1_1.done; tiers_1_1 = tiers_1.next()) {
var tier = tiers_1_1.value;
var limit = tier.limit;
var when = tier.when ? tier.when({ past: past }) : 0;
var tierDelta = limit || Math.abs(when - nowTime);
if (delta < tierDelta) {
var message = tier.message({ past: past, delta: delta, when: this });
var refresh = tier.refresh || delta - lastTierDelta;
return { message: message, refresh: refresh };
}
lastTierDelta = tierDelta;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (tiers_1_1 && !tiers_1_1.done && (_a = tiers_1.return)) _a.call(tiers_1);
}
finally { if (e_1) throw e_1.error; }
}
throw new Error('no tier matched the input delta');
};
/** Return the human relative display from now. */
Daet.prototype.fromNow = function () {
return this.fromNowDetails().message;
};
return Daet;
}());
exports.default = Daet;