js的一些function

/**
* * 根据秒数返回 一个日期范围
* timerFilter(10)
*/
function timerFilter(n) {
  let days = 31; // 一月多少天
  const oneM = 60; // 一分钟s
  const halfAnHour = oneM * 30; // 半小时s
  const oneHour = oneM * 60 * 1; // 一小时s
  const oneDay = oneHour * 24; // 一天s
  const oneMonth = oneDay * days; // 一个月s
  const oneYearAllDay = 365;
  const oneYearAllS = oneYearAllDay * oneDay;

  if (n < oneM) {
    return `${n}秒前`;
  } else if (n >= oneM && n < halfAnHour) {
    return `${Math.floor(n / oneM)}分钟前`;
  } else if (n >= halfAnHour && n < oneHour) {
    return `半小时前`;
  } else if (n >= oneHour && n < oneDay) {
    return `${Math.floor(n / oneHour)}小时前`;
  } else if (n >= oneDay && n < oneMonth) {
    return `${Math.floor(n / oneDay)}天前`;
  } else if (n >= oneMonth && n < oneYearAllS) {
    return `${Math.floor(n / oneMonth)}月前`;
  } else if (n >= oneYearAllS) {
    return `${Math.floor(n / oneYearAllS)}年前`;
  }
}


/**
* * x年 12个月,每月有几天
* month12Day(): [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
*/
function month12Day(year) {
  if (!year) {
    const date = new Date();
    year = date.getFullYear();
  }
  const months = [];
  for (let i = 0; i < 12; i++) {
    const index = i + 1;
    let date2 = new Date(year, index, 0);
    let days = date2.getDate();
    months.push(days);
  }
  return months;
}

/**
  * * x年x月 有多少天,默认本年本月
  * monthAllDay('2019', 2) // 28
  */
function monthAllDay(year, month) {
  if (!year || !month) {
    const date = new Date();
    year = date.getFullYear();
    month = date.getMonth() + 1;
  }
  const date2 = new Date(year, month, 0);
  const days = date2.getDate(); // 本月有多少天
  return days;
}

/**
 * 判断所有角的终边是否相等
 * @param {*} angles
 * finalSide([30, 390, 750]) -> true
 */
function finalSide(angles) {
  angles = angles.map(angle => {
    if (angle > 360) {
      return angle - Math.floor(angle / 360) * 360;
    } else {
      return angle;
    }
  });
  return !angles.some(angle => angle !== angles[0]);
}


/**
 * 判断一个角的终边处于在第几象限角
 * @param {*} angle 角度
 * quadrant(-180)
 */
function quadrant(angle) {
  // 是否为负的角
  const quadrantNum = 4; // 只有4个象限
  const quadrantItem = 90; // 每个象限为90度
  let isNegative = false;

  if (angle < 0) {
    isNegative = true;
    angle = Math.abs(angle);
  }
  // 不属于任何现象角
  if (angle % quadrantItem === 0) return null;
  const x = Math.ceil(angle / quadrantItem);
  return isNegative ? quadrantNum - x + 1 : x;
}


/**
 * 杨辉三角
 * @param {*} lines 行数
 * https://zh.wikipedia.org/wiki/%E6%9D%A8%E8%BE%89%E4%B8%89%E8%A7%92%E5%BD%A2
 * https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/pascal-triangle
 * ShowYangHuiTriangle(10);
 */
function ShowYangHuiTriangle(lines) {
  let str = ``;
  let nums = [];

  for (let i = 0; i < lines; i++) {
    //补空白
    for (let j = 0; j < lines - i; j++) {
      str += " ";
    }

    for (let j = 0; j < i + 1; j++) {
      let length = nums.length;
      let value;
      if (j === 0 || j === i) {
        value = 1; // 左右为1
      } else {
        value = nums[length - i] + nums[length - i - 1];
      }
      nums.push(value);
      str += ` ${value} `;
    }

    str += "
";
  }

  l(str);
}


// 检查一个正整数是否为 2 的幂
// https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/is-power-of-two
function is2Power(number) {
  return (number & (number - 1)) === 0 ? true : false;
}


