UNPKG

vague-time

Version:

A tiny library that formats precise time differences as a vague/fuzzy time.

179 lines (144 loc) 4.32 kB
/** * This module formats precise time differences as a vague/fuzzy * time, e.g. '3 weeks ago', 'just now' or 'in 2 hours'. */ /*globals define, module */ (function (globals) { 'use strict'; var times, functions; times = { year: 31557600000, // 1000 ms * 60 s * 60 m * 24 h * 365.25 d month: 2629800000, // 31557600000 ms / 12 m week: 604800000, // 1000 ms * 60 s * 60 m * 24 h * 7 d day: 86400000, // 1000 ms * 60 s * 60 m * 24 h hour: 3600000, // 1000 ms * 60 s * 60 m minute: 60000 // 1000 ms * 60 s }; functions = { get: getVagueTime }; exportFunctions(); /** * Public function `get`. * * Returns a vague time, such as '3 weeks ago', 'just now' or 'in 2 hours'. * * @option from The origin time. Defaults to `Date.now()`. * @option to The target time. Defaults to `Date.now()`. * @option units If `from` or `to` are timestamps rather than date * instances, this indicates the units that they are * measured in. Can be either `ms` for milliseconds * or `s` for seconds. Defaults to `ms`. * @option raw Return translation-friendly raw data in the format * `{ v: value, u: units }`. */ function getVagueTime (options) { var now, units, diff, action, key, numericalValue, value, threshold, plural; now = Date.now(); units = normaliseUnits(options.units); diff = normaliseTime(options.from, units, now) - normaliseTime(options.to, units, now); plural = 's'; if (diff >= 0) { action = past; } else { diff = -diff; action = future; } for (key in times) { if (times.hasOwnProperty(key)) { value = times[key]; threshold = value / 4; if (diff < threshold) { continue; } if (diff < value - threshold) { if (key !== 'hour') { continue; } value = 'half ' + singleValue(key); numericalValue = 0.5; plural = ''; } else { value = numericalValue = Math.round(diff / value); switch (value) { case 1: value = singleValue(key); plural = ''; break; case 2: value = 'a couple of'; } } if (options.raw) { return translationFriendlyResult(action, numericalValue, key); } return action(value, key + plural); } } if (options.raw) { return translationFriendlyResult(action, 0, null); } return action.f; } function normaliseUnits (units) { if (typeof units === 'undefined') { return 'ms'; } if (units === 's' || units === 'ms') { return units; } fail('units'); } function fail (reason) { throw new Error('Invalid ' + reason); } function normaliseTime(time, units, defaultTime) { if (typeof time === 'undefined') { return defaultTime; } if (typeof time === 'string') { time = parseInt(time, 10); } if (isNotDate(time) && isNotTimestamp(time)) { fail('time'); } if (typeof time === 'number' && units === 's') { time *= 1000; } return time; } function isNotDate (date) { return Object.prototype.toString.call(date) !== '[object Date]' || isNaN(date.getTime()); } function isNotTimestamp (timestamp) { return typeof timestamp !== 'number' || isNaN(timestamp); } function past (value, units) { return value + ' ' + units + ' ago'; } past.f = 'just now'; function future (value, units) { return 'in ' + value + ' ' + units; } future.f = 'soon'; function singleValue (time) { return time === 'hour' ? 'an' : 'a'; } function translationFriendlyResult (action, numericalValue, unit) { return { v: action === past ? -numericalValue : numericalValue, u: unit }; } function exportFunctions () { if (typeof define === 'function' && define.amd) { define('vagueTime', ['exports'], function(exports) { exports.get = functions.get; }); } else if (typeof module !== 'undefined' && module && module.exports) { module.exports = functions; } else { globals.vagueTime = functions; } } }(this));