relative-time
Version:
Formats JavaScript dates to relative time strings (e.g., "3 hours ago")
288 lines (233 loc) • 9.55 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var root = typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : {};
function getTemporal() {
var Temporal = root.Temporal;
if (!Temporal) {
throw new TypeError("Temporal is required to use relative-time");
}
return Temporal;
}
function defineCachedGetter(object, property, compute) {
Object.defineProperty(object, property, {
configurable: true,
enumerable: true,
get: function get() {
var value = compute();
Object.defineProperty(object, property, {
configurable: true,
enumerable: true,
value: value
});
return value;
}
});
}
function isTemporalZonedDateTime(value, Temporal) {
return Boolean(Temporal.ZonedDateTime && value instanceof Temporal.ZonedDateTime);
}
function isTemporalPlainDateTime(value, Temporal) {
return Boolean(Temporal.PlainDateTime && value instanceof Temporal.PlainDateTime);
}
function resolvePlainNow(now, Temporal, target) {
if (now === undefined || now === null) {
var current = Temporal.Now.plainDateTimeISO();
return typeof current.withCalendar === "function" && target.calendar ? current.withCalendar(target.calendar) : current;
}
if (!isTemporalPlainDateTime(now, Temporal)) {
throw new TypeError("Unsupported now value; expected Temporal.PlainDateTime");
}
return typeof now.withCalendar === "function" && target.calendar ? now.withCalendar(target.calendar) : now;
}
function resolveZonedNow(now, Temporal, targetZone) {
if (now === undefined || now === null) {
return Temporal.Now.zonedDateTimeISO(targetZone);
}
if (!isTemporalZonedDateTime(now, Temporal)) {
throw new TypeError("Unsupported now value; expected Temporal.ZonedDateTime");
}
if (now.timeZoneId !== targetZone) {
throw new TypeError("Unsupported now value; expected Temporal.ZonedDateTime in the same time zone as the target date");
}
return now;
}
function differenceInUnit(now, target, unit) {
if (unit === "year" || unit === "month") {
var startDate = typeof now.toPlainDate === "function" ? now.toPlainDate() : now;
var endDate = typeof target.toPlainDate === "function" ? target.toPlainDate() : target;
var yearDelta = endDate.year - startDate.year;
if (unit === "year") {
return yearDelta;
}
return yearDelta * 12 + (endDate.month - startDate.month);
}
if (unit === "day") {
var _startDate = typeof now.toPlainDate === "function" ? now.toPlainDate() : now;
var _endDate = typeof target.toPlainDate === "function" ? target.toPlainDate() : target;
var _duration = _startDate.until(_endDate, {
largestUnit: unit,
smallestUnit: unit,
roundingMode: "trunc"
});
return _duration.days;
}
if (unit === "hour") {
var _duration2 = now.until(target, {
largestUnit: unit,
smallestUnit: unit,
roundingMode: "trunc"
});
var hours = _duration2.hours;
if (hours === 0) {
var minutes = now.until(target, {
largestUnit: "minute",
smallestUnit: "minute",
roundingMode: "trunc"
});
if (minutes.minutes < 0) {
return -1;
}
}
return hours;
}
var duration = now.until(target, {
largestUnit: unit,
smallestUnit: unit,
roundingMode: "trunc"
});
return duration[unit + "s"];
}
var RelativeTimeResolver = exports.RelativeTimeResolver = function () {
function RelativeTimeResolver() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, RelativeTimeResolver);
this.Temporal = options.Temporal || this.constructor.Temporal;
this.threshold = options.threshold || this.constructor.threshold;
this.units = options.units || this.constructor.units;
}
_createClass(RelativeTimeResolver, [{
key: "resolve",
value: function resolve(date) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
now = _ref.now,
_ref$unit = _ref.unit,
unit = _ref$unit === undefined ? "best-fit" : _ref$unit;
var Temporal = this.Temporal || getTemporal();
var target = void 0;
var resolvedNow = void 0;
if (isTemporalZonedDateTime(date, Temporal)) {
var targetZone = date.timeZoneId;
target = date.withTimeZone(targetZone);
resolvedNow = resolveZonedNow(now, Temporal, targetZone);
} else if (isTemporalPlainDateTime(date, Temporal)) {
target = date;
resolvedNow = resolvePlainNow(now, Temporal, target);
} else {
throw new TypeError("Unsupported date value; expected Temporal.ZonedDateTime or Temporal.PlainDateTime");
}
var diff = Object.create(null);
var absDiff = Object.create(null);
var diffUnits = this.units;
diffUnits.forEach(function (currentUnit) {
defineCachedGetter(diff, currentUnit, function () {
return differenceInUnit(resolvedNow, target, currentUnit);
});
defineCachedGetter(absDiff, currentUnit, function () {
return Math.abs(diff[currentUnit]);
});
});
var resolvedUnit = unit === "best-fit" ? this.constructor.bestFit(absDiff, this.threshold) : unit;
return {
unit: resolvedUnit,
value: diff[resolvedUnit]
};
}
}], [{
key: "bestFit",
value: function bestFit(absDiff) {
var threshold = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.threshold;
switch (true) {
case absDiff.year > 0 && absDiff.month > threshold.month:
return "year";
case absDiff.month > 0 && absDiff.day > threshold.day:
return "month";
// case absDiff.month > 0 && absDiff.week > threshold.week: return "month";
// case absDiff.week > 0 && absDiff.day > threshold.day: return "week";
case absDiff.day > 0 && absDiff.hour > threshold.hour:
return "day";
case absDiff.hour > 0 && absDiff.minute > threshold.minute:
return "hour";
case absDiff.minute > 0 && absDiff.second > threshold.second:
return "minute";
default:
return "second";
}
}
}]);
return RelativeTimeResolver;
}();
RelativeTimeResolver.units = ["year", "month",
/* "week", */"day", "hour", "minute", "second"];
RelativeTimeResolver.threshold = {
month: 2,
// week: 4,
day: 6,
hour: 6,
minute: 59,
second: 59
};
var RelativeTime = function () {
function RelativeTime() {
_classCallCheck(this, RelativeTime);
this.formatters = RelativeTime.initializeFormatters.apply(RelativeTime, arguments);
this.resolver = new RelativeTimeResolver();
}
_createClass(RelativeTime, [{
key: "format",
value: function format(date) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var _options$unit = options.unit,
unit = _options$unit === undefined ? "best-fit" : _options$unit,
now = options.now;
var _resolver$resolve = this.resolver.resolve(date, {
unit: unit,
now: now
}),
resolvedUnit = _resolver$resolve.unit,
value = _resolver$resolve.value;
return this.formatters[resolvedUnit](value);
}
}]);
return RelativeTime;
}();
exports.default = RelativeTime;
RelativeTime.bestFit = RelativeTimeResolver.bestFit;
RelativeTime.threshold = RelativeTimeResolver.threshold;
RelativeTime.initializeFormatters = function (localesOrFormatter, options) {
var locales = localesOrFormatter;
var formatOptions = options;
if (localesOrFormatter && typeof localesOrFormatter.format === "function" && typeof localesOrFormatter.resolvedOptions === "function") {
return createFormatterMap(localesOrFormatter);
}
if (localesOrFormatter && (typeof localesOrFormatter === "undefined" ? "undefined" : _typeof(localesOrFormatter)) === "object" && !Array.isArray(localesOrFormatter)) {
formatOptions = localesOrFormatter;
locales = undefined;
}
return createFormatterMap(new Intl.RelativeTimeFormat(locales, Object.assign({
numeric: "auto"
}, formatOptions)));
};
function createFormatterMap(formatter) {
return ["second", "minute", "hour", "day",
/* "week", */"month", "year"].reduce(function (map, unit) {
map[unit] = function (value) {
return formatter.format(value, unit);
};
return map;
}, {});
}