// 阶乘
// 5! = 5 * 4 * 3 * 2 * 1 = 120
// https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/math/factorial/README.zh-CN.md
function factorial(number) {
  let r = 1,
    i;
  for (i = number; i > 0; i--) {
    r *= i;
  }
  return r;
}

// 最小公倍数
// lcm(a, b) = |a * b| / gcd(a, b)
// https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/least-common-multiple
function lcm(numbers = []) {
  numbers = numbers.map(n => Math.abs(n));
  return numbers.reduce((acc, el) => el * acc, 1) / gcd(numbers);
}

// 求公约数
// https://baike.baidu.com/item/%E6%9C%80%E5%A4%A7%E5%85%AC%E7%BA%A6%E6%95%B0
// https://en.wikipedia.org/w/index.php?title=Euclidean_algorithm&gettingStartedReturn=true
// https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm
function gcd(numbers) {
  const [resNumbers, n] = a(numbers);

  const x = b(resNumbers);
  // 第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数
  if (n === 0) {
    return x;
  } else {
    return x * 2 ** n;
  }

  /**
   *
   * @param {*} numbers
   * @param {*} n 整除了几次
   */
  function a(numbers, n = 0) {
    const len = numbers.length;
    let isAllEven = true; // 是否都是偶数
    let i = 0;
    for (i = 0; i < len; i++) {
      if (numbers[i] % 2 !== 0) {
        isAllEven = false;
        break;
      }
    }
    if (isAllEven) {
      // 都是偶数, 则用2约简
      const newNumbers = numbers.map(n => n / 2);
      return a(newNumbers, n + 1);
    } else {
      return [numbers, n];
    }
  }

  function b(numbers) {
    // 以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
    const maxNumber = Math.max(...numbers);
    const minNumber = Math.min(...numbers);

    const x = maxNumber - minNumber;

    // l(x);

    if (x === minNumber) {
      return x;
    } else {
      return b([minNumber, x]);
    }
  }
}


// flattenDeep(arr, 2)  https://www.css88.com/doc/lodash/#_flattendeptharray-depth1
function flattenDeep(arr, depath = -2, res = []) {
  for (let el of arr) {
    const isArr = el.constructor === Array;
    if ((isArr && depath >= 1) || (depath === -2 && isArr)) {
      flattenDeep(el, Math.max(depath - 1, -2), res);
    } else {
      res.push(el);
    }
  }
  return res;
}


// Docs: http://www.css88.com/doc/lodash/#_throttlefunc-wait0-options
function throttle(fn, rate = 1000) {
  let lastClick = Date.now() - rate;
  return function(...args) {
    if (Date.now() - lastClick >= rate) {
      fn(...args);
      lastClick = Date.now();
    }
  };
}


// 将数字从一个范围重新映射到另一个范围
// Docs: https://p5js.org/reference/#/p5/map
// Docs: https://github.com/processing/p5.js/blob/master/src/math/calculation.js
function our_map(v, start1, stop1, start2, stop2) {
  return (v - start1) / (stop1 - start1) * (stop2 - start2) + start2;
}

// 和下面的chunk 一样
function chunk2(arr, n) {
    let len = arr.length;
    return new Array(Math.ceil(len / n))
        .fill()
        .reduce((acc, el, index, target) => {
            var start = index * n,
                end = Math.min(start + n, len);
            acc.push([])
            for (let i = start; i < end; i++) {
                acc[index].push(arr[i]);
            }
            return acc;
        }, [])
}


// chunk([1, 2, 3], 2) -> [[1, 2], [3]]
function chunk(arr, n) {
    let res = [];
    arr = arr.slice()
    let len = arr.length;
    let from = Math.ceil(len / n)
    for (let i = 0; i < from; i++) {
        let a = []
        for (let j = 0; j < n; j++) {
            let v = arr.shift();
            if (v !== undefined) a.push(v);
        }
        res.push(a)
    }
    return res;
}


