src/index.js
'use strict'
const defaultIncrementNames = {
'd': ['d', 'd'],
'h': ['h', 'h'],
'm': ['m', 'm'],
's': ['s', 's'],
'ms': ['ms', 'ms'],
'µs': ['µs', 'µs'],
}
/**
* @module formatmicro
*/
/**
* Formats microseconds into strings that look like: 1 d 3 h 7 m 28 s 500 ms 324 µs
*
* @param {number} timeMicro
* @param {object|function|undefined} incrementNames
* @returns {string}
* @throws {Error} If either argument isn't the correct type
*/
const formatmicro = (timeMicro, incrementNames) => {
if(Number(parseFloat(timeMicro)) !== timeMicro) throw new Error("First parameter must be a number.")
if(incrementNames && (typeof incrementNames !== "function") && (typeof incrementNames !== "object")) throw new Error("Second parameter, if provided, must be a function or an object")
let formatReduce
if(incrementNames && typeof incrementNames === "function") {
formatReduce = incrementNames
}
else {
incrementNames = {
...defaultIncrementNames,
...incrementNames,
}
formatReduce = (carry, incrementKey, value) => {
if(value === 0) return carry
else return carry +
((carry === "") ? "" : " ") +
value.toString() + " " +
((value === 1) ? incrementNames[incrementKey][0] : incrementNames[incrementKey][1])
}
}
const increments = {'d' : 8.64e10, 'h' : 3.6e9, 'm' : 6e7, 's' : 1e6, 'ms' : 1000, 'µs' : 1 }
// how much of each increment step makes up our time
const parts = Object.keys(increments).reduce((carry, key) => {
const incValue = Math.floor(carry.microLeft / increments[key])
const microValue = incValue * increments[key]
return {
...carry,
[key]: incValue,
microLeft: carry.microLeft - microValue,
}
}, {microLeft: timeMicro})
// format the final result
return Object.keys(parts).reduce((carry, key) => {
if(!increments.hasOwnProperty(key)) return carry
else return formatReduce(carry, key, parts[key])
}, "")
}
/**
* Formats microseconds into strings that look like: 1 day 3 hours 7 minutes 28 seconds 500 milliseconds 324 microseconds
*
* @param {number} timeMicro
* @param {object|function|undefined} incrementNames
* @returns {string}
* @throws {Error} If either argument isn't the correct type
*/
const bignames = (timeMicro, incrementNames) => {
if(!incrementNames || (typeof incrementNames === "object")) {
incrementNames = {
'd' : ['day', 'days'],
'h' : ['hour', 'hours'],
'm' : ['minute', 'minutes'],
's' : ['second', 'seconds'],
'ms' : ['millisecond', 'milliseconds'],
'µs' : ['microsecond', 'microseconds'],
...incrementNames,
}
}
return formatmicro(timeMicro, incrementNames)
}
/**
* Same as {@link formatmicro}, except it only returns the first two non-zero values.
*
* @param {number} timeMicro
* @param {object|function|undefined} incrementNames
* @returns {string}
* @throws {Error} If either argument isn't the correct type
*/
const onlytwo = (timeMicro, incrementNames) => {
if(!incrementNames || (typeof incrementNames === "object")) {
incrementNames = {
...defaultIncrementNames,
...incrementNames,
}
}
else if(typeof incrementNames === "function") {
return formatmicro(timeMicro, incrementNames)
}
let foundNum = 0
const takeFor = 2
const formatReduce = (carry, incrementKey, value) => {
if(foundNum >= takeFor) return carry
if(value === 0) return carry
foundNum++
return carry +
((carry === "") ? "" : " ") +
value.toString() + " " +
((value === 1) ? incrementNames[incrementKey][0] : incrementNames[incrementKey][1])
}
return formatmicro(timeMicro, formatReduce)
}
export {
formatmicro as default,
formatmicro,
bignames,
onlytwo,
}