@cloudcome/utils-core 0.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/array.cjs +129 -0
- package/dist/array.cjs.map +1 -0
- package/dist/array.d.ts +171 -0
- package/dist/array.mjs +129 -0
- package/dist/array.mjs.map +1 -0
- package/dist/async.cjs +219 -0
- package/dist/async.cjs.map +1 -0
- package/dist/async.d.ts +137 -0
- package/dist/async.mjs +219 -0
- package/dist/async.mjs.map +1 -0
- package/dist/base64.cjs +16 -0
- package/dist/base64.cjs.map +1 -0
- package/dist/base64.d.ts +7 -0
- package/dist/base64.mjs +16 -0
- package/dist/base64.mjs.map +1 -0
- package/dist/cache.cjs +79 -0
- package/dist/cache.cjs.map +1 -0
- package/dist/cache.d.ts +90 -0
- package/dist/cache.mjs +79 -0
- package/dist/cache.mjs.map +1 -0
- package/dist/color/contrast.d.ts +10 -0
- package/dist/color/distance.d.ts +8 -0
- package/dist/color/helpers.d.ts +2 -0
- package/dist/color/hex-hsl.d.ts +3 -0
- package/dist/color/hex-hsv.d.ts +20 -0
- package/dist/color/hex-hwb.d.ts +23 -0
- package/dist/color/hex-rgb.d.ts +18 -0
- package/dist/color/hsl-lighten.d.ts +10 -0
- package/dist/color/hsv-brighten.d.ts +12 -0
- package/dist/color/luminance.d.ts +10 -0
- package/dist/color/mix.d.ts +18 -0
- package/dist/color/rgb-hsl.d.ts +23 -0
- package/dist/color/rgb-hsv.d.ts +25 -0
- package/dist/color/rgb-hwb.d.ts +29 -0
- package/dist/color/rgb-lab.d.ts +25 -0
- package/dist/color/rgb-whiter.d.ts +12 -0
- package/dist/color/rgb-xyz.d.ts +22 -0
- package/dist/color/types.d.ts +83 -0
- package/dist/color/xyz-lab.d.ts +25 -0
- package/dist/color.cjs +250 -0
- package/dist/color.cjs.map +1 -0
- package/dist/color.d.ts +19 -0
- package/dist/color.mjs +250 -0
- package/dist/color.mjs.map +1 -0
- package/dist/const.cjs +14 -0
- package/dist/const.cjs.map +1 -0
- package/dist/const.mjs +15 -0
- package/dist/const.mjs.map +1 -0
- package/dist/core.cjs +250 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.mjs +251 -0
- package/dist/core.mjs.map +1 -0
- package/dist/crypto/md5.d.mts +1 -0
- package/dist/crypto/sha1.d.mts +1 -0
- package/dist/crypto/sha256.d.mts +1 -0
- package/dist/crypto/sha512.d.mts +1 -0
- package/dist/crypto.cjs +812 -0
- package/dist/crypto.cjs.map +1 -0
- package/dist/crypto.d.ts +44 -0
- package/dist/crypto.mjs +812 -0
- package/dist/crypto.mjs.map +1 -0
- package/dist/date/const.d.ts +6 -0
- package/dist/date/core.d.ts +52 -0
- package/dist/date/days.d.ts +23 -0
- package/dist/date/is.d.ts +92 -0
- package/dist/date/relative.d.ts +44 -0
- package/dist/date/start-end.d.ts +73 -0
- package/dist/date/timezone.d.ts +67 -0
- package/dist/date/weeks.d.ts +72 -0
- package/dist/date.cjs +239 -0
- package/dist/date.cjs.map +1 -0
- package/dist/date.d.ts +8 -0
- package/dist/date.mjs +241 -0
- package/dist/date.mjs.map +1 -0
- package/dist/dict.cjs +2 -0
- package/dist/dict.cjs.map +1 -0
- package/dist/dict.d.ts +1 -0
- package/dist/dict.mjs +2 -0
- package/dist/dict.mjs.map +1 -0
- package/dist/each.cjs +18 -0
- package/dist/each.cjs.map +1 -0
- package/dist/each.mjs +19 -0
- package/dist/each.mjs.map +1 -0
- package/dist/easing.cjs +151 -0
- package/dist/easing.cjs.map +1 -0
- package/dist/easing.d.ts +46 -0
- package/dist/easing.mjs +151 -0
- package/dist/easing.mjs.map +1 -0
- package/dist/emitter.cjs +94 -0
- package/dist/emitter.cjs.map +1 -0
- package/dist/emitter.d.ts +68 -0
- package/dist/emitter.mjs +94 -0
- package/dist/emitter.mjs.map +1 -0
- package/dist/enum.cjs +58 -0
- package/dist/enum.cjs.map +1 -0
- package/dist/enum.d.ts +68 -0
- package/dist/enum.mjs +58 -0
- package/dist/enum.mjs.map +1 -0
- package/dist/env.cjs +28 -0
- package/dist/env.cjs.map +1 -0
- package/dist/env.d.ts +38 -0
- package/dist/env.mjs +28 -0
- package/dist/env.mjs.map +1 -0
- package/dist/error.cjs +12 -0
- package/dist/error.cjs.map +1 -0
- package/dist/error.d.ts +22 -0
- package/dist/error.mjs +12 -0
- package/dist/error.mjs.map +1 -0
- package/dist/exception.cjs +22 -0
- package/dist/exception.cjs.map +1 -0
- package/dist/exception.d.ts +31 -0
- package/dist/exception.mjs +22 -0
- package/dist/exception.mjs.map +1 -0
- package/dist/fn.cjs +76 -0
- package/dist/fn.cjs.map +1 -0
- package/dist/fn.d.ts +102 -0
- package/dist/fn.mjs +76 -0
- package/dist/fn.mjs.map +1 -0
- package/dist/index.cjs +5 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +5 -0
- package/dist/index.mjs.map +1 -0
- package/dist/merge.cjs +87 -0
- package/dist/merge.cjs.map +1 -0
- package/dist/merge.mjs +88 -0
- package/dist/merge.mjs.map +1 -0
- package/dist/number.cjs +11 -0
- package/dist/number.cjs.map +1 -0
- package/dist/number.d.ts +137 -0
- package/dist/number.mjs +11 -0
- package/dist/number.mjs.map +1 -0
- package/dist/object/each.d.ts +36 -0
- package/dist/object/get-set.d.ts +111 -0
- package/dist/object/is.d.ts +32 -0
- package/dist/object/merge.d.ts +72 -0
- package/dist/object/process.d.ts +46 -0
- package/dist/object.cjs +130 -0
- package/dist/object.cjs.map +1 -0
- package/dist/object.d.ts +5 -0
- package/dist/object.mjs +130 -0
- package/dist/object.mjs.map +1 -0
- package/dist/path.cjs +77 -0
- package/dist/path.cjs.map +1 -0
- package/dist/path.d.ts +82 -0
- package/dist/path.mjs +77 -0
- package/dist/path.mjs.map +1 -0
- package/dist/promise.cjs +62 -0
- package/dist/promise.cjs.map +1 -0
- package/dist/promise.d.ts +50 -0
- package/dist/promise.mjs +62 -0
- package/dist/promise.mjs.map +1 -0
- package/dist/qs.cjs +47 -0
- package/dist/qs.cjs.map +1 -0
- package/dist/qs.d.ts +62 -0
- package/dist/qs.mjs +47 -0
- package/dist/qs.mjs.map +1 -0
- package/dist/regexp.cjs +66 -0
- package/dist/regexp.cjs.map +1 -0
- package/dist/regexp.d.ts +65 -0
- package/dist/regexp.mjs +66 -0
- package/dist/regexp.mjs.map +1 -0
- package/dist/string.cjs +16 -0
- package/dist/string.cjs.map +1 -0
- package/dist/string.d.ts +80 -0
- package/dist/string.mjs +16 -0
- package/dist/string.mjs.map +1 -0
- package/dist/string2.cjs +147 -0
- package/dist/string2.cjs.map +1 -0
- package/dist/string2.mjs +148 -0
- package/dist/string2.mjs.map +1 -0
- package/dist/time/from.d.ts +14 -0
- package/dist/time/to.d.ts +38 -0
- package/dist/time.cjs +82 -0
- package/dist/time.cjs.map +1 -0
- package/dist/time.d.ts +2 -0
- package/dist/time.mjs +82 -0
- package/dist/time.mjs.map +1 -0
- package/dist/timer.cjs +119 -0
- package/dist/timer.cjs.map +1 -0
- package/dist/timer.d.ts +96 -0
- package/dist/timer.mjs +119 -0
- package/dist/timer.mjs.map +1 -0
- package/dist/tree.cjs +125 -0
- package/dist/tree.cjs.map +1 -0
- package/dist/tree.d.ts +210 -0
- package/dist/tree.mjs +125 -0
- package/dist/tree.mjs.map +1 -0
- package/dist/type.cjs +78 -0
- package/dist/type.cjs.map +1 -0
- package/dist/type.d.ts +121 -0
- package/dist/type.mjs +78 -0
- package/dist/type.mjs.map +1 -0
- package/dist/types.cjs +2 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -0
- package/dist/unique.cjs +46 -0
- package/dist/unique.cjs.map +1 -0
- package/dist/unique.d.ts +22 -0
- package/dist/unique.mjs +46 -0
- package/dist/unique.mjs.map +1 -0
- package/dist/url.cjs +37 -0
- package/dist/url.cjs.map +1 -0
- package/dist/url.d.ts +53 -0
- package/dist/url.mjs +37 -0
- package/dist/url.mjs.map +1 -0
- package/dist/version.cjs +33 -0
- package/dist/version.cjs.map +1 -0
- package/dist/version.d.ts +32 -0
- package/dist/version.mjs +33 -0
- package/dist/version.mjs.map +1 -0
- package/package.json +1 -8
package/dist/string2.mjs
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { o as objectDefaults } from "./merge.mjs";
|
|
2
|
+
import { isObject, isUndefined, isFunction, isNullish } from "./type.mjs";
|
|
3
|
+
function numberFixed(number, options) {
|
|
4
|
+
const { precision = 0, round = 0 } = options || {};
|
|
5
|
+
const scale = 10 ** precision;
|
|
6
|
+
if (round === 1) {
|
|
7
|
+
return Math.ceil(number * scale) / scale;
|
|
8
|
+
}
|
|
9
|
+
if (round === -1) {
|
|
10
|
+
return Math.floor(number * scale) / scale;
|
|
11
|
+
}
|
|
12
|
+
return Math.round(number * scale) / scale;
|
|
13
|
+
}
|
|
14
|
+
function randomNumber(min, max) {
|
|
15
|
+
const [minFinal, maxFinal] = min > max ? [max, min] : [min, max];
|
|
16
|
+
return Math.floor(Math.random() * (maxFinal - minFinal + 1) + minFinal);
|
|
17
|
+
}
|
|
18
|
+
function numberAbbr(number, units, options) {
|
|
19
|
+
const { base = 1e3, precision = 0 } = options || {};
|
|
20
|
+
const { length } = units;
|
|
21
|
+
if (length === 0) throw new Error("数字单位组不能为空");
|
|
22
|
+
let numberFinal = number;
|
|
23
|
+
let step = 0;
|
|
24
|
+
while (numberFinal >= base && step < length - 1) {
|
|
25
|
+
numberFinal = numberFinal / base;
|
|
26
|
+
step++;
|
|
27
|
+
}
|
|
28
|
+
const value = numberFixed(numberFinal, { precision, round: -1 });
|
|
29
|
+
const unit = units[step];
|
|
30
|
+
return `${value}${unit}`;
|
|
31
|
+
}
|
|
32
|
+
function fileSizeAbbr(number, precision = 0) {
|
|
33
|
+
return numberAbbr(number, ["B", "KB", "MB", "GB", "TB"], {
|
|
34
|
+
base: 1024,
|
|
35
|
+
precision
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function numberConvert(decimal, dict) {
|
|
39
|
+
const dictFinal = dict || STRING_DICT;
|
|
40
|
+
if (dictFinal.length < 2) throw new Error("进制转换字典长度不能小于 2");
|
|
41
|
+
let bigInt = BigInt(decimal);
|
|
42
|
+
const symbol = bigInt < 0n ? "-" : "";
|
|
43
|
+
bigInt = bigInt < 0n ? -bigInt : bigInt;
|
|
44
|
+
const result = [];
|
|
45
|
+
const { length } = dictFinal;
|
|
46
|
+
const bigLength = BigInt(length);
|
|
47
|
+
const calculate = () => {
|
|
48
|
+
const y = Number(bigInt % bigLength);
|
|
49
|
+
bigInt = bigInt / bigLength;
|
|
50
|
+
result.unshift(dictFinal[y]);
|
|
51
|
+
if (bigInt > 0) {
|
|
52
|
+
calculate();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
calculate();
|
|
56
|
+
return symbol + result.join("");
|
|
57
|
+
}
|
|
58
|
+
function numberFormat(number, options) {
|
|
59
|
+
let optionsFinal = {
|
|
60
|
+
separator: ",",
|
|
61
|
+
step: 3
|
|
62
|
+
};
|
|
63
|
+
if (typeof options === "string") {
|
|
64
|
+
optionsFinal.separator = options;
|
|
65
|
+
} else if (typeof options === "number") {
|
|
66
|
+
optionsFinal.step = options;
|
|
67
|
+
} else {
|
|
68
|
+
optionsFinal = objectDefaults(options || {}, optionsFinal);
|
|
69
|
+
}
|
|
70
|
+
const { separator, step } = optionsFinal;
|
|
71
|
+
const arr = String(number).split(".");
|
|
72
|
+
const re = new RegExp(`(\\d)(?=(\\d{${step}})+(?!\\d))`, "g");
|
|
73
|
+
const p1 = arr[0].replace(re, `$1${separator}`);
|
|
74
|
+
return p1 + (arr[1] ? `.${arr[1]}` : "");
|
|
75
|
+
}
|
|
76
|
+
const STRING_ARABIC_NUMERALS = "0123456789";
|
|
77
|
+
const STRING_HEXADECIMALS = "0123456789abcdef";
|
|
78
|
+
const STRING_LOWERCASE_ALPHA = "abcdefghijklmnopqrstuvwxyz";
|
|
79
|
+
const STRING_UPPERCASE_ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
80
|
+
const STRING_DICT = `${STRING_ARABIC_NUMERALS + STRING_UPPERCASE_ALPHA + STRING_LOWERCASE_ALPHA}`;
|
|
81
|
+
function stringCamelCase(string, bigger) {
|
|
82
|
+
const string2 = string.replace(/[\s_-](.)/g, (_, char) => char.toUpperCase());
|
|
83
|
+
return bigger ? string2.slice(0, 1).toUpperCase() + string2.slice(1) : string2;
|
|
84
|
+
}
|
|
85
|
+
function stringKebabCase(string, separator = "-") {
|
|
86
|
+
return string.replace(/[A-Z]/g, (origin) => `${separator}${origin.toLowerCase()}`);
|
|
87
|
+
}
|
|
88
|
+
function randomString(length, dict) {
|
|
89
|
+
const dictFinal = dict || STRING_DICT;
|
|
90
|
+
const dictLength = dictFinal.length;
|
|
91
|
+
let result = "";
|
|
92
|
+
for (let i = 0; i < length; i++) {
|
|
93
|
+
result += dictFinal.charAt(randomNumber(0, dictLength - 1));
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
function stringFormat(str, ...args) {
|
|
98
|
+
const [firstArg, fallback] = args;
|
|
99
|
+
if (isObject(firstArg) || isUndefined(firstArg)) {
|
|
100
|
+
const vars = firstArg || {};
|
|
101
|
+
return str.replace(/\{(\w+)\}/g, (_, key) => vars[key] ?? (isFunction(fallback) ? fallback(key) : fallback) ?? key);
|
|
102
|
+
}
|
|
103
|
+
return str.replace(/\{(\d+)\}/g, (_, key) => {
|
|
104
|
+
const index = Number(key);
|
|
105
|
+
if (Number.isNaN(index)) return key;
|
|
106
|
+
return args[index];
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function randomUUID4() {
|
|
110
|
+
const template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
|
|
111
|
+
let result = "";
|
|
112
|
+
for (let i = 0; i < template.length; i++) {
|
|
113
|
+
const t = template[i];
|
|
114
|
+
if (t === "-" || t === "4") {
|
|
115
|
+
result += t;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (t === "y") {
|
|
119
|
+
result += randomString(1, "89ab");
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
result += randomString(1, STRING_HEXADECIMALS);
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
function stringify(value) {
|
|
127
|
+
return isNullish(value) ? "" : String(value);
|
|
128
|
+
}
|
|
129
|
+
export {
|
|
130
|
+
STRING_DICT as S,
|
|
131
|
+
numberFixed as a,
|
|
132
|
+
numberAbbr as b,
|
|
133
|
+
numberFormat as c,
|
|
134
|
+
STRING_ARABIC_NUMERALS as d,
|
|
135
|
+
STRING_HEXADECIMALS as e,
|
|
136
|
+
fileSizeAbbr as f,
|
|
137
|
+
STRING_LOWERCASE_ALPHA as g,
|
|
138
|
+
STRING_UPPERCASE_ALPHA as h,
|
|
139
|
+
stringCamelCase as i,
|
|
140
|
+
stringKebabCase as j,
|
|
141
|
+
randomString as k,
|
|
142
|
+
randomUUID4 as l,
|
|
143
|
+
stringify as m,
|
|
144
|
+
numberConvert as n,
|
|
145
|
+
randomNumber as r,
|
|
146
|
+
stringFormat as s
|
|
147
|
+
};
|
|
148
|
+
//# sourceMappingURL=string2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string2.mjs","sources":["../src/number.ts","../src/string.ts"],"sourcesContent":["import { objectDefaults } from './object';\nimport { STRING_DICT } from './string';\n\nexport type NumberFixedOptions = {\n /**\n * 保留的小数位数\n * @default 0\n */\n precision?: number;\n\n /**\n * 舍入方法,0 为四舍五入,1 为向上取整,-1 为向下取整\n * @default 0\n */\n round?: 0 | 1 | -1;\n};\n\n/**\n * 对数字进行精确小数位数处理并按规则舍入\n * @param number 需要处理的原始数值\n * @param options 可选配置参数\n * @returns 处理后的数值(number类型)\n * @example\n * // 四舍五入示例\n * numberFixed(3.1415, { precision: 2 }); // 3.14\n * // 向上取整示例\n * numberFixed(3.1415, { precision: 2, round: 1 }); // 3.15\n * // 向下取整示例\n * numberFixed(3.9999, { precision: 1, round: -1 }); // 3.9\n */\nexport function numberFixed(number: number, options?: NumberFixedOptions) {\n const { precision = 0, round = 0 } = options || {};\n const scale = 10 ** precision;\n\n if (round === 1) {\n return Math.ceil(number * scale) / scale;\n }\n\n if (round === -1) {\n return Math.floor(number * scale) / scale;\n }\n\n return Math.round(number * scale) / scale;\n}\n\n/**\n * 生成指定范围内的随机整数\n * @param {number} min - 随机数的最小值(包含)\n * @param {number} max - 随机数的最大值(包含)\n * @returns {number} - 生成的随机整数\n * @example\n * // 生成 1 到 10 之间的随机整数\n * randomNumber(1, 10); // 可能返回 7\n */\nexport function randomNumber(min: number, max: number): number {\n const [minFinal, maxFinal] = min > max ? [max, min] : [min, max];\n return Math.floor(Math.random() * (maxFinal - minFinal + 1) + minFinal);\n}\n\n/**\n * 数字缩写选项\n */\nexport type NumberAbbrOptions = {\n /**\n * 进制基数,用于计算单位进阶(如 1000 表示千进制)\n * @default 1000\n */\n base?: number;\n\n /**\n * 数值保留的小数位数\n * @default 0\n */\n precision?: number;\n};\n\n/**\n * 将数字转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的原始数值\n * @param {Array<string>} units - 单位数组,按从小到大顺序排列(如['B','KB','MB']),不能为空\n * @param {NumberAbbrOptions} [options] - 可选配置参数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * numberAbbr(1500, ['', 'K', 'M'], { base: 1000 }); // \"1.5K\"\n * @example\n * // 自定义小数位\n * numberAbbr(123456, ['B','KB','MB'], { precision: 1 }); // \"0.1MB\"\n * @example\n * // 处理不足基数的情况\n * numberAbbr(500, ['B','KB']); // \"500B\"\n */\nexport function numberAbbr(number: number, units: Array<string>, options?: NumberAbbrOptions): string {\n const { base = 1000, precision = 0 } = options || {};\n const { length } = units;\n\n if (length === 0) throw new Error('数字单位组不能为空');\n\n let numberFinal = number;\n let step = 0;\n\n while (numberFinal >= base && step < length - 1) {\n numberFinal = numberFinal / base;\n step++;\n }\n\n const value = numberFixed(numberFinal, { precision, round: -1 });\n const unit = units[step];\n\n return `${value}${unit}`;\n}\n\n/**\n * 将文件大小转换为带单位缩写的字符串表示\n *\n * @param {number} number - 需要转换的文件大小数值\n * @param {number} [precision=0] - 数值保留的小数位数\n * @returns {string} - 转换后的带单位字符串(如\"1.2KB\")\n * @example\n * // 基础用法\n * fileSizeAbbr(1024); // \"1KB\"\n * @example\n * // 自定义小数位\n * fileSizeAbbr(123456, 1); // \"0.1MB\"\n */\nexport function fileSizeAbbr(number: number, precision = 0) {\n return numberAbbr(number, ['B', 'KB', 'MB', 'GB', 'TB'], {\n base: 1024,\n precision,\n });\n}\n\n/**\n * 将十进制数转换为指定进制的字符串表示\n *\n * @param {number | bigint} decimal - 需要转换的十进制数,可以是任意长度的数字或大整数\n * @param {string} [dict] - 用于表示进制的字符字典,默认为数字、小写字母和大写字母的组合(62 进制)\n * @returns {string} - 转换后的指定进制字符串\n * @throws {Error} - 如果字符字典的长度小于 2,将抛出错误\n * @example\n * // 默认 62 进制\n * numberConvert(123456789); // \"8M0kX\"\n * @example\n * // 自定义 16 进制\n * numberConvert(255, '0123456789ABCDEF'); // \"FF\"\n * @example\n * // 处理大整数\n * numberConvert(9007199254740991n); // \"2gosa7pa2GV\"\n */\nexport function numberConvert(decimal: number | bigint, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n\n if (dictFinal.length < 2) throw new Error('进制转换字典长度不能小于 2');\n\n let bigInt = BigInt(decimal);\n const symbol = bigInt < 0n ? '-' : '';\n bigInt = bigInt < 0n ? -bigInt : bigInt;\n const result: Array<string> = [];\n const { length } = dictFinal;\n const bigLength = BigInt(length);\n const calculate = (): void => {\n const y = Number(bigInt % bigLength);\n\n bigInt = bigInt / bigLength;\n result.unshift(dictFinal[y]);\n\n if (bigInt > 0) {\n calculate();\n }\n };\n\n calculate();\n\n return symbol + result.join('');\n}\n\n/**\n * 数字格式化配置选项\n */\nexport type NumberFormatOptions = {\n /**\n * 分隔符字符,用于数字分隔\n * @default ','\n * @example 使用 '_' 分隔符时,123456 会格式化为 '123_456'\n */\n separator?: string;\n\n /**\n * 分隔步长,即每隔多少位添加分隔符\n * @default 3\n * @example 步长为 2 时,123456 会格式化为 '12,34,56'\n */\n step?: number;\n};\n\n/**\n * 数字格式化\n * @param [number] {number} 数字\n * @param options {NumberFormatOptions} 格式化配置\n * @returns {string} 分割后的字符串\n * @example\n * // 使用默认分隔符和步长\n * numberFormat(123456.789); // => \"123,456.789\"\n * // 自定义分隔符\n * numberFormat(123456.789, '_'); // => \"123_456.789\"\n * // 自定义步长\n * numberFormat(123456.789, 2); // => \"12,34,56.789\"\n * // 使用对象配置\n * numberFormat(123456.789, { separator: '.', step: 4 }); // => \"12.3456.789\"\n */\nexport function numberFormat(number: number, options: NumberFormatOptions): string;\nexport function numberFormat(number: number, separator: string): string;\nexport function numberFormat(number: number, step: number): string;\nexport function numberFormat(number: number): string;\nexport function numberFormat(number: number, options?: NumberFormatOptions | string | number) {\n let optionsFinal: Required<NumberFormatOptions> = {\n separator: ',',\n step: 3,\n };\n\n if (typeof options === 'string') {\n optionsFinal.separator = options;\n } else if (typeof options === 'number') {\n optionsFinal.step = options;\n } else {\n optionsFinal = objectDefaults(options || {}, optionsFinal) as Required<NumberFormatOptions>;\n }\n\n const { separator, step } = optionsFinal;\n const arr = String(number).split('.');\n const re = new RegExp(`(\\\\d)(?=(\\\\d{${step}})+(?!\\\\d))`, 'g');\n const p1 = arr[0].replace(re, `$1${separator}`);\n\n return p1 + (arr[1] ? `.${arr[1]}` : '');\n}\n","import { numberConvert, randomNumber } from './number';\nimport { isFunction, isNullish, isNumber, isObject, isString, isUndefined } from './type';\n\nexport const STRING_ARABIC_NUMERALS = '0123456789';\nexport const STRING_HEXADECIMALS = '0123456789abcdef';\nexport const STRING_LOWERCASE_ALPHA = 'abcdefghijklmnopqrstuvwxyz';\nexport const STRING_UPPERCASE_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nexport const STRING_DICT = `${STRING_ARABIC_NUMERALS + STRING_UPPERCASE_ALPHA + STRING_LOWERCASE_ALPHA}`;\n\n/**\n * 将字符串转换为驼峰格式\n * @param {string} string - 要转换的字符串\n * @param {boolean} [bigger] - 是否大写第一个字母,默认为 false\n * @returns {string} - 转换后的驼峰格式字符串\n */\nexport function stringCamelCase(string: string, bigger?: boolean): string {\n const string2 = string.replace(/[\\s_-](.)/g, (_, char) => (char as string).toUpperCase());\n return bigger ? string2.slice(0, 1).toUpperCase() + string2.slice(1) : string2;\n}\n\n/**\n * 将字符串转换为连字格式\n * @param {string} string - 要转换的字符串\n * @param {string} [separator] - 分隔符,默认是 \"-\"(短横线)\n * @returns {string} - 转换后的连字格式字符串\n */\nexport function stringKebabCase(string: string, separator = '-'): string {\n return string.replace(/[A-Z]/g, (origin) => `${separator}${origin.toLowerCase()}`);\n}\n\n/**\n * 生成随机字符串\n * @param {number} length - 生成的随机字符串长度\n * @param {string} [dict] - 用于生成随机字符串的字符字典,默认为数字、小写字母和大写字母的组合\n * @returns {string} - 生成的随机字符串\n * @example\n * randomString(10); // 生成一个长度为 10 的随机字符串\n * randomString(8, 'ABCDEF'); // 生成一个长度为 8 的随机字符串,仅包含字符 'ABCDEF'\n */\nexport function randomString(length: number, dict?: string): string {\n const dictFinal = dict || STRING_DICT;\n const dictLength = dictFinal.length;\n\n let result = '';\n\n for (let i = 0; i < length; i++) {\n result += dictFinal.charAt(randomNumber(0, dictLength - 1));\n }\n\n return result;\n}\n\n/**\n * 简单的模板引擎,类似于 Python 的 `.format()` 方法\n * 支持通过索引或对象/名称的方式传递变量\n * 当使用对象/名称方式时,可以传递一个回退值作为第三个参数\n *\n * @category 字符串\n * @example\n * ```\n * // 索引方式\n * const result = stringFormat(\n * '你好 {0}!我的名字是 {1}。',\n * '张三',\n * '李四'\n * ); // 你好 张三!我的名字是 李四。\n * ```\n *\n * @example\n * ```\n * // 对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好', name: '王五' }\n * ); // 你好!我的名字是 王五。\n * ```\n *\n * @example\n * ```\n * // 带回退值的对象方式\n * const result = stringFormat(\n * '{greet}!我的名字是 {name}。',\n * { greet: '你好' }, // name 未传递,因此会使用回退值\n * '未知'\n * ); // 你好!我的名字是 未知。\n * ```\n */\nexport function stringFormat(\n str: string,\n object: Record<string | number, unknown>,\n fallback?: string | ((key: string) => string),\n): string;\nexport function stringFormat(str: string, ...args: (string | number | bigint | undefined | null)[]): string;\nexport function stringFormat(str: string, ...args: unknown[]): string {\n const [firstArg, fallback] = args;\n\n if (isObject(firstArg) || isUndefined(firstArg)) {\n const vars = firstArg || {};\n return str.replace(/\\{(\\w+)\\}/g, (_, key) => vars[key] ?? (isFunction(fallback) ? fallback(key) : fallback) ?? key);\n }\n\n return str.replace(/\\{(\\d+)\\}/g, (_, key) => {\n const index = Number(key);\n if (Number.isNaN(index)) return key;\n return args[index];\n });\n}\n\n/**\n * 生成符合 [RFC 4122](https://www.ietf.org/rfc/rfc4122.txt) 版本 4 的 UUID 字符串\n * @returns {string} - 生成的 UUID 字符串\n * @example\n * const uuid = randomUUID4();\n * console.log(uuid); // 输出类似 '123e4567-e89b-12d3-a456-426614174000' 的 UUID 字符串\n */\nexport function randomUUID4(): string {\n const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';\n let result = '';\n\n for (let i = 0; i < template.length; i++) {\n const t = template[i];\n\n if (t === '-' || t === '4') {\n result += t;\n continue;\n }\n\n if (t === 'y') {\n result += randomString(1, '89ab');\n continue;\n }\n\n result += randomString(1, STRING_HEXADECIMALS);\n }\n\n return result;\n}\n\n/**\n * 将值转换为字符串,若值为 null 或 undefined 则返回空字符串\n * @param {unknown} value - 需要转换的值\n * @returns {string} 转换后的字符串结果\n */\nexport function stringify(value: unknown) {\n return isNullish(value) ? '' : String(value);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TTimeDuration } from './to';
|
|
2
|
+
/**
|
|
3
|
+
* 将时间持续时间字符串或对象转换为毫秒数
|
|
4
|
+
*
|
|
5
|
+
* @param duration - 可以是时间持续时间字符串(如 '1d2h')或 TTimeDuration 对象
|
|
6
|
+
* @returns 计算得到的总毫秒数
|
|
7
|
+
*/
|
|
8
|
+
export declare function timeFrom(duration: string | TTimeDuration): number;
|
|
9
|
+
/**
|
|
10
|
+
* 将时长字符串解析为时间对象
|
|
11
|
+
* @param duration - 时长字符串(例如 "1h30m")
|
|
12
|
+
* @returns 包含解析后时间单位的对象(小时、分钟等)
|
|
13
|
+
*/
|
|
14
|
+
export declare function timeParse(duration: string): TTimeDuration;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type TTimeDuration = {
|
|
2
|
+
years: number;
|
|
3
|
+
months: number;
|
|
4
|
+
/** 天数 */
|
|
5
|
+
days: number;
|
|
6
|
+
/** 小时数 */
|
|
7
|
+
hours: number;
|
|
8
|
+
/** 分钟数 */
|
|
9
|
+
minutes: number;
|
|
10
|
+
/** 秒数 */
|
|
11
|
+
seconds: number;
|
|
12
|
+
/** 毫秒数 */
|
|
13
|
+
milliseconds: number;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* 将时间毫秒数解析为以天为最大单位的绝对时间对象
|
|
17
|
+
* @param timeMs 时间毫秒数
|
|
18
|
+
* @returns 包含天/小时/分钟/秒/毫秒分解结果的对象
|
|
19
|
+
*/
|
|
20
|
+
export declare function timeToDays(timeMs: number): TTimeDuration;
|
|
21
|
+
/**
|
|
22
|
+
* 将时间毫秒数解析为以小时为最大单位的绝对时间对象
|
|
23
|
+
* @param timeMs 时间毫秒数
|
|
24
|
+
* @returns 包含小时/分钟/秒/毫秒分解结果的对象
|
|
25
|
+
*/
|
|
26
|
+
export declare function timeToHours(timeMs: number): TTimeDuration;
|
|
27
|
+
/**
|
|
28
|
+
* 将时间毫秒数解析为以分钟为最大单位的绝对时间对象
|
|
29
|
+
* @param timeMs 时间毫秒数
|
|
30
|
+
* @returns 包含分钟/秒/毫秒分解结果的对象
|
|
31
|
+
*/
|
|
32
|
+
export declare function timeToMinutes(timeMs: number): TTimeDuration;
|
|
33
|
+
/**
|
|
34
|
+
* 将时间毫秒数解析为以秒为最大单位的绝对时间对象
|
|
35
|
+
* @param timeMs 时间毫秒数
|
|
36
|
+
* @returns 包含秒/毫秒分解结果的对象
|
|
37
|
+
*/
|
|
38
|
+
export declare function timeToSeconds(timeMs: number): TTimeDuration;
|
package/dist/time.cjs
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const _const = require("./const.cjs");
|
|
4
|
+
const type = require("./type.cjs");
|
|
5
|
+
const rules = [
|
|
6
|
+
["years", _const.DATE_YEAR_MS],
|
|
7
|
+
["months", _const.DATE_MONTH_MS],
|
|
8
|
+
["days", _const.DATE_DAY_MS],
|
|
9
|
+
["hours", _const.DATE_HOUR_MS],
|
|
10
|
+
["minutes", _const.DATE_MINUTE_MS],
|
|
11
|
+
["seconds", _const.DATE_SECOND_MS]
|
|
12
|
+
];
|
|
13
|
+
function timeFrom(duration) {
|
|
14
|
+
const td = type.isString(duration) ? timeParse(duration) : duration;
|
|
15
|
+
return rules.reduce((acc, [key, time]) => acc + (td[key] || 0) * time, 0);
|
|
16
|
+
}
|
|
17
|
+
const durationMatchRules = [
|
|
18
|
+
[/(\d+)y/i, "years"],
|
|
19
|
+
[/(\d+)M/, "months"],
|
|
20
|
+
[/(\d+)d/i, "days"],
|
|
21
|
+
[/(\d+)h/i, "hours"],
|
|
22
|
+
[/(\d+)m/, "minutes"],
|
|
23
|
+
[/(\d+)s/, "seconds"]
|
|
24
|
+
];
|
|
25
|
+
function timeParse(duration) {
|
|
26
|
+
const result = {};
|
|
27
|
+
for (const [regex, key] of durationMatchRules) {
|
|
28
|
+
const match = duration.match(regex);
|
|
29
|
+
if (match) result[key] = Number(match[1]);
|
|
30
|
+
else result[key] = 0;
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
function _timeAbsolute(timeMs, maxPoint) {
|
|
35
|
+
const minPoint = "S";
|
|
36
|
+
const defines = [
|
|
37
|
+
["D", "days", _const.DATE_DAY_MS],
|
|
38
|
+
["h", "hours", _const.DATE_HOUR_MS],
|
|
39
|
+
["m", "minutes", _const.DATE_MINUTE_MS],
|
|
40
|
+
["s", "seconds", _const.DATE_SECOND_MS],
|
|
41
|
+
["S", "milliseconds", 1]
|
|
42
|
+
];
|
|
43
|
+
const minIndex = defines.findIndex((item) => item[0] === maxPoint);
|
|
44
|
+
const maxIndex = defines.findIndex((item) => item[0] === minPoint);
|
|
45
|
+
let timeMsFinal = timeMs;
|
|
46
|
+
const dao = {
|
|
47
|
+
years: 0,
|
|
48
|
+
months: 0,
|
|
49
|
+
days: 0,
|
|
50
|
+
hours: 0,
|
|
51
|
+
minutes: 0,
|
|
52
|
+
seconds: 0,
|
|
53
|
+
milliseconds: 0
|
|
54
|
+
};
|
|
55
|
+
for (let i = minIndex; i <= maxIndex; i++) {
|
|
56
|
+
const mode = defines[i];
|
|
57
|
+
const base = mode[2];
|
|
58
|
+
const value = Math.floor(timeMsFinal / base);
|
|
59
|
+
timeMsFinal = timeMsFinal - value * base;
|
|
60
|
+
dao[mode[1]] = value;
|
|
61
|
+
}
|
|
62
|
+
return dao;
|
|
63
|
+
}
|
|
64
|
+
function timeToDays(timeMs) {
|
|
65
|
+
return _timeAbsolute(timeMs, "D");
|
|
66
|
+
}
|
|
67
|
+
function timeToHours(timeMs) {
|
|
68
|
+
return _timeAbsolute(timeMs, "h");
|
|
69
|
+
}
|
|
70
|
+
function timeToMinutes(timeMs) {
|
|
71
|
+
return _timeAbsolute(timeMs, "m");
|
|
72
|
+
}
|
|
73
|
+
function timeToSeconds(timeMs) {
|
|
74
|
+
return _timeAbsolute(timeMs, "s");
|
|
75
|
+
}
|
|
76
|
+
exports.timeFrom = timeFrom;
|
|
77
|
+
exports.timeParse = timeParse;
|
|
78
|
+
exports.timeToDays = timeToDays;
|
|
79
|
+
exports.timeToHours = timeToHours;
|
|
80
|
+
exports.timeToMinutes = timeToMinutes;
|
|
81
|
+
exports.timeToSeconds = timeToSeconds;
|
|
82
|
+
//# sourceMappingURL=time.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.cjs","sources":["../src/time/from.ts","../src/time/to.ts"],"sourcesContent":["// @rer https://day.js.org/docs/en/durations/creating\n\nimport { DATE_DAY_MS, DATE_HOUR_MS, DATE_MINUTE_MS, DATE_MONTH_MS, DATE_SECOND_MS, DATE_YEAR_MS } from '@/date';\nimport { isString } from '@/type';\nimport type { TTimeDuration } from './to';\n\n/**\n * 时间转换规则数组\n * @type {Array<[RegExp, (match: RegExpMatchArray) => number]>}\n * @property {RegExp} 0 - 匹配时间单位正则表达式\n * @property {function} 1 - 将匹配结果转换为毫秒数的函数\n */\nconst rules: [key: keyof TTimeDuration, time: number][] = [\n ['years', DATE_YEAR_MS],\n ['months', DATE_MONTH_MS],\n ['days', DATE_DAY_MS],\n ['hours', DATE_HOUR_MS],\n ['minutes', DATE_MINUTE_MS],\n ['seconds', DATE_SECOND_MS],\n];\n\n/**\n * 将时间持续时间字符串或对象转换为毫秒数\n *\n * @param duration - 可以是时间持续时间字符串(如 '1d2h')或 TTimeDuration 对象\n * @returns 计算得到的总毫秒数\n */\nexport function timeFrom(duration: string | TTimeDuration) {\n const td = isString(duration) ? timeParse(duration) : duration;\n return rules.reduce((acc, [key, time]) => acc + (td[key] || 0) * time, 0);\n}\n\nconst durationMatchRules: [RegExp, key: keyof TTimeDuration][] = [\n [/(\\d+)y/i, 'years'],\n [/(\\d+)M/, 'months'],\n [/(\\d+)d/i, 'days'],\n [/(\\d+)h/i, 'hours'],\n [/(\\d+)m/, 'minutes'],\n [/(\\d+)s/, 'seconds'],\n];\n\n/**\n * 将时长字符串解析为时间对象\n * @param duration - 时长字符串(例如 \"1h30m\")\n * @returns 包含解析后时间单位的对象(小时、分钟等)\n */\nexport function timeParse(duration: string) {\n const result = {} as TTimeDuration;\n\n for (const [regex, key] of durationMatchRules) {\n const match = duration.match(regex);\n if (match) result[key] = Number(match[1]);\n else result[key] = 0;\n }\n\n return result;\n}\n","import { DATE_DAY_MS, DATE_HOUR_MS, DATE_MINUTE_MS, DATE_SECOND_MS } from '../date';\n\nexport type TTimeDuration = {\n years: number;\n months: number;\n /** 天数 */\n days: number;\n /** 小时数 */\n hours: number;\n /** 分钟数 */\n minutes: number;\n /** 秒数 */\n seconds: number;\n /** 毫秒数 */\n milliseconds: number;\n};\n\ntype _TTimeParsePoint = 'D' | 'h' | 'm' | 's' | 'S';\n\n/**\n * 解析时间毫秒数为绝对时间对象\n * @param timeMs 时间毫秒数\n * @param maxPoint 最大时间单位(决定分解的起始单位)\n * @returns 包含时间单位分解结果的对象\n * @example\n * ```typescript\n * // 默认以天为最大单位分解\n * timeInDay(123456789);\n * // { days: 1, hours: 10, minutes: 17, seconds: 36, milliseconds: 789 }\n *\n * // 指定最大单位为分钟,分解到分钟及以下单位\n * timeInMinute(123456789);\n * // { days: 0, hours: 0, minutes: 2057, seconds: 36, milliseconds: 789 }\n * ```\n */\nfunction _timeAbsolute(timeMs: number, maxPoint: _TTimeParsePoint): TTimeDuration {\n const minPoint: _TTimeParsePoint = 'S';\n\n const defines: [point: _TTimeParsePoint, key: keyof TTimeDuration, base: number][] = [\n ['D', 'days', DATE_DAY_MS],\n ['h', 'hours', DATE_HOUR_MS],\n ['m', 'minutes', DATE_MINUTE_MS],\n ['s', 'seconds', DATE_SECOND_MS],\n ['S', 'milliseconds', 1],\n ] as const;\n\n const minIndex = defines.findIndex((item) => item[0] === maxPoint);\n const maxIndex = defines.findIndex((item) => item[0] === minPoint);\n\n let timeMsFinal = timeMs;\n const dao: TTimeDuration = {\n years: 0,\n months: 0,\n days: 0,\n hours: 0,\n minutes: 0,\n seconds: 0,\n milliseconds: 0,\n };\n\n for (let i = minIndex; i <= maxIndex; i++) {\n const mode = defines[i];\n const base = mode[2];\n const value = Math.floor(timeMsFinal / base);\n timeMsFinal = timeMsFinal - value * base;\n dao[mode[1]] = value;\n }\n\n return dao;\n}\n\n/**\n * 将时间毫秒数解析为以天为最大单位的绝对时间对象\n * @param timeMs 时间毫秒数\n * @returns 包含天/小时/分钟/秒/毫秒分解结果的对象\n */\nexport function timeToDays(timeMs: number) {\n return _timeAbsolute(timeMs, 'D');\n}\n\n/**\n * 将时间毫秒数解析为以小时为最大单位的绝对时间对象\n * @param timeMs 时间毫秒数\n * @returns 包含小时/分钟/秒/毫秒分解结果的对象\n */\nexport function timeToHours(timeMs: number) {\n return _timeAbsolute(timeMs, 'h');\n}\n\n/**\n * 将时间毫秒数解析为以分钟为最大单位的绝对时间对象\n * @param timeMs 时间毫秒数\n * @returns 包含分钟/秒/毫秒分解结果的对象\n */\nexport function timeToMinutes(timeMs: number) {\n return _timeAbsolute(timeMs, 'm');\n}\n\n/**\n * 将时间毫秒数解析为以秒为最大单位的绝对时间对象\n * @param timeMs 时间毫秒数\n * @returns 包含秒/毫秒分解结果的对象\n */\nexport function timeToSeconds(timeMs: number) {\n return _timeAbsolute(timeMs, 's');\n}\n"],"names":["DATE_YEAR_MS","DATE_MONTH_MS","DATE_DAY_MS","DATE_HOUR_MS","DATE_MINUTE_MS","DATE_SECOND_MS","isString"],"mappings":";;;;AAYA,MAAM,QAAoD;AAAA,EACxD,CAAC,SAASA,OAAAA,YAAY;AAAA,EACtB,CAAC,UAAUC,OAAAA,aAAa;AAAA,EACxB,CAAC,QAAQC,OAAAA,WAAW;AAAA,EACpB,CAAC,SAASC,OAAAA,YAAY;AAAA,EACtB,CAAC,WAAWC,OAAAA,cAAc;AAAA,EAC1B,CAAC,WAAWC,OAAc,cAAA;AAC5B;AAQO,SAAS,SAAS,UAAkC;AACzD,QAAM,KAAKC,KAAAA,SAAS,QAAQ,IAAI,UAAU,QAAQ,IAAI;AACtD,SAAO,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,MAAM,OAAO,GAAG,GAAG,KAAK,KAAK,MAAM,CAAC;AAC1E;AAEA,MAAM,qBAA2D;AAAA,EAC/D,CAAC,WAAW,OAAO;AAAA,EACnB,CAAC,UAAU,QAAQ;AAAA,EACnB,CAAC,WAAW,MAAM;AAAA,EAClB,CAAC,WAAW,OAAO;AAAA,EACnB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,UAAU,SAAS;AACtB;AAOO,SAAS,UAAU,UAAkB;AAC1C,QAAM,SAAS,CAAC;AAEhB,aAAW,CAAC,OAAO,GAAG,KAAK,oBAAoB;AACvC,UAAA,QAAQ,SAAS,MAAM,KAAK;AAClC,QAAI,MAAc,QAAA,GAAG,IAAI,OAAO,MAAM,CAAC,CAAC;AAAA,QACnC,QAAO,GAAG,IAAI;AAAA,EAAA;AAGd,SAAA;AACT;ACrBA,SAAS,cAAc,QAAgB,UAA2C;AAChF,QAAM,WAA6B;AAEnC,QAAM,UAA+E;AAAA,IACnF,CAAC,KAAK,QAAQJ,kBAAW;AAAA,IACzB,CAAC,KAAK,SAASC,mBAAY;AAAA,IAC3B,CAAC,KAAK,WAAWC,qBAAc;AAAA,IAC/B,CAAC,KAAK,WAAWC,qBAAc;AAAA,IAC/B,CAAC,KAAK,gBAAgB,CAAC;AAAA,EACzB;AAEM,QAAA,WAAW,QAAQ,UAAU,CAAC,SAAS,KAAK,CAAC,MAAM,QAAQ;AAC3D,QAAA,WAAW,QAAQ,UAAU,CAAC,SAAS,KAAK,CAAC,MAAM,QAAQ;AAEjE,MAAI,cAAc;AAClB,QAAM,MAAqB;AAAA,IACzB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,cAAc;AAAA,EAChB;AAEA,WAAS,IAAI,UAAU,KAAK,UAAU,KAAK;AACnC,UAAA,OAAO,QAAQ,CAAC;AAChB,UAAA,OAAO,KAAK,CAAC;AACnB,UAAM,QAAQ,KAAK,MAAM,cAAc,IAAI;AAC3C,kBAAc,cAAc,QAAQ;AAChC,QAAA,KAAK,CAAC,CAAC,IAAI;AAAA,EAAA;AAGV,SAAA;AACT;AAOO,SAAS,WAAW,QAAgB;AAClC,SAAA,cAAc,QAAQ,GAAG;AAClC;AAOO,SAAS,YAAY,QAAgB;AACnC,SAAA,cAAc,QAAQ,GAAG;AAClC;AAOO,SAAS,cAAc,QAAgB;AACrC,SAAA,cAAc,QAAQ,GAAG;AAClC;AAOO,SAAS,cAAc,QAAgB;AACrC,SAAA,cAAc,QAAQ,GAAG;AAClC;;;;;;;"}
|
package/dist/time.d.ts
ADDED
package/dist/time.mjs
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { D as DATE_YEAR_MS, a as DATE_MONTH_MS, b as DATE_DAY_MS, c as DATE_HOUR_MS, d as DATE_MINUTE_MS, e as DATE_SECOND_MS } from "./const.mjs";
|
|
2
|
+
import { isString } from "./type.mjs";
|
|
3
|
+
const rules = [
|
|
4
|
+
["years", DATE_YEAR_MS],
|
|
5
|
+
["months", DATE_MONTH_MS],
|
|
6
|
+
["days", DATE_DAY_MS],
|
|
7
|
+
["hours", DATE_HOUR_MS],
|
|
8
|
+
["minutes", DATE_MINUTE_MS],
|
|
9
|
+
["seconds", DATE_SECOND_MS]
|
|
10
|
+
];
|
|
11
|
+
function timeFrom(duration) {
|
|
12
|
+
const td = isString(duration) ? timeParse(duration) : duration;
|
|
13
|
+
return rules.reduce((acc, [key, time]) => acc + (td[key] || 0) * time, 0);
|
|
14
|
+
}
|
|
15
|
+
const durationMatchRules = [
|
|
16
|
+
[/(\d+)y/i, "years"],
|
|
17
|
+
[/(\d+)M/, "months"],
|
|
18
|
+
[/(\d+)d/i, "days"],
|
|
19
|
+
[/(\d+)h/i, "hours"],
|
|
20
|
+
[/(\d+)m/, "minutes"],
|
|
21
|
+
[/(\d+)s/, "seconds"]
|
|
22
|
+
];
|
|
23
|
+
function timeParse(duration) {
|
|
24
|
+
const result = {};
|
|
25
|
+
for (const [regex, key] of durationMatchRules) {
|
|
26
|
+
const match = duration.match(regex);
|
|
27
|
+
if (match) result[key] = Number(match[1]);
|
|
28
|
+
else result[key] = 0;
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
function _timeAbsolute(timeMs, maxPoint) {
|
|
33
|
+
const minPoint = "S";
|
|
34
|
+
const defines = [
|
|
35
|
+
["D", "days", DATE_DAY_MS],
|
|
36
|
+
["h", "hours", DATE_HOUR_MS],
|
|
37
|
+
["m", "minutes", DATE_MINUTE_MS],
|
|
38
|
+
["s", "seconds", DATE_SECOND_MS],
|
|
39
|
+
["S", "milliseconds", 1]
|
|
40
|
+
];
|
|
41
|
+
const minIndex = defines.findIndex((item) => item[0] === maxPoint);
|
|
42
|
+
const maxIndex = defines.findIndex((item) => item[0] === minPoint);
|
|
43
|
+
let timeMsFinal = timeMs;
|
|
44
|
+
const dao = {
|
|
45
|
+
years: 0,
|
|
46
|
+
months: 0,
|
|
47
|
+
days: 0,
|
|
48
|
+
hours: 0,
|
|
49
|
+
minutes: 0,
|
|
50
|
+
seconds: 0,
|
|
51
|
+
milliseconds: 0
|
|
52
|
+
};
|
|
53
|
+
for (let i = minIndex; i <= maxIndex; i++) {
|
|
54
|
+
const mode = defines[i];
|
|
55
|
+
const base = mode[2];
|
|
56
|
+
const value = Math.floor(timeMsFinal / base);
|
|
57
|
+
timeMsFinal = timeMsFinal - value * base;
|
|
58
|
+
dao[mode[1]] = value;
|
|
59
|
+
}
|
|
60
|
+
return dao;
|
|
61
|
+
}
|
|
62
|
+
function timeToDays(timeMs) {
|
|
63
|
+
return _timeAbsolute(timeMs, "D");
|
|
64
|
+
}
|
|
65
|
+
function timeToHours(timeMs) {
|
|
66
|
+
return _timeAbsolute(timeMs, "h");
|
|
67
|
+
}
|
|
68
|
+
function timeToMinutes(timeMs) {
|
|
69
|
+
return _timeAbsolute(timeMs, "m");
|
|
70
|
+
}
|
|
71
|
+
function timeToSeconds(timeMs) {
|
|
72
|
+
return _timeAbsolute(timeMs, "s");
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
timeFrom,
|
|
76
|
+
timeParse,
|
|
77
|
+
timeToDays,
|
|
78
|
+
timeToHours,
|
|
79
|
+
timeToMinutes,
|
|
80
|
+
timeToSeconds
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=time.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.mjs","sources":["../src/time/from.ts","../src/time/to.ts"],"sourcesContent":["// @rer https://day.js.org/docs/en/durations/creating\n\nimport { DATE_DAY_MS, DATE_HOUR_MS, DATE_MINUTE_MS, DATE_MONTH_MS, DATE_SECOND_MS, DATE_YEAR_MS } from '@/date';\nimport { isString } from '@/type';\nimport type { TTimeDuration } from './to';\n\n/**\n * 时间转换规则数组\n * @type {Array<[RegExp, (match: RegExpMatchArray) => number]>}\n * @property {RegExp} 0 - 匹配时间单位正则表达式\n * @property {function} 1 - 将匹配结果转换为毫秒数的函数\n */\nconst rules: [key: keyof TTimeDuration, time: number][] = [\n ['years', DATE_YEAR_MS],\n ['months', DATE_MONTH_MS],\n ['days', DATE_DAY_MS],\n ['hours', DATE_HOUR_MS],\n ['minutes', DATE_MINUTE_MS],\n ['seconds', DATE_SECOND_MS],\n];\n\n/**\n * 将时间持续时间字符串或对象转换为毫秒数\n *\n * @param duration - 可以是时间持续时间字符串(如 '1d2h')或 TTimeDuration 对象\n * @returns 计算得到的总毫秒数\n */\nexport function timeFrom(duration: string | TTimeDuration) {\n const td = isString(duration) ? timeParse(duration) : duration;\n return rules.reduce((acc, [key, time]) => acc + (td[key] || 0) * time, 0);\n}\n\nconst durationMatchRules: [RegExp, key: keyof TTimeDuration][] = [\n [/(\\d+)y/i, 'years'],\n [/(\\d+)M/, 'months'],\n [/(\\d+)d/i, 'days'],\n [/(\\d+)h/i, 'hours'],\n [/(\\d+)m/, 'minutes'],\n [/(\\d+)s/, 'seconds'],\n];\n\n/**\n * 将时长字符串解析为时间对象\n * @param duration - 时长字符串(例如 \"1h30m\")\n * @returns 包含解析后时间单位的对象(小时、分钟等)\n */\nexport function timeParse(duration: string) {\n const result = {} as TTimeDuration;\n\n for (const [regex, key] of durationMatchRules) {\n const match = duration.match(regex);\n if (match) result[key] = Number(match[1]);\n else result[key] = 0;\n }\n\n return result;\n}\n","import { DATE_DAY_MS, DATE_HOUR_MS, DATE_MINUTE_MS, DATE_SECOND_MS } from '../date';\n\nexport type TTimeDuration = {\n years: number;\n months: number;\n /** 天数 */\n days: number;\n /** 小时数 */\n hours: number;\n /** 分钟数 */\n minutes: number;\n /** 秒数 */\n seconds: number;\n /** 毫秒数 */\n milliseconds: number;\n};\n\ntype _TTimeParsePoint = 'D' | 'h' | 'm' | 's' | 'S';\n\n/**\n * 解析时间毫秒数为绝对时间对象\n * @param timeMs 时间毫秒数\n * @param maxPoint 最大时间单位(决定分解的起始单位)\n * @returns 包含时间单位分解结果的对象\n * @example\n * ```typescript\n * // 默认以天为最大单位分解\n * timeInDay(123456789);\n * // { days: 1, hours: 10, minutes: 17, seconds: 36, milliseconds: 789 }\n *\n * // 指定最大单位为分钟,分解到分钟及以下单位\n * timeInMinute(123456789);\n * // { days: 0, hours: 0, minutes: 2057, seconds: 36, milliseconds: 789 }\n * ```\n */\nfunction _timeAbsolute(timeMs: number, maxPoint: _TTimeParsePoint): TTimeDuration {\n const minPoint: _TTimeParsePoint = 'S';\n\n const defines: [point: _TTimeParsePoint, key: keyof TTimeDuration, base: number][] = [\n ['D', 'days', DATE_DAY_MS],\n ['h', 'hours', DATE_HOUR_MS],\n ['m', 'minutes', DATE_MINUTE_MS],\n ['s', 'seconds', DATE_SECOND_MS],\n ['S', 'milliseconds', 1],\n ] as const;\n\n const minIndex = defines.findIndex((item) => item[0] === maxPoint);\n const maxIndex = defines.findIndex((item) => item[0] === minPoint);\n\n let timeMsFinal = timeMs;\n const dao: TTimeDuration = {\n years: 0,\n months: 0,\n days: 0,\n hours: 0,\n minutes: 0,\n seconds: 0,\n milliseconds: 0,\n };\n\n for (let i = minIndex; i <= maxIndex; i++) {\n const mode = defines[i];\n const base = mode[2];\n const value = Math.floor(timeMsFinal / base);\n timeMsFinal = timeMsFinal - value * base;\n dao[mode[1]] = value;\n }\n\n return dao;\n}\n\n/**\n * 将时间毫秒数解析为以天为最大单位的绝对时间对象\n * @param timeMs 时间毫秒数\n * @returns 包含天/小时/分钟/秒/毫秒分解结果的对象\n */\nexport function timeToDays(timeMs: number) {\n return _timeAbsolute(timeMs, 'D');\n}\n\n/**\n * 将时间毫秒数解析为以小时为最大单位的绝对时间对象\n * @param timeMs 时间毫秒数\n * @returns 包含小时/分钟/秒/毫秒分解结果的对象\n */\nexport function timeToHours(timeMs: number) {\n return _timeAbsolute(timeMs, 'h');\n}\n\n/**\n * 将时间毫秒数解析为以分钟为最大单位的绝对时间对象\n * @param timeMs 时间毫秒数\n * @returns 包含分钟/秒/毫秒分解结果的对象\n */\nexport function timeToMinutes(timeMs: number) {\n return _timeAbsolute(timeMs, 'm');\n}\n\n/**\n * 将时间毫秒数解析为以秒为最大单位的绝对时间对象\n * @param timeMs 时间毫秒数\n * @returns 包含秒/毫秒分解结果的对象\n */\nexport function timeToSeconds(timeMs: number) {\n return _timeAbsolute(timeMs, 's');\n}\n"],"names":[],"mappings":";;AAYA,MAAM,QAAoD;AAAA,EACxD,CAAC,SAAS,YAAY;AAAA,EACtB,CAAC,UAAU,aAAa;AAAA,EACxB,CAAC,QAAQ,WAAW;AAAA,EACpB,CAAC,SAAS,YAAY;AAAA,EACtB,CAAC,WAAW,cAAc;AAAA,EAC1B,CAAC,WAAW,cAAc;AAC5B;AAQO,SAAS,SAAS,UAAkC;AACzD,QAAM,KAAK,SAAS,QAAQ,IAAI,UAAU,QAAQ,IAAI;AACtD,SAAO,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,MAAM,OAAO,GAAG,GAAG,KAAK,KAAK,MAAM,CAAC;AAC1E;AAEA,MAAM,qBAA2D;AAAA,EAC/D,CAAC,WAAW,OAAO;AAAA,EACnB,CAAC,UAAU,QAAQ;AAAA,EACnB,CAAC,WAAW,MAAM;AAAA,EAClB,CAAC,WAAW,OAAO;AAAA,EACnB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,UAAU,SAAS;AACtB;AAOO,SAAS,UAAU,UAAkB;AAC1C,QAAM,SAAS,CAAC;AAEhB,aAAW,CAAC,OAAO,GAAG,KAAK,oBAAoB;AACvC,UAAA,QAAQ,SAAS,MAAM,KAAK;AAClC,QAAI,MAAc,QAAA,GAAG,IAAI,OAAO,MAAM,CAAC,CAAC;AAAA,QACnC,QAAO,GAAG,IAAI;AAAA,EAAA;AAGd,SAAA;AACT;ACrBA,SAAS,cAAc,QAAgB,UAA2C;AAChF,QAAM,WAA6B;AAEnC,QAAM,UAA+E;AAAA,IACnF,CAAC,KAAK,QAAQ,WAAW;AAAA,IACzB,CAAC,KAAK,SAAS,YAAY;AAAA,IAC3B,CAAC,KAAK,WAAW,cAAc;AAAA,IAC/B,CAAC,KAAK,WAAW,cAAc;AAAA,IAC/B,CAAC,KAAK,gBAAgB,CAAC;AAAA,EACzB;AAEM,QAAA,WAAW,QAAQ,UAAU,CAAC,SAAS,KAAK,CAAC,MAAM,QAAQ;AAC3D,QAAA,WAAW,QAAQ,UAAU,CAAC,SAAS,KAAK,CAAC,MAAM,QAAQ;AAEjE,MAAI,cAAc;AAClB,QAAM,MAAqB;AAAA,IACzB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,cAAc;AAAA,EAChB;AAEA,WAAS,IAAI,UAAU,KAAK,UAAU,KAAK;AACnC,UAAA,OAAO,QAAQ,CAAC;AAChB,UAAA,OAAO,KAAK,CAAC;AACnB,UAAM,QAAQ,KAAK,MAAM,cAAc,IAAI;AAC3C,kBAAc,cAAc,QAAQ;AAChC,QAAA,KAAK,CAAC,CAAC,IAAI;AAAA,EAAA;AAGV,SAAA;AACT;AAOO,SAAS,WAAW,QAAgB;AAClC,SAAA,cAAc,QAAQ,GAAG;AAClC;AAOO,SAAS,YAAY,QAAgB;AACnC,SAAA,cAAc,QAAQ,GAAG;AAClC;AAOO,SAAS,cAAc,QAAgB;AACrC,SAAA,cAAc,QAAQ,GAAG;AAClC;AAOO,SAAS,cAAc,QAAgB;AACrC,SAAA,cAAc,QAAQ,GAAG;AAClC;"}
|
package/dist/timer.cjs
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const STATUS_READY = 0;
|
|
4
|
+
const STATUS_START = 1;
|
|
5
|
+
const STATUS_PAUSE = 2;
|
|
6
|
+
const STATUS_STOP = 3;
|
|
7
|
+
function makeInterval(nextTime, effect) {
|
|
8
|
+
let startAt = 0;
|
|
9
|
+
let lastAt = 0;
|
|
10
|
+
let stopAt = 0;
|
|
11
|
+
let pauseAt = 0;
|
|
12
|
+
let resumeAt = 0;
|
|
13
|
+
let times = 0;
|
|
14
|
+
let status = STATUS_READY;
|
|
15
|
+
let runningTime = 0;
|
|
16
|
+
const execute = () => {
|
|
17
|
+
if (status >= STATUS_PAUSE) return;
|
|
18
|
+
const now = Date.now();
|
|
19
|
+
const intervalTime = lastAt > 0 ? now - lastAt : 0;
|
|
20
|
+
runningTime += intervalTime;
|
|
21
|
+
lastAt = now;
|
|
22
|
+
const state = {
|
|
23
|
+
times: ++times,
|
|
24
|
+
startAt,
|
|
25
|
+
stopAt,
|
|
26
|
+
pauseAt,
|
|
27
|
+
resumeAt,
|
|
28
|
+
currentAt: now,
|
|
29
|
+
elapsedTime: startAt > 0 ? now - startAt : 0,
|
|
30
|
+
runningTime,
|
|
31
|
+
intervalTime
|
|
32
|
+
};
|
|
33
|
+
if (effect.length === 2) {
|
|
34
|
+
effect(state, () => {
|
|
35
|
+
nextTime(execute);
|
|
36
|
+
});
|
|
37
|
+
} else {
|
|
38
|
+
effect(state);
|
|
39
|
+
nextTime(execute);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const canStart = () => status === STATUS_READY;
|
|
43
|
+
const start = () => {
|
|
44
|
+
if (!canStart()) return;
|
|
45
|
+
status = STATUS_START;
|
|
46
|
+
startAt = Date.now();
|
|
47
|
+
execute();
|
|
48
|
+
};
|
|
49
|
+
const canStop = () => status === STATUS_START;
|
|
50
|
+
const stop = () => {
|
|
51
|
+
if (!canStop()) return;
|
|
52
|
+
status = STATUS_STOP;
|
|
53
|
+
stopAt = Date.now();
|
|
54
|
+
};
|
|
55
|
+
const canPause = () => status === STATUS_START;
|
|
56
|
+
const pause = () => {
|
|
57
|
+
if (!canPause()) return;
|
|
58
|
+
status = STATUS_PAUSE;
|
|
59
|
+
pauseAt = Date.now();
|
|
60
|
+
};
|
|
61
|
+
const canResume = () => status === STATUS_PAUSE;
|
|
62
|
+
const resume = () => {
|
|
63
|
+
if (!canResume()) return;
|
|
64
|
+
status = STATUS_START;
|
|
65
|
+
resumeAt = Date.now();
|
|
66
|
+
lastAt = resumeAt;
|
|
67
|
+
execute();
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
canStart,
|
|
71
|
+
canStop,
|
|
72
|
+
canPause,
|
|
73
|
+
canResume,
|
|
74
|
+
start,
|
|
75
|
+
stop,
|
|
76
|
+
pause,
|
|
77
|
+
resume,
|
|
78
|
+
execute
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function timeInterval(callback, interval, options) {
|
|
82
|
+
let timeId;
|
|
83
|
+
const { canStart, canStop, canPause, canResume, start, stop, pause, resume, execute } = makeInterval((call) => {
|
|
84
|
+
timeId = setTimeout(call, interval);
|
|
85
|
+
}, callback);
|
|
86
|
+
return {
|
|
87
|
+
start() {
|
|
88
|
+
if (!canStart()) return;
|
|
89
|
+
if (options == null ? void 0 : options.leading) {
|
|
90
|
+
start();
|
|
91
|
+
} else {
|
|
92
|
+
timeId = setTimeout(start, interval);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
stop() {
|
|
96
|
+
if (!canStop()) return;
|
|
97
|
+
if (options == null ? void 0 : options.trailing) execute();
|
|
98
|
+
clearTimeout(timeId);
|
|
99
|
+
stop();
|
|
100
|
+
},
|
|
101
|
+
pause() {
|
|
102
|
+
if (!canPause()) return;
|
|
103
|
+
if (options == null ? void 0 : options.trailing) execute();
|
|
104
|
+
clearTimeout(timeId);
|
|
105
|
+
pause();
|
|
106
|
+
},
|
|
107
|
+
resume(immediate) {
|
|
108
|
+
if (!canResume()) return;
|
|
109
|
+
if (immediate || (options == null ? void 0 : options.leading)) {
|
|
110
|
+
resume();
|
|
111
|
+
} else {
|
|
112
|
+
timeId = setTimeout(resume, interval);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
exports.makeInterval = makeInterval;
|
|
118
|
+
exports.timeInterval = timeInterval;
|
|
119
|
+
//# sourceMappingURL=timer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timer.cjs","sources":["../src/timer.ts"],"sourcesContent":["/**\n * 定时器状态接口\n */\nexport type TTimerState = {\n /**\n * 执行次数\n */\n times: number;\n /**\n * 开始时间戳\n */\n startAt: number;\n /**\n * 停止时间戳\n */\n stopAt: number;\n /**\n * 暂停时间戳\n */\n pauseAt: number;\n /**\n * 恢复时间戳\n */\n resumeAt: number;\n /**\n * 当前时间戳\n */\n currentAt: number;\n /**\n * 总耗时(包括暂停时间)\n */\n elapsedTime: number;\n /**\n * 实际运行时间(不包括暂停时间)\n */\n runningTime: number;\n /**\n * 当前间隔时间\n */\n intervalTime: number;\n};\n\nexport type TTimerHandler = {\n /**\n * 开始\n */\n start: () => void;\n /**\n * 暂停\n */\n pause: () => void;\n /**\n * 恢复\n */\n resume: (immediate?: boolean) => void;\n /**\n * 停止\n */\n stop: () => void;\n};\n\nconst STATUS_READY = 0;\nconst STATUS_START = 1;\nconst STATUS_PAUSE = 2;\nconst STATUS_STOP = 3;\n\n/**\n * 创建间隔定时器核心函数\n *\n * @param nextTime - 用于安排下一次执行的函数\n * @param effect - 每次执行的回调函数,接收定时器状态和可选的next函数\n * @returns 返回包含控制方法的对象\n */\nexport function makeInterval(\n nextTime: (call: () => void) => void,\n effect: (timer: TTimerState, next?: () => void) => unknown,\n) {\n let startAt = 0;\n let lastAt = 0;\n let stopAt = 0;\n let pauseAt = 0;\n let resumeAt = 0;\n let times = 0;\n let status = STATUS_READY;\n let runningTime = 0;\n\n const execute = () => {\n if (status >= STATUS_PAUSE) return;\n\n const now = Date.now();\n const intervalTime = lastAt > 0 ? now - lastAt : 0;\n runningTime += intervalTime;\n lastAt = now;\n const state: TTimerState = {\n times: ++times,\n startAt,\n stopAt,\n pauseAt,\n resumeAt,\n currentAt: now,\n elapsedTime: startAt > 0 ? now - startAt : 0,\n runningTime,\n intervalTime,\n };\n\n if (effect.length === 2) {\n effect(state, () => {\n nextTime(execute);\n });\n } else {\n effect(state);\n nextTime(execute);\n }\n };\n\n const canStart = () => status === STATUS_READY;\n const start = () => {\n if (!canStart()) return;\n status = STATUS_START;\n startAt = Date.now();\n execute();\n };\n\n const canStop = () => status === STATUS_START;\n const stop = () => {\n if (!canStop()) return;\n status = STATUS_STOP;\n stopAt = Date.now();\n };\n\n const canPause = () => status === STATUS_START;\n const pause = () => {\n if (!canPause()) return;\n status = STATUS_PAUSE;\n pauseAt = Date.now();\n };\n\n const canResume = () => status === STATUS_PAUSE;\n const resume = () => {\n if (!canResume()) return;\n status = STATUS_START;\n resumeAt = Date.now();\n lastAt = resumeAt;\n execute();\n };\n\n return {\n canStart,\n canStop,\n canPause,\n canResume,\n start,\n stop,\n pause,\n resume,\n execute,\n };\n}\n\nexport type TTimerOptions = {\n /**\n * 是否在定时器开始时立即执行回调\n */\n leading?: boolean;\n /**\n * 是否在定时器停止时执行最后一次回调\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个基于 `setTimeout` 的间隔定时器\n *\n * @param callback - 每次间隔执行的回调函数,接收定时器状态和可选的 `next` 函数\n * @param interval - 间隔时间,单位为毫秒\n * @param options - 配置选项\n * @returns {TTimerHandler}\n */\nexport function timeInterval(\n callback: (state: TTimerState, next?: () => void) => unknown,\n interval: number,\n options?: TTimerOptions,\n): TTimerHandler {\n let timeId: number | NodeJS.Timeout;\n const { canStart, canStop, canPause, canResume, start, stop, pause, resume, execute } = makeInterval((call) => {\n timeId = setTimeout(call, interval);\n }, callback);\n\n return {\n start() {\n if (!canStart()) return;\n\n if (options?.leading) {\n start();\n } else {\n timeId = setTimeout(start, interval);\n }\n },\n\n stop() {\n if (!canStop()) return;\n if (options?.trailing) execute();\n\n clearTimeout(timeId);\n stop();\n },\n\n pause() {\n if (!canPause()) return;\n if (options?.trailing) execute();\n\n clearTimeout(timeId);\n pause();\n },\n\n resume(immediate?: boolean) {\n if (!canResume()) return;\n\n if (immediate || options?.leading) {\n resume();\n } else {\n timeId = setTimeout(resume, interval);\n }\n },\n };\n}\n"],"names":[],"mappings":";;AA6DA,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,cAAc;AASJ,SAAA,aACd,UACA,QACA;AACA,MAAI,UAAU;AACd,MAAI,SAAS;AACb,MAAI,SAAS;AACb,MAAI,UAAU;AACd,MAAI,WAAW;AACf,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,MAAI,cAAc;AAElB,QAAM,UAAU,MAAM;AACpB,QAAI,UAAU,aAAc;AAEtB,UAAA,MAAM,KAAK,IAAI;AACrB,UAAM,eAAe,SAAS,IAAI,MAAM,SAAS;AAClC,mBAAA;AACN,aAAA;AACT,UAAM,QAAqB;AAAA,MACzB,OAAO,EAAE;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,aAAa,UAAU,IAAI,MAAM,UAAU;AAAA,MAC3C;AAAA,MACA;AAAA,IACF;AAEI,QAAA,OAAO,WAAW,GAAG;AACvB,aAAO,OAAO,MAAM;AAClB,iBAAS,OAAO;AAAA,MAAA,CACjB;AAAA,IAAA,OACI;AACL,aAAO,KAAK;AACZ,eAAS,OAAO;AAAA,IAAA;AAAA,EAEpB;AAEM,QAAA,WAAW,MAAM,WAAW;AAClC,QAAM,QAAQ,MAAM;AACd,QAAA,CAAC,WAAY;AACR,aAAA;AACT,cAAU,KAAK,IAAI;AACX,YAAA;AAAA,EACV;AAEM,QAAA,UAAU,MAAM,WAAW;AACjC,QAAM,OAAO,MAAM;AACb,QAAA,CAAC,UAAW;AACP,aAAA;AACT,aAAS,KAAK,IAAI;AAAA,EACpB;AAEM,QAAA,WAAW,MAAM,WAAW;AAClC,QAAM,QAAQ,MAAM;AACd,QAAA,CAAC,WAAY;AACR,aAAA;AACT,cAAU,KAAK,IAAI;AAAA,EACrB;AAEM,QAAA,YAAY,MAAM,WAAW;AACnC,QAAM,SAAS,MAAM;AACf,QAAA,CAAC,YAAa;AACT,aAAA;AACT,eAAW,KAAK,IAAI;AACX,aAAA;AACD,YAAA;AAAA,EACV;AAEO,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAqBgB,SAAA,aACd,UACA,UACA,SACe;AACX,MAAA;AACJ,QAAM,EAAE,UAAU,SAAS,UAAU,WAAW,OAAO,MAAM,OAAO,QAAQ,QAAY,IAAA,aAAa,CAAC,SAAS;AACpG,aAAA,WAAW,MAAM,QAAQ;AAAA,KACjC,QAAQ;AAEJ,SAAA;AAAA,IACL,QAAQ;AACF,UAAA,CAAC,WAAY;AAEjB,UAAI,mCAAS,SAAS;AACd,cAAA;AAAA,MAAA,OACD;AACI,iBAAA,WAAW,OAAO,QAAQ;AAAA,MAAA;AAAA,IAEvC;AAAA,IAEA,OAAO;AACD,UAAA,CAAC,UAAW;AACZ,UAAA,mCAAS,SAAkB,SAAA;AAE/B,mBAAa,MAAM;AACd,WAAA;AAAA,IACP;AAAA,IAEA,QAAQ;AACF,UAAA,CAAC,WAAY;AACb,UAAA,mCAAS,SAAkB,SAAA;AAE/B,mBAAa,MAAM;AACb,YAAA;AAAA,IACR;AAAA,IAEA,OAAO,WAAqB;AACtB,UAAA,CAAC,YAAa;AAEd,UAAA,cAAa,mCAAS,UAAS;AAC1B,eAAA;AAAA,MAAA,OACF;AACI,iBAAA,WAAW,QAAQ,QAAQ;AAAA,MAAA;AAAA,IACtC;AAAA,EAEJ;AACF;;;"}
|