// 'click-value-x-Z' -> camelHD -> clickValueXZ
function camelHD(str) {
    let a = str.split(/-/)
    let len = a.length;
    for (let i = 1; i < len; i++) {
        let c = a[i].codePointAt(0);
        if (c >= 65 && c <= 90) continue; // A ~ Z
        let obj = a[i]
        a[i] = obj.replace(/^[a-z]{0,1}/, obj[0].toUpperCase())
    }
    return a.join('')
}


// 打乱集合里面的元素位置
function shuffle(arr) {
    const random = (a, b) => Math.floor(Math.random() * (b - a + 1) + a);
    return arr.slice().reduce((acc, item, index, target) => {
        const objIndex = random(0, index);
        target.splice(index, 1, target[objIndex]);
        target.splice(objIndex, 1, item);
        return target;
    });
}

// 返回 start - end数字之间的素数。
function getPrime(start, end) {
    const res = [];
    for (let i = start; i <= end; i++) {
        if (primenp(i)) res.push(i);
    }
    return res;
}

// 判断一个数字是否为 素数
// 指在大于1的自然数中,除了1和该数自身外,无法被其他自然数整除的数
// https://zh.wikipedia.org/wiki/%E7%B4%A0%E6%95%B0
function primenp(n) {
  if (n <= 1) return false;
  for (let i = 2; i < n; i++) {
    if (n % i === 0) return false;
  }
  return true;
}

function random(a, b) {
    // 0 * n = 0; +a是为了保证最小值 
    return Math.floor((Math.random() * (b - a + 1)) + a);
}


// 默认返回32位随机字符串
function randomString32(len) {
    const loopn = len || 32;
    const c = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
    const c_len = c.length;

    let res = '';
    for (let i = 0; i < loopn; i++) {
        res += c.charAt(random(0, c_len - 1));
    }
    return res;
}


// node 返回MD5加密后的字符串
function MD5(data) {
    const md5 = crypto.createHash('md5', 'utf8').update(data).digest('hex');
    return md5;
}


// { name: 'ajanuw', age: [12, 14] } -> jsonToSerialize -> name=ajanuw&age=12&age=14
function jsonToSerialize(o) {
    let s = '';
    for (let k in o) {
        let v = o[k];
        let vTag = Object.prototype.toString.call(v);
        if (vTag === '[object Array]') {
            for (let i of v) {
                s += `${k}=${encodeURIComponent(i)}&`
            }
        } else if (vTag === '[object Object]') {
            s += `${k}=${encodeURIComponent(JSON.stringify(v))}&`
        } else {
            s += `${k}=${encodeURIComponent(v)}&`
        }
    }
    return s.replace(/&$/, '');
}


function charCode(string) {
    // char-code 返回与字符相关的数字
    return string.codePointAt(0);
}

function codeChar(number) {
    // code-char 返回与数字相关的字符
    return String.fromCodePoint(number);
}

