@base-web-kits/base-tools-ts 0.9.5 → 0.9.8
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/base-tools-ts.umd.global.js +2 -1
- package/dist/base-tools-ts.umd.global.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/package.json +9 -17
- package/src/ts/array/index.ts +13 -0
- package/src/ts/async/index.ts +20 -0
- package/src/ts/bean/EventBus.ts +61 -0
- package/src/ts/bean/index.ts +1 -0
- package/src/ts/day/index.ts +184 -0
- package/src/ts/index.ts +14 -0
- package/src/ts/lodash/index.ts +7 -0
- package/src/ts/number/big.ts +192 -0
- package/src/ts/number/format.ts +253 -0
- package/src/ts/number/index.ts +3 -0
- package/src/ts/number/random.ts +65 -0
- package/src/ts/object/index.ts +12 -0
- package/src/ts/string/format.ts +52 -0
- package/src/ts/string/index.ts +3 -0
- package/src/ts/string/other.ts +33 -0
- package/src/ts/string/random.ts +42 -0
- package/src/ts/typing/index.ts +161 -0
- package/src/ts/url/file/index.ts +57 -0
- package/src/ts/url/index.ts +4 -0
- package/src/ts/url/oss/index.d.ts +120 -0
- package/src/ts/url/oss/index.ts +168 -0
- package/src/ts/url/param/index.ts +119 -0
- package/src/ts/url/qn/index.d.ts +103 -0
- package/src/ts/url/qn/index.ts +237 -0
- package/src/ts/validator/index.ts +601 -0
- package/base-tools-ts.umd.global.js +0 -10619
- package/index.cjs +0 -2
- package/index.d.ts +0 -1
- package/index.js +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@base-web-kits/base-tools-ts",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.8",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"description": "Independent TS utilities package built from src/ts.",
|
|
6
6
|
"keywords": [
|
|
@@ -10,26 +10,18 @@
|
|
|
10
10
|
"thin-wrapper"
|
|
11
11
|
],
|
|
12
12
|
"license": "MIT",
|
|
13
|
-
"main": "./index.cjs",
|
|
14
|
-
"module": "./index.js",
|
|
15
|
-
"types": "./index.d.ts",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"index": [
|
|
22
|
-
"./dist/index.d.ts"
|
|
23
|
-
]
|
|
13
|
+
"main": "./dist/index.cjs",
|
|
14
|
+
"module": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"require": "./dist/index.cjs"
|
|
24
21
|
}
|
|
25
22
|
},
|
|
26
23
|
"files": [
|
|
27
24
|
"dist",
|
|
28
|
-
"index.d.ts",
|
|
29
|
-
"index.js",
|
|
30
|
-
"index.cjs",
|
|
31
|
-
"base-tools-ts.umd.global.js",
|
|
32
|
-
"base-tools-ts.umd.global.js.map",
|
|
33
25
|
"README.md",
|
|
34
26
|
"src"
|
|
35
27
|
],
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 拖拽排序 (不改变原数组)
|
|
3
|
+
* @param list 原始数组
|
|
4
|
+
* @param fromIndex 要移动的元素的原始索引
|
|
5
|
+
* @param toIndex 要移动到的目标索引
|
|
6
|
+
* @returns 移动元素后的新数组
|
|
7
|
+
*/
|
|
8
|
+
export function arrayMove<T>(list: T[], fromIndex: number, toIndex: number) {
|
|
9
|
+
const newList = [...list]; // 创建新数组副本
|
|
10
|
+
const [removed] = newList.splice(fromIndex, 1); // 移除 fromIndex 处的元素
|
|
11
|
+
newList.splice(toIndex, 0, removed); // 插入到 toIndex 处
|
|
12
|
+
return newList;
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 将 Promise 包装为 [data, error] 形式, 减少 try-catch 代码量
|
|
3
|
+
* @param p 要包装的 Promise
|
|
4
|
+
* @returns 一个 Promise,其结果为 [data, error] 形式
|
|
5
|
+
* @example
|
|
6
|
+
* const [data, err] = await toAsync(fetch('https://api.example.com/data'));
|
|
7
|
+
* if (err) {
|
|
8
|
+
* console.error(err);
|
|
9
|
+
* return;
|
|
10
|
+
* }
|
|
11
|
+
* console.log(data);
|
|
12
|
+
*/
|
|
13
|
+
export async function toAsync<T>(p: Promise<T>): Promise<[T | null, unknown]> {
|
|
14
|
+
try {
|
|
15
|
+
const data = await p;
|
|
16
|
+
return [data, null];
|
|
17
|
+
} catch (err) {
|
|
18
|
+
return [null, err];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import mitt, { type Emitter, type EventType } from 'mitt';
|
|
2
|
+
|
|
3
|
+
type Events = Record<EventType, unknown>;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 总线式发布订阅
|
|
7
|
+
* @example
|
|
8
|
+
* const emitter = new EventBus(); // 支持链式调用
|
|
9
|
+
* emitter.on('xx', fn); // 订阅事件 xx
|
|
10
|
+
* emitter.once('xx', fn); // 订阅事件 xx 一次
|
|
11
|
+
* emitter.emit('xx', any); // 发布事件 xx,参数任意
|
|
12
|
+
* emitter.off('xx'); // 移除事件 xx 下全部监听
|
|
13
|
+
* emitter.off('xx', fn); // 移除事件 xx 下指定监听
|
|
14
|
+
* emitter.clear(); // 移除所有事件
|
|
15
|
+
*
|
|
16
|
+
* @example 类型约束
|
|
17
|
+
* type T = { a: number; b: string };
|
|
18
|
+
* const emitter = new EventBus<{ xx: T; yy: void }>();
|
|
19
|
+
* const fn = (arg: T) => {}
|
|
20
|
+
* emitter.on('xx', fn);
|
|
21
|
+
* emitter.off('xx', fn);
|
|
22
|
+
* emitter.emit('xx', { a: 123, b: '123' });
|
|
23
|
+
* emitter.emit('yy');
|
|
24
|
+
*/
|
|
25
|
+
export class EventBus<T extends Events = Events> {
|
|
26
|
+
private readonly _emitter: Emitter<T> = mitt<T>();
|
|
27
|
+
|
|
28
|
+
/** 订阅 */
|
|
29
|
+
on<K extends keyof T>(type: K, fn: (event: T[K]) => void): this {
|
|
30
|
+
this._emitter.on(type, fn);
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** 订阅一次 */
|
|
35
|
+
once<K extends keyof T>(type: K, fn: (event: T[K]) => void): this {
|
|
36
|
+
const wrap = (event: T[K]) => {
|
|
37
|
+
this._emitter.off(type, wrap);
|
|
38
|
+
fn(event);
|
|
39
|
+
};
|
|
40
|
+
this._emitter.on(type, wrap);
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 发布 */
|
|
45
|
+
emit<K extends keyof T>(type: K, event?: T[K]): this {
|
|
46
|
+
this._emitter.emit(type, event as T[K]);
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** 移除 */
|
|
51
|
+
off<K extends keyof T>(type: K, fn?: (event: T[K]) => void): this {
|
|
52
|
+
this._emitter.off(type, fn);
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** 清空 */
|
|
57
|
+
clear(): this {
|
|
58
|
+
this._emitter.all.clear();
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EventBus } from './EventBus'; // 注意内部不能写export default,因为这里是export *
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
3
|
+
import utc from 'dayjs/plugin/utc';
|
|
4
|
+
import timezone from 'dayjs/plugin/timezone';
|
|
5
|
+
import relativeTime from 'dayjs/plugin/relativeTime';
|
|
6
|
+
import advancedFormat from 'dayjs/plugin/advancedFormat';
|
|
7
|
+
import 'dayjs/locale/zh-cn';
|
|
8
|
+
import { zeroPad } from '../number';
|
|
9
|
+
|
|
10
|
+
dayjs.extend(customParseFormat);
|
|
11
|
+
dayjs.extend(utc);
|
|
12
|
+
dayjs.extend(timezone);
|
|
13
|
+
dayjs.extend(relativeTime);
|
|
14
|
+
dayjs.extend(advancedFormat);
|
|
15
|
+
dayjs.locale('zh-cn');
|
|
16
|
+
|
|
17
|
+
type BaseTime = number | string | Date | dayjs.Dayjs | null | undefined;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 创建 dayjs 实例
|
|
21
|
+
* 文档: https://day.js.org/zh-CN/
|
|
22
|
+
* @param t 各种规范或不规范的时间
|
|
23
|
+
* @returns dayjs 实例
|
|
24
|
+
* @example
|
|
25
|
+
* const d = toDayjs('2021-01-01'); // dayjs 实例
|
|
26
|
+
* d.format('YYYY-MM-DD HH:mm:ss'); // "2025-12-10 11:33:16"
|
|
27
|
+
* d.valueOf(); // 毫秒时间戳,如 1765337596913
|
|
28
|
+
* d.unix(); // 秒时间戳,如 1765337596
|
|
29
|
+
* d.millisecond(); // 毫秒 913
|
|
30
|
+
* d.second(); // 秒 16
|
|
31
|
+
* d.minute(); // 分 33
|
|
32
|
+
* d.hour(); // 时 11
|
|
33
|
+
* d.date(); // 日 10
|
|
34
|
+
* d.day(); // 星期几 5(周日=0)
|
|
35
|
+
* d.month() + 1; // 月 12
|
|
36
|
+
* d.year(); // 年 2025
|
|
37
|
+
* d.startOf('day').valueOf(); // 当日零点
|
|
38
|
+
* d.startOf('month').format('YYYY-MM-DD HH:mm:ss'); // 月初 "2025-12-01 00:00:00"
|
|
39
|
+
* d.endOf('month').format('YYYY-MM-DD HH:mm:ss'); // 月末 "2025-12-31 23:59:59"
|
|
40
|
+
* d.fromNow(); // “刚刚”、“x分钟前/后”、“x小时前/后”、“x天前/后”、“x月前/后”、“x年前/后”
|
|
41
|
+
* d.isSame(t, 'day'); // 是否与t在同一天
|
|
42
|
+
* d.diff(); // 与当前时间相差的毫秒数
|
|
43
|
+
* d.diff(t); // 与t相差的毫秒数
|
|
44
|
+
* d.diff(t, 'second'); // 与t相差的秒数
|
|
45
|
+
* d.diff(t, 'minute'); // 与t相差的分钟数
|
|
46
|
+
* d.diff(t, 'hour'); // 与t相差的小时数
|
|
47
|
+
* d.diff(t, 'day'); // 与t相差的天数
|
|
48
|
+
* d.diff(t, 'week'); // 与t相差的周数
|
|
49
|
+
* d.diff(t, 'month'); // 与t相差的月数
|
|
50
|
+
* d.diff(t, 'quarter'); // 与t相差的季度数
|
|
51
|
+
* d.diff(t, 'year'); // 与t相差的年数
|
|
52
|
+
*/
|
|
53
|
+
export function toDayjs(t: BaseTime, fmt?: dayjs.OptionType) {
|
|
54
|
+
if (t === null || t === undefined) return dayjs();
|
|
55
|
+
if (typeof t === 'number') {
|
|
56
|
+
const s = String(Math.trunc(t));
|
|
57
|
+
return dayjs(s.length === 10 ? t * 1000 : t, fmt);
|
|
58
|
+
}
|
|
59
|
+
if (typeof t === 'string') {
|
|
60
|
+
const s = t.trim();
|
|
61
|
+
if (/^\d{10}$/.test(s)) return dayjs(Number(s) * 1000, fmt);
|
|
62
|
+
if (/^\d{13}$/.test(s)) return dayjs(Number(s), fmt);
|
|
63
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(s)) return dayjs(s, fmt || 'YYYY-MM-DD');
|
|
64
|
+
if (/^\d{4}\/\d{2}\/\d{2}$/.test(s)) return dayjs(s, fmt || 'YYYY/MM/DD');
|
|
65
|
+
if (/^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}$/.test(s))
|
|
66
|
+
return dayjs(s, fmt || 'YYYY-MM-DD HH:mm:ss');
|
|
67
|
+
if (/^\d{4}\/\d{2}\/\d{2}\s+\d{2}:\d{2}:\d{2}$/.test(s))
|
|
68
|
+
return dayjs(s, fmt || 'YYYY/MM/DD HH:mm:ss');
|
|
69
|
+
return dayjs(s, fmt);
|
|
70
|
+
}
|
|
71
|
+
return dayjs(t, fmt);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 获取“前几天”的日期范围
|
|
76
|
+
* @param offset 正整数天数
|
|
77
|
+
* @param fmt 日期格式,默认 `YYYY-MM-DD`
|
|
78
|
+
* @returns `[start, end]` 日期字符串数组
|
|
79
|
+
* @example
|
|
80
|
+
* 若今天为 2025-11-19:
|
|
81
|
+
* getDateRangeBefore(1) // ['2025-11-18', '2025-11-19']
|
|
82
|
+
* getDateRangeBefore(1, 'YYYY-MM-DD HH:mm:ss') // ['2025-11-18 00:00:00', '2025-11-19 23:59:59']
|
|
83
|
+
*/
|
|
84
|
+
export function getDateRangeBefore(offset: number, fmt = 'YYYY-MM-DD') {
|
|
85
|
+
const now = toDayjs(Date.now());
|
|
86
|
+
const n = Math.max(0, Math.trunc(offset));
|
|
87
|
+
const hasTime = /H|h|m|s|S|A|a|x|X/.test(fmt);
|
|
88
|
+
const startDay = now.add(-n, 'day');
|
|
89
|
+
const endDay = now;
|
|
90
|
+
const start = (hasTime ? startDay.startOf('day') : startDay).format(fmt);
|
|
91
|
+
const end = (hasTime ? endDay.endOf('day') : endDay).format(fmt);
|
|
92
|
+
return [start, end];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 获取“后几天”的日期范围
|
|
97
|
+
* - 起点:今天;终点:`offset` 天后
|
|
98
|
+
* - 若 `fmt` 含时间令牌(如 `HH:mm:ss`),则返回整日范围:起点为当日零点,终点为当日末尾
|
|
99
|
+
* @param offset 正整数天数
|
|
100
|
+
* @param fmt 日期格式,默认 `YYYY-MM-DD`
|
|
101
|
+
* @returns `[start, end]` 日期字符串数组
|
|
102
|
+
* @example
|
|
103
|
+
* 若今天为 2025-11-19:
|
|
104
|
+
* getDateRangeAfter(1) // ['2025-11-19', '2025-11-20']
|
|
105
|
+
* getDateRangeAfter(1, 'YYYY-MM-DD HH:mm:ss') // ['2025-11-19 00:00:00', '2025-11-20 23:59:59']
|
|
106
|
+
*/
|
|
107
|
+
export function getDateRangeAfter(offset: number, fmt = 'YYYY-MM-DD') {
|
|
108
|
+
const now = toDayjs(Date.now());
|
|
109
|
+
const n = Math.max(0, Math.trunc(offset));
|
|
110
|
+
const hasTime = /H|h|m|s|S|A|a|x|X/.test(fmt);
|
|
111
|
+
const startDay = now;
|
|
112
|
+
const endDay = now.add(n, 'day');
|
|
113
|
+
const start = (hasTime ? startDay.startOf('day') : startDay).format(fmt);
|
|
114
|
+
const end = (hasTime ? endDay.endOf('day') : endDay).format(fmt);
|
|
115
|
+
return [start, end];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 获取倒计时的时间分解(零填充字符串)
|
|
120
|
+
* @param diff 毫秒差值(正数表示剩余时间,负数/0表示已到期)
|
|
121
|
+
* @returns 包含天、时、分、秒、毫秒的零填充对象
|
|
122
|
+
* @example
|
|
123
|
+
* const diff = toDayjs(t).diff(); // 毫秒差值
|
|
124
|
+
* const parts = getCountdownParts(diff); // { d: '01', h: '02', m: '03', s: '04', ms: '567' }
|
|
125
|
+
*/
|
|
126
|
+
export function getCountdownParts(diff: number) {
|
|
127
|
+
if (diff <= 0) return { d: '00', h: '00', m: '00', s: '00', ms: '000' };
|
|
128
|
+
|
|
129
|
+
const d = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
130
|
+
const h = Math.floor((diff / (1000 * 60 * 60)) % 24);
|
|
131
|
+
const m = Math.floor((diff / (1000 * 60)) % 60);
|
|
132
|
+
const s = Math.floor((diff / 1000) % 60);
|
|
133
|
+
const ms = diff % 1000;
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
d: zeroPad(d),
|
|
137
|
+
h: zeroPad(h),
|
|
138
|
+
m: zeroPad(m),
|
|
139
|
+
s: zeroPad(s),
|
|
140
|
+
ms: zeroPad(ms, 3),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* 通过出生日期计算年龄
|
|
146
|
+
* @param birthdate 生日日期,支持多种格式(会被自动解析)
|
|
147
|
+
* @returns 年龄对象,包含 `age`(年龄数值)和 `type`(年龄单位,'year' 表示年,'month' 表示月)
|
|
148
|
+
* @example
|
|
149
|
+
* // 假设当前日期为 2025-11-19
|
|
150
|
+
* getAgeByBirthdate('2025-05-10'); // { age: 6, type: 'month' }
|
|
151
|
+
* getAgeByBirthdate('2020-11-19'); // { age: 5, type: 'year' }
|
|
152
|
+
* getAgeByBirthdate('2020-12-01'); // { age: 4, type: 'year' }(生日还没到, 所以年龄是4岁)
|
|
153
|
+
*/
|
|
154
|
+
export function getAgeByBirthdate(birthdate: string) {
|
|
155
|
+
const birth = toDayjs(birthdate, 'YYYY-MM-DD');
|
|
156
|
+
const now = toDayjs(Date.now());
|
|
157
|
+
|
|
158
|
+
// 精确的月份计算
|
|
159
|
+
const totalMonths = (now.year() - birth.year()) * 12 + (now.month() - birth.month());
|
|
160
|
+
|
|
161
|
+
// 如果当前日期小于出生日期,月份减1
|
|
162
|
+
const adjustedMonths = now.date() < birth.date() ? totalMonths - 1 : totalMonths;
|
|
163
|
+
|
|
164
|
+
if (adjustedMonths >= 12) {
|
|
165
|
+
let age = Math.floor(adjustedMonths / 12);
|
|
166
|
+
// 检查生日是否已过
|
|
167
|
+
const birthdayThisYear = birth.add(age, 'year');
|
|
168
|
+
if (now.isBefore(birthdayThisYear)) {
|
|
169
|
+
age--;
|
|
170
|
+
}
|
|
171
|
+
return { age, type: 'year' };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return { age: adjustedMonths, type: 'month' };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 对外抛出 dayjs 以便全局配置
|
|
179
|
+
* @example
|
|
180
|
+
* 切换语言
|
|
181
|
+
* dayjs.locale('en'); // 切换为英文
|
|
182
|
+
* dayjs.locale('zh-cn'); // 切换为中文 (默认)
|
|
183
|
+
*/
|
|
184
|
+
export { dayjs };
|
package/src/ts/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 内部统一导出, 外部快捷引入: import {xx} from 'base-tools/ts'
|
|
3
|
+
*/
|
|
4
|
+
export * from './array';
|
|
5
|
+
export * from './async';
|
|
6
|
+
export * from './bean';
|
|
7
|
+
export * from './day';
|
|
8
|
+
export * from './lodash';
|
|
9
|
+
export * from './number';
|
|
10
|
+
export * from './object';
|
|
11
|
+
export * from './string';
|
|
12
|
+
export * from './typing';
|
|
13
|
+
export * from './url';
|
|
14
|
+
export * from './validator';
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import BigNumber from 'bignumber.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 数值入参类型。
|
|
5
|
+
* 支持原生 `number`、`string`(包含小数、科学计数法等)以及 `BigNumber`。
|
|
6
|
+
*/
|
|
7
|
+
export type NumLike = string | number | BigNumber;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 将任意 `NumLike` 统一转换为 `BigNumber` 实例。
|
|
11
|
+
* @param x 任意支持的数值入参。
|
|
12
|
+
* @returns `BigNumber` 实例。
|
|
13
|
+
* @example
|
|
14
|
+
* big('0.1'); // => BigNumber
|
|
15
|
+
* big(0.2); // => BigNumber
|
|
16
|
+
*/
|
|
17
|
+
export function big(x: NumLike): BigNumber {
|
|
18
|
+
return x instanceof BigNumber ? x : new BigNumber(x);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 高精度加法(支持多个参数连加)。
|
|
23
|
+
* @example
|
|
24
|
+
* bigAdd(0.1, 0.2); // => 0.3
|
|
25
|
+
* bigAdd('0.1', '0.2'); // => 0.3
|
|
26
|
+
* bigAdd(1, 2, 3, 4); // => 10 // 多参数连加: 1+2+3+4
|
|
27
|
+
*/
|
|
28
|
+
export function bigAdd(a: NumLike, ...rest: NumLike[]) {
|
|
29
|
+
let acc = big(a);
|
|
30
|
+
for (const x of rest) acc = acc.plus(big(x));
|
|
31
|
+
return acc.toNumber();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 高精度减法(支持多个参数连减)。
|
|
36
|
+
* @example
|
|
37
|
+
* bigSub(1, 0.9); // => 0.1
|
|
38
|
+
* bigSub('1.1', '0.2'); // => 0.9
|
|
39
|
+
* bigSub(10, 1, 2, 3); // => 4 // 多参数连减: 10-1-2-3
|
|
40
|
+
*/
|
|
41
|
+
export function bigSub(a: NumLike, ...rest: NumLike[]) {
|
|
42
|
+
let acc = big(a);
|
|
43
|
+
for (const x of rest) acc = acc.minus(big(x));
|
|
44
|
+
return acc.toNumber();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 高精度乘法(支持多个参数连乘)。
|
|
49
|
+
* @example
|
|
50
|
+
* bigMul(0.1, 0.2); // => 0.02
|
|
51
|
+
* bigMul('1.5', '3'); // => 4.5
|
|
52
|
+
* bigMul(2, 3, 4); // => 24 // 多参数连乘: 2*3*4
|
|
53
|
+
*/
|
|
54
|
+
export function bigMul(a: NumLike, ...rest: NumLike[]) {
|
|
55
|
+
let acc = big(a);
|
|
56
|
+
for (const x of rest) acc = acc.times(big(x));
|
|
57
|
+
return acc.toNumber();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 高精度除法(支持多个参数连除)。
|
|
62
|
+
* @example
|
|
63
|
+
* bigDiv(1, 3); // => 0.333333...
|
|
64
|
+
* bigDiv('10', '4'); // => 2.5
|
|
65
|
+
* bigDiv(100, 5, 2); // => 10 // 多参数连除: 100/5/2
|
|
66
|
+
*/
|
|
67
|
+
export function bigDiv(a: NumLike, ...rest: NumLike[]) {
|
|
68
|
+
let acc = big(a);
|
|
69
|
+
for (const x of rest) acc = acc.div(big(x));
|
|
70
|
+
return acc.toNumber();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 指数运算
|
|
75
|
+
* @param x 底数。
|
|
76
|
+
* @param y 指数。
|
|
77
|
+
* @returns 计算结果。
|
|
78
|
+
* @example
|
|
79
|
+
* bigPow(2, 3); // => 8
|
|
80
|
+
* bigPow('2.5', 2); // => 6.25
|
|
81
|
+
*/
|
|
82
|
+
export function bigPow(x: NumLike, y: NumLike) {
|
|
83
|
+
return big(x).pow(big(y)).toNumber();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 四舍五入到指定位数
|
|
88
|
+
* @param x 需要舍入的数值。
|
|
89
|
+
* @param dp 保留的小数位数,默认 `0`(取整)。
|
|
90
|
+
* @param rm 舍入模式,默认 `ROUND_HALF_UP`(四舍五入)。
|
|
91
|
+
* @returns 舍入后的数值。
|
|
92
|
+
* @example
|
|
93
|
+
* bigRound(1.6); // => 2
|
|
94
|
+
* bigRound('1.234', 2); // => 1.23
|
|
95
|
+
* bigRound('1.235', 2); // => 1.24
|
|
96
|
+
* bigRound('1.299', 2, BigNumber.ROUND_DOWN); // => 1.29
|
|
97
|
+
*/
|
|
98
|
+
export function bigRound(x: NumLike, dp = 0, rm: BigNumber.RoundingMode = BigNumber.ROUND_HALF_UP) {
|
|
99
|
+
return big(x).decimalPlaces(dp, rm).toNumber();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 将数值按指定位数格式化为字符串(保留小数位)。
|
|
104
|
+
* @param x 需要格式化的数值。
|
|
105
|
+
* @param dp 保留的小数位数,默认 `2`。
|
|
106
|
+
* @param rm 舍入模式,默认 `ROUND_HALF_UP`(四舍五入)。
|
|
107
|
+
* @returns 格式化后的字符串。
|
|
108
|
+
* @example
|
|
109
|
+
* toFixed('1'); // => '1.00'
|
|
110
|
+
* +toFixed('1'); // => 1
|
|
111
|
+
* toFixed(1.2345); // => '1.23'
|
|
112
|
+
* toFixed(1.2345, 3); // => '1.235'
|
|
113
|
+
* toFixed('1.2345', 0, BigNumber.ROUND_UP); // => '2'
|
|
114
|
+
*/
|
|
115
|
+
export function toFixed(
|
|
116
|
+
x: NumLike,
|
|
117
|
+
dp = 2,
|
|
118
|
+
rm: BigNumber.RoundingMode = BigNumber.ROUND_HALF_UP,
|
|
119
|
+
): string {
|
|
120
|
+
return big(x).toFixed(dp, rm);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 比较两个数值大小。
|
|
125
|
+
* @example
|
|
126
|
+
* bigCompare('2', '10'); // => -1
|
|
127
|
+
* bigCompare(3, 3); // => 0
|
|
128
|
+
* bigCompare('10', 2); // => 1
|
|
129
|
+
*/
|
|
130
|
+
export function bigCompare(a: NumLike, b: NumLike): -1 | 0 | 1 | null {
|
|
131
|
+
return big(a).comparedTo(big(b));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 判断两个数值是否相等。
|
|
136
|
+
* @example
|
|
137
|
+
* bigEqual('1.0', 1); // => true
|
|
138
|
+
* bigEqual(2, 1); // => false
|
|
139
|
+
*/
|
|
140
|
+
export function bigEqual(a: NumLike, b: NumLike): boolean {
|
|
141
|
+
return big(a).isEqualTo(big(b));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* 判断 a 是否大于 b。
|
|
146
|
+
* @example
|
|
147
|
+
* bigGt(2, 1); // => true
|
|
148
|
+
* bigGt(1, 2); // => false
|
|
149
|
+
*/
|
|
150
|
+
export function bigGt(a: NumLike, b: NumLike): boolean {
|
|
151
|
+
return big(a).isGreaterThan(big(b));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* 判断 a 是否大于等于 b。
|
|
156
|
+
* @example
|
|
157
|
+
* bigGte(2, 2); // => true
|
|
158
|
+
* bigGte(1, 2); // => false
|
|
159
|
+
*/
|
|
160
|
+
export function bigGte(a: NumLike, b: NumLike): boolean {
|
|
161
|
+
return big(a).isGreaterThanOrEqualTo(big(b));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 判断 a 是否小于 b。
|
|
166
|
+
* @example
|
|
167
|
+
* bigLt(1, 2); // => true
|
|
168
|
+
* bigLt(2, 1); // => false
|
|
169
|
+
*/
|
|
170
|
+
export function bigLt(a: NumLike, b: NumLike): boolean {
|
|
171
|
+
return big(a).isLessThan(big(b));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 判断 a 是否小于等于 b。
|
|
176
|
+
* @example
|
|
177
|
+
* bigLte(2, 2); // => true
|
|
178
|
+
* bigLte(1, 2); // => true
|
|
179
|
+
* bigLte(2, 1); // => false
|
|
180
|
+
*/
|
|
181
|
+
export function bigLte(a: NumLike, b: NumLike): boolean {
|
|
182
|
+
return big(a).isLessThanOrEqualTo(big(b));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* 导出 BigNumber 类
|
|
187
|
+
* @example
|
|
188
|
+
* BigNumber.ROUND_HALF_UP; // 使用类型
|
|
189
|
+
* BigNumber.set(config); // 设置全局配置
|
|
190
|
+
* const bn = new BigNumber('123456.789'); // 创建实例
|
|
191
|
+
*/
|
|
192
|
+
export { BigNumber };
|