|
|
/**
|
|
|
* 辅助变量定义部分。
|
|
|
* 这里定义了一系列时间单位换算相关的变量,方便后续在时间格式化和解析等操作中使用。
|
|
|
*/
|
|
|
// 定义变量 s 表示 1 秒对应的毫秒数,即 1000 毫秒
|
|
|
var s = 1000;
|
|
|
// 定义变量 m 表示 1 分钟对应的毫秒数,通过 1 分钟等于 60 秒来换算,即 60 * 1000 毫秒
|
|
|
var m = s * 60;
|
|
|
// 定义变量 h 表示 1 小时对应的毫秒数,通过 1 小时等于 60 分钟来换算,即 60 * 60 * 1000 毫秒
|
|
|
var h = m * 60;
|
|
|
// 定义变量 d 表示 1 天对应的毫秒数,通过 1 天等于 24 小时来换算,即 24 * 60 * 60 * 1000 毫秒
|
|
|
var d = h * 24;
|
|
|
// 定义变量 y 表示 1 年对应的毫秒数,这里取一年为 365.25 天进行换算,即 365.25 * 24 * 60 * 60 * 1000 毫秒
|
|
|
var y = d * 365.25;
|
|
|
|
|
|
/**
|
|
|
* Parse or format the given `val`.
|
|
|
* 此函数是模块对外暴露的主要接口,用于解析给定的 `val` 参数(如果是字符串)或者格式化给定的 `val` 参数(如果是数字)。
|
|
|
*
|
|
|
* Options:
|
|
|
*
|
|
|
* - `long` verbose formatting [false]
|
|
|
* 可以传入一个可选的 `options` 对象,其中 `long` 属性用于控制是否采用详细(冗长)的格式化方式,默认值为 `false`。
|
|
|
*
|
|
|
* @param {String|Number} val 要处理的参数,可以是字符串或者数字类型。
|
|
|
* @param {Object} [options] 可选的配置对象,用于控制格式化等相关行为。
|
|
|
* @throws {Error} throw an error if val is not a non-empty string or a number 如果 `val` 既不是非空字符串也不是有效的数字,会抛出一个错误。
|
|
|
* @return {String|Number} 根据 `val` 的类型以及 `options` 的配置,返回相应的解析或格式化后的结果,可能是字符串或者数字类型。
|
|
|
* @api public
|
|
|
*/
|
|
|
module.exports = function(val, options) {
|
|
|
// 如果没有传入 `options` 参数,则创建一个空对象作为默认值,确保后续对 `options` 属性的访问不会出现问题
|
|
|
options = options || {};
|
|
|
// 获取 `val` 的类型,通过 `typeof` 操作符判断是字符串、数字还是其他类型
|
|
|
var type = typeof val;
|
|
|
// 如果 `val` 是字符串类型且长度大于 0,说明需要进行解析操作,调用 `parse` 函数(内部私有函数)进行解析,并返回解析结果
|
|
|
if (type ==='string' && val.length > 0) {
|
|
|
return parse(val);
|
|
|
} else if (type === 'number' && isNaN(val) === false) {
|
|
|
// 如果 `val` 是数字类型且不是 `NaN`(即有效数字),根据 `options.long` 的值来决定调用 `fmtLong`(详细格式化)函数还是 `fmtShort`(简短格式化)函数进行格式化,并返回格式化后的结果
|
|
|
return options.long? fmtLong(val) : fmtShort(val);
|
|
|
}
|
|
|
// 如果 `val` 不符合上述两种合法情况(既不是非空字符串也不是有效数字),抛出一个错误,提示 `val` 的值不符合要求,并展示 `val` 的具体内容(通过 `JSON.stringify` 转换为字符串形式)
|
|
|
throw new Error(
|
|
|
'val is not a non-empty string or a valid number. val=' +
|
|
|
JSON.stringify(val)
|
|
|
);
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* Parse the given `str` and return milliseconds.
|
|
|
* 此函数用于解析给定的字符串 `str`,尝试从字符串中提取时间相关的数值和单位信息,并将其转换为对应的毫秒数返回。
|
|
|
* 如果字符串格式不符合要求或者无法正确解析,则返回 `undefined`。
|
|
|
*
|
|
|
* @param {String} str 要解析的字符串,期望包含时间数值和对应的时间单位表示(如 "1h" 表示 1 小时)。
|
|
|
* @return {Number} 返回解析后的毫秒数,如果解析失败则返回 `undefined`。
|
|
|
* @api private
|
|
|
*/
|
|
|
function parse(str) {
|
|
|
// 将传入的 `str` 参数强制转换为字符串类型,确保后续字符串操作的一致性
|
|
|
str = String(str);
|
|
|
// 如果字符串长度大于 100,可能认为是不合理的输入,直接返回,不进行后续解析操作(这里 100 只是一个人为设定的长度限制阈值)
|
|
|
if (str.length > 100) {
|
|
|
return;
|
|
|
}
|
|
|
// 使用正则表达式来匹配字符串中的时间数值和单位部分,尝试提取相关信息。
|
|
|
// 正则表达式的含义如下:
|
|
|
// ^ 表示匹配字符串的开头
|
|
|
// (?:\d+)?\.?\d+ 表示匹配可选的整数部分(可能没有)、可选的小数点以及必须的小数部分,用于提取时间数值
|
|
|
// * 表示前面的数值部分和后面的单位部分之间可以有零个或多个空格
|
|
|
// (milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)? 表示匹配可选的时间单位部分,支持多种不同的时间单位缩写形式(如 "ms"、"s"、"m"、"h"、"d"、"y" 等),并且单位部分是不区分大小写的(通过 /i 修饰符指定)
|
|
|
// $ 表示匹配字符串的结尾
|
|
|
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
|
|
|
str
|
|
|
);
|
|
|
if (!match) {
|
|
|
return;
|
|
|
}
|
|
|
// 提取匹配到的时间数值部分,并通过 `parseFloat` 转换为浮点数类型,存储在变量 `n` 中
|
|
|
var n = parseFloat(match[1]);
|
|
|
// 提取匹配到的时间单位部分,如果没有匹配到则默认使用 "ms"(毫秒),并将其转换为小写形式,存储在变量 `type` 中
|
|
|
var type = (match[2] || 'ms').toLowerCase();
|
|
|
// 根据提取到的时间单位 `type`,通过 `switch` 语句进行不同情况的处理,将对应的时间数值转换为毫秒数并返回
|
|
|
switch (type) {
|
|
|
case 'years':
|
|
|
case 'year':
|
|
|
case 'yrs':
|
|
|
case 'yr':
|
|
|
case 'y':
|
|
|
return n * y;
|
|
|
case 'days':
|
|
|
case 'day':
|
|
|
case 'd':
|
|
|
return n * d;
|
|
|
case 'hours':
|
|
|
case 'hour':
|
|
|
case 'hrs':
|
|
|
case 'hr':
|
|
|
case 'h':
|
|
|
return n * h;
|
|
|
case 'minutes':
|
|
|
case 'minute':
|
|
|
case 'mins':
|
|
|
case 'min':
|
|
|
case 'm':
|
|
|
return n * m;
|
|
|
case 'seconds':
|
|
|
case 'second':
|
|
|
case 'secs':
|
|
|
case 'sec':
|
|
|
case 's':
|
|
|
return n * s;
|
|
|
case 'milliseconds':
|
|
|
case 'millisecond':
|
|
|
case 'msecs':
|
|
|
case 'msec':
|
|
|
case 'ms':
|
|
|
return n;
|
|
|
default:
|
|
|
return undefined;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Short format for `ms`.
|
|
|
* 此函数用于将给定的毫秒数 `ms` 转换为简短格式的时间表示字符串,根据毫秒数的大小选择合适的时间单位进行缩写显示。
|
|
|
*
|
|
|
* @param {Number} ms 要格式化的毫秒数。
|
|
|
* @return {String} 返回简短格式的时间表示字符串,如 "1h"、"30m"、"10s" 等形式。
|
|
|
* @api private
|
|
|
*/
|
|
|
function fmtShort(ms) {
|
|
|
// 如果毫秒数大于等于 1 天对应的毫秒数(`d`),则将其除以 `d` 并取整,然后加上时间单位 "d"(天)返回,表示以天为单位的时间格式
|
|
|
if (ms >= d) {
|
|
|
return Math.round(ms / d) + 'd';
|
|
|
}
|
|
|
// 如果毫秒数大于等于 1 小时对应的毫秒数(`h`),则将其除以 `h` 并取整,然后加上时间单位 "h"(小时)返回,表示以小时为单位的时间格式
|
|
|
if (ms >= h) {
|
|
|
return Math.round(ms / h) + 'h';
|
|
|
}
|
|
|
// 如果毫秒数大于等于 1 分钟对应的毫秒数(`m`),则将其除以 `m` 并取整,然后加上时间单位 "m"(分钟)返回,表示以分钟为单位的时间格式
|
|
|
if (ms >= m) {
|
|
|
return Math.round(ms / m) + 'm';
|
|
|
}
|
|
|
// 如果毫秒数大于等于 1 秒对应的毫秒数(`s`),则将其除以 `s` 并取整,然后加上时间单位 "s"(秒)返回,表示以秒为单位的时间格式
|
|
|
if (ms >= s) {
|
|
|
return Math.round(ms / s) + 's';
|
|
|
}
|
|
|
// 如果毫秒数小于 1 秒对应的毫秒数,直接返回原始的毫秒数加上时间单位 "ms"(毫秒),表示以毫秒为单位的时间格式
|
|
|
return ms + 'ms';
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Long format for `ms`.
|
|
|
* 此函数用于将给定的毫秒数 `ms` 转换为详细格式的时间表示字符串,会根据不同的时间范围使用更详细的表述方式(包含复数形式等)进行格式化。
|
|
|
*
|
|
|
* @param {Number} ms 要格式化的毫秒数。
|
|
|
* @return {String} 返回详细格式的时间表示字符串,如 "1 day"、"2 hours" 等形式,更符合自然语言的表述习惯。
|
|
|
* @api private
|
|
|
*/
|
|
|
function fmtLong(ms) {
|
|
|
return (
|
|
|
// 调用 `plural` 函数(内部私有函数)尝试按照以天为单位进行格式化,如果满足条件则返回相应的格式化字符串,否则继续后续的格式化判断
|
|
|
plural(ms, d, 'day') ||
|
|
|
// 调用 `plural` 函数尝试按照以小时为单位进行格式化,如果满足条件则返回相应的格式化字符串,否则继续后续的格式化判断
|
|
|
plural(ms, h, 'hour') ||
|
|
|
// 调用 `plural` 函数尝试按照以分钟为单位进行格式化,如果满足条件则返回相应的格式化字符串,否则继续后续的格式化判断
|
|
|
plural(ms, h, 'minute') ||
|
|
|
// 调用 `plural` 函数尝试按照以秒为单位进行格式化,如果满足条件则返回相应的格式化字符串,否则直接返回原始的毫秒数加上 " ms"(注意这里有空格)作为最后的格式化结果
|
|
|
plural(ms, s, 'second') ||
|
|
|
ms +'ms'
|
|
|
);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Pluralization helper.
|
|
|
* 此函数是一个辅助函数,用于根据给定的毫秒数 `ms`、时间单位对应的毫秒数 `n`(如 `d`、`h`、`m`、`s` 等)以及时间单位名称 `name`,
|
|
|
* 来判断是否需要使用复数形式进行格式化,并返回相应的格式化字符串。
|
|
|
* 如果毫秒数小于对应的时间单位毫秒数 `n`,则直接返回 `undefined`,表示不满足格式化条件。
|
|
|
*/
|
|
|
function plural(ms, n, name) {
|
|
|
if (ms < n) {
|
|
|
return;
|
|
|
}
|
|
|
// 如果毫秒数小于对应时间单位毫秒数的 1.5 倍,使用 `Math.floor` 向下取整,并按照单数形式(不带 "s")进行格式化,返回如 "1 day" 的格式字符串
|
|
|
if (ms < n * 1.5) {
|
|
|
return Math.floor(ms / n) +' '+ name;
|
|
|
}
|
|
|
// 如果毫秒数大于等于对应时间单位毫秒数的 1.5 倍,使用 `Math.ceil` 向上取整,并按照复数形式(带 "s")进行格式化,返回如 "2 days" 的格式字符串
|
|
|
return Math.ceil(ms / n) +' '+ name +'s';
|
|
|
} |