function bubbleSort(arr, is = '<') {
    // 网上找的排序,带破坏性
    var len = arr.length;
    for (var i = 0; i < len; i++) {
        for (var j = 0; j < len - 1 - i; j++) {
            if (is === '<') {
                if (arr[j] > arr[j + 1]) { //相邻元素两两对比
                    var temp = arr[j + 1]; //元素交换
                    arr[j + 1] = arr[j];
                    arr[j] = temp;
                }
            } else {
                if (arr[j] < arr[j + 1]) { //相邻元素两两对比
                    var temp = arr[j + 1]; //元素交换
                    arr[j + 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }
    return arr;
}


// 指出相等元素出现的次数
// occ(['a', 'b', 'a', 'd', 'a', 'c', 'd', 'c', 'a']) // [["a", 4],["d", 2],["c", 2],["b", 1]]
function occ(lst) {
    let res = [];
    let n = 0;

    // 数组去重
    let lsta = (function (array) {
        let n = [];
        for (let i = 0; i < array.length; i++) {
            if (n.indexOf(array[i]) === -1) n.push(array[i]);
        }
        return n;
    })(lst);

    for (let i = 0; i < lsta.length; i++) {
        const key = lsta[i];
        for (let j = 0; j < lst.length; j++) {
            if (lst[j] === key) {
                n += 1;
            }
        }
        res.push([key, n]);
        n = 0;
    }

    return res.sort((a, b) => {
        return a[1] < b[1]
    });
}

// 如果其中一个参数为真,立即返回当前元素, some直接返回true
// or(false,1,false) // 1
function or() {
    const props = ([]).slice.call(arguments);
    for (let el of props) {
        if (el || el === 0) { // js会把0转化成false
            return el
        };
    }
    return false;
}

function and() {
    const props = ([]).slice.call(arguments);
    for (let el of props) {
        if (!el && el !== 0)  return false;
    }
    return props.pop();
}


function ourSplit(dataStr, splitData, addStr) {
    /**
     * 这个函数更 split很想,但是有三个参数
     * 在分割的时候同时 在前或在后 添加第三个参数
     * 
     * console.log( ourSplit('1-2--34-5--6--', '--', '?hello') );
     * console.log( ourSplit('1-2-----3', '-', '?xx') );
     */
    if (splitData.constructor !== String) {
        // 分割失败返回 false
        return false;
    }

    if (!addStr) {
        // 不存在第三个参数,就更split一样
        return dataStr.split(splitData);
    }

    if (addStr.constructor !== String) {
        // 分割失败返回 false
        return false;
    }

    const dataStrLength = dataStr.length; //分割字符串的长度
    const isGetPlaceholder = addStr.charAt(0) === '?';
    const a1 = []; // splitData 存在的坐标

    if (isGetPlaceholder) {
        for (let i = 0; i < dataStrLength; i++) {
            if (dataStr.substr(i, splitData.length) === splitData) {
                a1.push(i);
            }
        }

        const addStrData = addStr.slice(1); // 需要添加的数据
        const res = []; // 分割后的 数据
        let start = 0;
        for (let i = 0; i < a1.length + 1; i++) {
            res.push(
                i < a1.length ?
                dataStr.substring(start, a1[i]) + addStrData :
                dataStr.substring(start, a1[i])
            );
            start = a1[i] + splitData.length
        }
        return res;
    }
}


// 这个函数用来用多个函数来处理 一个参数
// function mu(n) { return n ** 2 }
// apllyfunc(3, [mu, [Number.prototype.toFixed, 2]]) // 9.00
function apllyfunc(target, f = []) {
    if (f.constructor !== Array) {
        throw Error(`${f.name}:应该是'Array', 而不是'${f.constructor.name}'`);
    }
    if (f.length === 0) {
        return target;
    }
    let res = target;
    const checkFunction = fn => fn.constructor === Function ? '' : console.error(`${fn}:不是'Function'.`);
    let fn;
    f.reduce((accumulator, el) => {
        if (el.constructor === Array) {
            fn = el[0];
            checkFunction(fn);
            return res = fn.call(res, el[1])
        } else {
            fn = el;
            checkFunction(fn);
            return res = fn(res);
        }
    }, res);
    return res;
}


// 回文有偶数个元素,那么后半段会是前半段的镜射 
// mirror([1,2,2,1])
function mirror(lst) {
    const len = lst.length;
    if (len % 2 !== 0) return false;

    let mid = len / 2;
    const a = lst.slice(0, mid);
    const b = lst.slice(mid).reverse();
    let res = true;
    while (res && mid > 0) {
        res = a[mid - 1] == b[mid - 1];
        mid--;
    }
    return res;
}


function complement(s, a) {
    /*
     * 补集 (complement) 递归版
     * S是一个集合,A是S的一个子集,由S中所有不属于A的元素组成的集合,叫做子集A在S中的绝对补集
     * console.log(
     *   complement([1, 2, 3, 1, 2], [2, 3])
     * );
     */
    if (s.constructor !== Array && a.constructor !== Array) return false;

    if (s.length === 0) return [];

    const obj = s[0];
    const check = a.indexOf(obj) < 0; // S中所有不属于A的元素

    return check ? [obj, ...complement(s.slice(1), a)] : [...complement(s.slice(1), a)]
}

function complement(s, a) {
    /*
     * 补集 (complement)
     * S是一个集合,A是S的一个子集,
     * 由S中所有不属于A的元素组成的集合,叫做子集A在S中的绝对补集
     * console.log(complement([1, 2, 3, 1, 2], [2, 3]));
     * [1, 1]
     */
    if (s.constructor === Array && a.constructor === Array) {
        const com = s.filter(el => a.indexOf(el) < 0); // S中所有不属于A的元素
        return com.length > 0 ? com : false;
    }
    return false;
}

function intersection(lstA, lstB) {
    /*
     * 交集 (intersection)  递归版
     * A,B是两个集合,由所有属于集合A且属于集合B的元素所组成的集合
     * console.log(
     *   intersection([1,2,3,4,2], [2,3,5])
     * );
     */
    if (lstA.constructor !== Array && lstB.constructor !== Array) return false;

    if (lstA.length === 0) return [];

    const value = lstA[0];
    const check = lstB.indexOf(value) >= 0; // 相交

    return check ? [lstA[0], ...intersection(lstA.slice(1), lstB)] : [...intersection(lstA.slice(1), lstB)]
}


function intersection(lstA, lstB) {
    /*
     * 交集 (intersection)
     * A,B是两个集合,由所有属于集合A且属于集合B的元素所组成的集合
     * console.log(intersection([1, 2, 3, 4, 2], [2, 3, 5]));
     * [2, 3, 2]
     */
    return (lstA.constructor === Array && lstB.constructor === Array) ?
        lstA.filter(el => lstB.indexOf(el) >= 0) :
        false;
}


function union(lstA, lstB) {
    /*
     * 并集 (union)
     * 若A和B是集合,则A和B并集是有所有A的元素和所有B的元素,而没有其他元素的集合。
     * console.log(union([1, 2], [2, 3]));
     * [1, 2, 3]
     */
    return (lstA.constructor === Array && lstB.constructor === Array) ?
        ([...lstA, ...lstB]).reduce((acc, el) => [...acc, acc.indexOf(el) < 0 ? el : ''], []).filter(el => el !== '') :
        false;
}


// 遍历树, 更改修改值
// arr = [1, 2, "y", ['y', 'a', ['z','z','y']]]
// subtr('p', 'y', arr)
function subtr(newV, oldV, tree) {
    if (oldV === tree) {
        return newV;
    }

    if ((tree).constructor !== Array || tree.length === 0) {
        return tree;
    }
    return [
        subtr(newV, oldV, tree[0]),
        ...subtr(newV, oldV, tree.slice(1)),
    ];
}


// 拷贝数组
// copyTree([1,2, ['a', 'b'], 6, 9, {}])
function copyTree(tr) {
    if (tr.constructor !== Array || tr.length === 0) {
        return tr;
    }
    return [
        copyTree(tr[0]),
        ...copyTree(tr.slice(1))
    ]
}


// mapList([1, 2, 3, "a", "b"], lst => lst.slice(2)) // [ [ 1, 2, 3, 'a', 'b' ], [ 'a', 'b' ] ]
function mapList(lst, next) {
  if (lst.length === 0 || lst.constructor !== Array) return;

  let arr = [];
  let a = list => {
    if (list.length === 0 || list.constructor !== Array) return [];

    arr.push(list);
    return a(next(list.slice(1)));
  };
  a(lst.slice());
  return arr;
}


// ourSort([1,2,3,6,-1], '<')
function ourSort(lst, n) {
    let newlst = lst.slice();
    if (n && n === '>') {
        // 从大到小
        return newlst.sort((a, b) => a < b);
    } else if (n && n === '<') {
        // 从小到大
        return newlst.sort((a, b) => a > b);
    }
}


function AVector(x = 0, y = 0, z = 0) {
    // 模拟 p5.js 的 p5.p5.Vector 对象
    this.x = x;
    this.y = y;
    this.z = z;
    this.test = 'ajanuw';

    this.add = function (v) { // 相加
        if (v) {
            this.x += v.x;
            this.y += v.y;
            this.z += v.z;
        }
    }

    this.sub = function (v) { // 相减
        if (v) {
            this.x -= v.x;
            this.y -= v.y;
            this.z -= v.z;
        }
    }

    this.mult = function (n) { // 乘以标量以延伸向量
        if (n) {
            this.x *= n;
            this.y *= n;
        }
    }

    this.div = function (n) { // 除以标量以缩短向量
        if (n) {
            this.x /= n;
            this.y /= n;
        }
    }

    this.mag = function () { // 计算向量长度,勾股定理
        return Math.sqrt(this.x * this.x + this.y * this.y)
    }

    this.setMag = function (v) { // 设置向量的长度

    }

    this.normalize = function () { // 单位化向量,使其长度为1
        var m = this.mag();
        if (m !== 0) {
            this.div(m);
        }
    }

    this.limit = function (max) { // 限制向量的长度
    }

    this.constructor = function () {
        return {
            x: this.x,
            y: this.y,
            z: this.z,
        }
    }

    this.constructor();
}


function fangen(target, n) {
    /**
     * 求方根
     * Math.pow(2,3)
     * 2**3
     */
    // fangen(10, 2) // 100
    if (n == 0) {
        return target;
    }

    function abc(intertarget, n) {
        if (n == 0) {
            return intertarget;
        }
        return abc(intertarget * target, n - 1)
    }
    return abc(target, n - 1)
}

function average(a = []) {
    // 求平均值
    // average([1, 2, 3]) // 2
    var i = 0,
        len = a.length,
        all = 0;
    while (i < len) {
        all += a[i];
        i++
    }
    return all / len;
}

function variance(a = []) {
    // 求方差和
    // 方差 = 每个元素减去平均值的平方根 ( a[i] - average(a) )^2
    // 方差和 = (+ fangen( a[i] - average(a), 2))
    var len = a.length,
        all = 0,
        avg = average(a);
    for (let i = 0; i < len; i++) {
        all += fangen(a[i] - avg, 2);
    }
    return all;
}

function gaussian(a = []) {
    // 求标准差
    // 标准差 = 方差和,在平均后,在方根
    // Math.sqrt( variance(a) / a.len)
    // gaussian([85, 82, 88, 86, 85, 93, 98, 40, 73, 83]) // 15.126466871017833
    return Math.sqrt(variance(a) / a.length);
}


// 控制台打印颜色 [yarn add chalk]
// console.log( logger("hello", {string: 'red'}) );
// console.log( logger(123, 'red') );
function logger(target, obj = {}) {
    var inspect = util.inspect;
    if (typeof obj === 'object') {
        Object.assign(inspect.styles, obj);
    } else {
        Object.assign(inspect.styles, {
            [typeof target]: obj
        });
    }
    return inspect(target, {
        colors: true
    }).replace(/'/g, '');
}


// _slice('a..t')
// _slice('b..z')
function _slice(str) {
    if (str.constructor.name !== 'String') return !!0;

    var start,
        end,
        cStart,
        cEnd,
        arr = [];

    start = str.charAt(0);
    end = str.charAt(str.length - 1);

    if (start < end) {
        cStart = start.codePointAt(0);
        cEnd = end.codePointAt(0);

        for (let i = cStart; i <= cEnd; i++) {
            arr.push(String.fromCodePoint(i));
        }
    } else {
        cEnd = start.codePointAt(0);
        cStart = end.codePointAt(0);

        for (let i = cEnd; i >= cStart; i--) {
            arr.push(String.fromCodePoint(i));
        }
    }
    return arr;
}

//返回对象的prop []
function keys(obj, isOwn = false) {
    var a = [];
    if (isOwn) {
        return Reflect.ownKeys(obj);
    } else {
        for (let i in obj)
            a.push(i);
    }
    return a;
}


//返回对象的value[]
function values(obj, isOwn = false) {
    var a = [];
    if (isOwn) {
        let i, al = Reflect.ownKeys(obj);
        for (i in al) a.push(obj[al[i]]);
    } else {
        for (let i in obj) a.push(obj[i]);
    }
    return a;
}


function _date(s) {
    // _date('w') 星期二
    var odate;
    if (s.constructor === Array) { // 返回指定时间
        if (s.length === 1) {
            return new Date(s[0]).getTime(); // 返回时间搓
        } else {
            odate = new Date(s[0])
            return nowT(s[1]); // 返回指定参数
        }
    }

    odate = new Date()
    return nowT(s);

    function nowT(ti) {
        // 返回当前时间
        switch (ti) {
            case 'y':
                return odate.getFullYear(); // 年
                break;
            case 'm':
                return odate.getMonth() + 1; // 月
                break;
            case 'd':
                return odate.getDate(); // 日
                break;
            case 'h':
                return odate.getHours(); // 小时
                break;
            case 'n':
                return odate.getMinutes(); // 分钟
                break;
            case 's':
                return odate.getSeconds(); // 秒
                break;
            case 'w':
                return odate.getDay(); // 星期
                break;
            case 'ms':
                return odate.getMilliseconds(); // 毫秒
                break;
            case 'prc':
                return odate.toLocaleString() // 本地时间格式
                break;
            default:
                return Date.now(); // 时间搓
        }
    }
}

// 递归创建文件夹
// [在那个文件夹下创建, 创建新文件夹的list, 回调函数]
function _mkdirs(dir, lst, next) {
    if (lst.length === 0) {
        next(null, dir);
        return true;
    }
    var d = path.join(dir, lst[0])
    fs.mkdir(d, err => {
        if (err) {
            next(err, d)
            return false;
        }
        return _mkdirs(d, lst.slice(1), next)
    })
}

// 返回 00::00:00 格式时间
function _timer(timer) {
    let nowTime = '';
    let hour = 0,
        minute = 0,
        second = 0;

    const h = Math.floor(v / 60 / 60);
    hour = h >= 60 || h >= 10 ?
        h :
        '0' + h;

    const m = Math.floor(v / 60 % 60);
    minute = m >= 60 || m >= 10 ?
        m :
        '0' + m;
    const s = Math.floor(v % 60);
    second = s >= 10 ?
        s :
        '0' + s;

    nowTime = v >= (60 * 60) ?
        hour + ":" + minute + ":" + second :
        hour + ':' + minute + ":" + second;
    return nowTime;
}

// 排序 默认从小到大
// 用法 Array.sort( _min )
function _min(value1, value2) {
    if (value1 > value2) {
        return 1;
    } else if (value1 < value2) {
        return -1;
    } else {
        return 0;
    }
}


// 排序 默认从大到小
// 用法 Array.sort( _max )
function _max(value1, value2) {
    if (value1 > value2) {
        return -1;
    } else if (value1 < value2) {
        return 1;
    } else {
        return 0;
    }
}
/**
 * 
 * @param {string} byteStr 
 * @param {number} limit 
 * @returns string[] | undefined
 */
function byteStrSplit(byteStr, limit = 2) {
  if (byteStr.length % 2 != 0) return;
  let arr = [],
    start = 0,
    end = 0;

  do {
    end += limit;
    arr.push(byteStr.slice(start, end));
    start = end;
  } while (byteStr.length > end);
  return arr;
}

/**
 * 
 * @param {string[]} bytes 
 * @param {number} lineSize 
 * @param {number} offset 
 * @returns string
 */
function formatBytes(bytes, lineSize = 4, offset = 0) {
  let r = "";
  for (let i = 0; i < offset; i++) bytes.unshift("  ");

  bytes.forEach((it, index) => {
    index++;
    r += " " + it;
    if (index % lineSize == 0) r += "
";
  });
  return r;
}

console.log(
  formatBytes(
    byteStrSplit(
      `544c42423031d5011800007e0b8480580e0300000061616100ffffffff01000000000000544c4242303173031000007f0000000000000000000000001e030400`
    ),16,6
  )
);

                   54 4c 42 42 30 31 d5 01 18 00
 00 7e 0b 84 80 58 0e 03 00 00 00 61 61 61 00 ff
 ff ff ff 01 00 00 00 00 00 00 54 4c 42 42 30 31
 73 03 10 00 00 7f 00 00 00 00 00 00 00 00 00 00
 00 00 1e 03 04 00
原文地址:https://www.cnblogs.com/ajanuw/p/8159326.html