UNPKG

relative-time

Version:

Formats JavaScript dates to relative time strings (e.g., "3 hours ago")

288 lines (233 loc) 9.55 kB
"use strict"; 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; }, {}); }