sculp-js 1.19.1 → 1.19.3
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/cjs/array.cjs +1 -1
- package/dist/cjs/async.cjs +1 -1
- package/dist/cjs/base64.cjs +157 -71
- package/dist/cjs/clipboard.cjs +1 -1
- package/dist/cjs/cloneDeep.cjs +1 -1
- package/dist/cjs/cookie.cjs +1 -1
- package/dist/cjs/date.cjs +130 -70
- package/dist/cjs/dom.cjs +1 -1
- package/dist/cjs/download.cjs +1 -1
- package/dist/cjs/file.cjs +1 -1
- package/dist/cjs/func.cjs +1 -1
- package/dist/cjs/index.cjs +11 -3
- package/dist/cjs/isEqual.cjs +1 -1
- package/dist/cjs/math.cjs +1 -1
- package/dist/cjs/number.cjs +1 -1
- package/dist/cjs/object.cjs +1 -1
- package/dist/cjs/path.cjs +1 -1
- package/dist/cjs/qs.cjs +1 -1
- package/dist/cjs/random.cjs +1 -1
- package/dist/cjs/string.cjs +1 -1
- package/dist/cjs/tooltip.cjs +1 -1
- package/dist/cjs/tree.cjs +1 -1
- package/dist/cjs/type.cjs +71 -3
- package/dist/cjs/unicodeToolkit.cjs +19 -19
- package/dist/cjs/unique.cjs +1 -1
- package/dist/cjs/url.cjs +1 -1
- package/dist/cjs/validator.cjs +1 -1
- package/dist/cjs/variable.cjs +1 -1
- package/dist/cjs/watermark.cjs +1 -1
- package/dist/esm/array.mjs +1 -1
- package/dist/esm/async.mjs +1 -1
- package/dist/esm/base64.mjs +157 -71
- package/dist/esm/clipboard.mjs +1 -1
- package/dist/esm/cloneDeep.mjs +1 -1
- package/dist/esm/cookie.mjs +1 -1
- package/dist/esm/date.mjs +130 -78
- package/dist/esm/dom.mjs +1 -1
- package/dist/esm/download.mjs +1 -1
- package/dist/esm/file.mjs +1 -1
- package/dist/esm/func.mjs +1 -1
- package/dist/esm/index.mjs +11 -10
- package/dist/esm/isEqual.mjs +1 -1
- package/dist/esm/math.mjs +1 -1
- package/dist/esm/number.mjs +1 -1
- package/dist/esm/object.mjs +1 -1
- package/dist/esm/path.mjs +1 -1
- package/dist/esm/qs.mjs +1 -1
- package/dist/esm/random.mjs +1 -1
- package/dist/esm/string.mjs +1 -1
- package/dist/esm/tooltip.mjs +1 -1
- package/dist/esm/tree.mjs +1 -1
- package/dist/esm/type.mjs +71 -3
- package/dist/esm/unicodeToolkit.mjs +19 -19
- package/dist/esm/unique.mjs +1 -1
- package/dist/esm/url.mjs +1 -1
- package/dist/esm/validator.mjs +1 -1
- package/dist/esm/variable.mjs +1 -1
- package/dist/esm/watermark.mjs +1 -1
- package/dist/types/base64.d.ts +6 -6
- package/dist/types/date.d.ts +124 -28
- package/dist/types/type.d.ts +86 -3
- package/dist/umd/index.min.js +2 -2
- package/package.json +1 -1
package/dist/cjs/array.cjs
CHANGED
package/dist/cjs/async.cjs
CHANGED
package/dist/cjs/base64.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.19.
|
|
2
|
+
* sculp-js v1.19.3
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -15,112 +15,198 @@ const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
|
15
15
|
// eslint-disable-next-line
|
|
16
16
|
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* 高性能 UTF-8 字符串转 Uint8Array
|
|
19
|
+
*/
|
|
20
|
+
function stringToUint8Array(str) {
|
|
21
|
+
const len = str.length;
|
|
22
|
+
const bytes = new Uint8Array(len * 3); // 最多 3 倍长度
|
|
23
|
+
let j = 0;
|
|
24
|
+
for (let i = 0; i < len; i++) {
|
|
25
|
+
let code = str.charCodeAt(i);
|
|
26
|
+
if (code < 0x80) {
|
|
27
|
+
bytes[j++] = code;
|
|
28
|
+
} else if (code < 0x800) {
|
|
29
|
+
bytes[j++] = 0xc0 | (code >> 6);
|
|
30
|
+
bytes[j++] = 0x80 | (code & 0x3f);
|
|
31
|
+
} else if (code < 0xd800 || code >= 0xe000) {
|
|
32
|
+
bytes[j++] = 0xe0 | (code >> 12);
|
|
33
|
+
bytes[j++] = 0x80 | ((code >> 6) & 0x3f);
|
|
34
|
+
bytes[j++] = 0x80 | (code & 0x3f);
|
|
35
|
+
} else {
|
|
36
|
+
// 处理代理对(emoji 等)
|
|
37
|
+
i++;
|
|
38
|
+
code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
|
|
39
|
+
bytes[j++] = 0xf0 | (code >> 18);
|
|
40
|
+
bytes[j++] = 0x80 | ((code >> 12) & 0x3f);
|
|
41
|
+
bytes[j++] = 0x80 | ((code >> 6) & 0x3f);
|
|
42
|
+
bytes[j++] = 0x80 | (code & 0x3f);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return bytes.subarray(0, j);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 高性能 Uint8Array 转 UTF-8 字符串
|
|
49
|
+
*/
|
|
50
|
+
function uint8ArrayToString(bytes) {
|
|
51
|
+
const len = bytes.length;
|
|
52
|
+
let result = '';
|
|
53
|
+
let i = 0;
|
|
54
|
+
while (i < len) {
|
|
55
|
+
const byte1 = bytes[i++];
|
|
56
|
+
if (byte1 < 0x80) {
|
|
57
|
+
result += String.fromCharCode(byte1);
|
|
58
|
+
} else if (byte1 < 0xe0) {
|
|
59
|
+
const byte2 = bytes[i++] & 0x3f;
|
|
60
|
+
result += String.fromCharCode(((byte1 & 0x1f) << 6) | byte2);
|
|
61
|
+
} else if (byte1 < 0xf0) {
|
|
62
|
+
const byte2 = bytes[i++] & 0x3f;
|
|
63
|
+
const byte3 = bytes[i++] & 0x3f;
|
|
64
|
+
result += String.fromCharCode(((byte1 & 0x0f) << 12) | (byte2 << 6) | byte3);
|
|
65
|
+
} else {
|
|
66
|
+
const byte2 = bytes[i++] & 0x3f;
|
|
67
|
+
const byte3 = bytes[i++] & 0x3f;
|
|
68
|
+
const byte4 = bytes[i++] & 0x3f;
|
|
69
|
+
let code = ((byte1 & 0x07) << 18) | (byte2 << 12) | (byte3 << 6) | byte4;
|
|
70
|
+
code -= 0x10000;
|
|
71
|
+
result += String.fromCharCode(0xd800 + ((code >> 10) & 0x3ff), 0xdc00 + (code & 0x3ff));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 高性能 Base64 编码(二进制字符串转 Base64)
|
|
78
|
+
*/
|
|
79
|
+
function binaryToBase64(binary) {
|
|
80
|
+
const len = binary.length;
|
|
81
|
+
let result = '';
|
|
82
|
+
let i = 0;
|
|
83
|
+
for (; i < len - 2; i += 3) {
|
|
84
|
+
const n = (binary.charCodeAt(i) << 16) | (binary.charCodeAt(i + 1) << 8) | binary.charCodeAt(i + 2);
|
|
85
|
+
result += b64.charAt(n >> 18) + b64.charAt((n >> 12) & 0x3f) + b64.charAt((n >> 6) & 0x3f) + b64.charAt(n & 0x3f);
|
|
86
|
+
}
|
|
87
|
+
// 处理剩余字节
|
|
88
|
+
const remaining = len - i;
|
|
89
|
+
if (remaining === 1) {
|
|
90
|
+
const n = binary.charCodeAt(i);
|
|
91
|
+
result += b64.charAt(n >> 2) + b64.charAt((n << 4) & 0x3f) + '==';
|
|
92
|
+
} else if (remaining === 2) {
|
|
93
|
+
const n = (binary.charCodeAt(i) << 8) | binary.charCodeAt(i + 1);
|
|
94
|
+
result += b64.charAt(n >> 10) + b64.charAt((n >> 4) & 0x3f) + b64.charAt((n << 2) & 0x3f) + '=';
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 高性能 Base64 解码(Base64 转二进制字符串)
|
|
100
|
+
*/
|
|
101
|
+
function base64ToBinary(base64Str) {
|
|
102
|
+
base64Str = String(base64Str).replace(/[\t\n\f\r ]+/g, '');
|
|
103
|
+
if (!b64re.test(base64Str)) {
|
|
104
|
+
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
|
|
105
|
+
}
|
|
106
|
+
const len = base64Str.length;
|
|
107
|
+
const padding = base64Str.endsWith('==') ? 2 : base64Str.endsWith('=') ? 1 : 0;
|
|
108
|
+
const result = new Array(len * 0.75 - padding);
|
|
109
|
+
let j = 0;
|
|
110
|
+
for (let i = 0; i < len; i += 4) {
|
|
111
|
+
const n =
|
|
112
|
+
(b64.indexOf(base64Str.charAt(i)) << 18) |
|
|
113
|
+
(b64.indexOf(base64Str.charAt(i + 1)) << 12) |
|
|
114
|
+
((b64.indexOf(base64Str.charAt(i + 2)) & 0x3f) << 6) |
|
|
115
|
+
(b64.indexOf(base64Str.charAt(i + 3)) & 0x3f);
|
|
116
|
+
result[j++] = String.fromCharCode((n >> 16) & 0xff);
|
|
117
|
+
if (i + 2 < len - padding || padding < 2) {
|
|
118
|
+
result[j++] = String.fromCharCode((n >> 8) & 0xff);
|
|
119
|
+
}
|
|
120
|
+
if (i + 3 < len - padding || padding < 1) {
|
|
121
|
+
result[j++] = String.fromCharCode(n & 0xff);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return result.join('');
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 字符串编码成 Base64(适用于任何环境,包括小程序)
|
|
19
128
|
* @param {string} string
|
|
20
129
|
* @returns {string}
|
|
21
130
|
*/
|
|
22
131
|
function weBtoa(string) {
|
|
23
|
-
// 同window.btoa: 字符串编码成Base64
|
|
24
132
|
string = String(string);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
c,
|
|
29
|
-
result = '',
|
|
30
|
-
i = 0;
|
|
31
|
-
const strLen = string.length;
|
|
32
|
-
const rest = strLen % 3;
|
|
33
|
-
for (; i < strLen; ) {
|
|
34
|
-
if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255)
|
|
133
|
+
const len = string.length;
|
|
134
|
+
for (let i = 0; i < len; i++) {
|
|
135
|
+
if (string.charCodeAt(i) > 255) {
|
|
35
136
|
throw new TypeError(
|
|
36
137
|
"Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."
|
|
37
138
|
);
|
|
38
|
-
|
|
39
|
-
result +=
|
|
40
|
-
b64.charAt((bitmap >> 18) & 63) +
|
|
41
|
-
b64.charAt((bitmap >> 12) & 63) +
|
|
42
|
-
b64.charAt((bitmap >> 6) & 63) +
|
|
43
|
-
b64.charAt(bitmap & 63);
|
|
139
|
+
}
|
|
44
140
|
}
|
|
45
|
-
return
|
|
141
|
+
return binaryToBase64(string);
|
|
46
142
|
}
|
|
47
143
|
/**
|
|
48
|
-
* Base64
|
|
144
|
+
* Base64 解码为原始字符串(适用于任何环境,包括小程序)
|
|
49
145
|
* @param {string} string
|
|
50
146
|
* @returns {string}
|
|
51
147
|
*/
|
|
52
148
|
function weAtob(string) {
|
|
53
|
-
|
|
54
|
-
string = String(string).replace(/[\t\n\f\r ]+/g, '');
|
|
55
|
-
if (!b64re.test(string))
|
|
56
|
-
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
|
|
57
|
-
string += '=='.slice(2 - (string.length & 3));
|
|
58
|
-
let bitmap,
|
|
59
|
-
result = '',
|
|
60
|
-
r1,
|
|
61
|
-
r2,
|
|
62
|
-
i = 0;
|
|
63
|
-
for (const strLen = string.length; i < strLen; ) {
|
|
64
|
-
bitmap =
|
|
65
|
-
(b64.indexOf(string.charAt(i++)) << 18) |
|
|
66
|
-
(b64.indexOf(string.charAt(i++)) << 12) |
|
|
67
|
-
((r1 = b64.indexOf(string.charAt(i++))) << 6) |
|
|
68
|
-
(r2 = b64.indexOf(string.charAt(i++)));
|
|
69
|
-
result +=
|
|
70
|
-
r1 === 64
|
|
71
|
-
? String.fromCharCode((bitmap >> 16) & 255)
|
|
72
|
-
: r2 === 64
|
|
73
|
-
? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255)
|
|
74
|
-
: String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255, bitmap & 255);
|
|
75
|
-
}
|
|
76
|
-
return result;
|
|
77
|
-
}
|
|
78
|
-
function stringToUint8Array(str) {
|
|
79
|
-
const utf8 = encodeURIComponent(str); // 将字符串转换为 UTF-8 编码
|
|
80
|
-
const uint8Array = new Uint8Array(utf8.length); // 创建 Uint8Array
|
|
81
|
-
for (let i = 0; i < utf8.length; i++) {
|
|
82
|
-
uint8Array[i] = utf8.charCodeAt(i); // 填充 Uint8Array
|
|
83
|
-
}
|
|
84
|
-
return uint8Array;
|
|
85
|
-
}
|
|
86
|
-
function uint8ArrayToString(uint8Array) {
|
|
87
|
-
const utf8 = String.fromCharCode.apply(null, uint8Array); // 将 Uint8Array 转为字符串
|
|
88
|
-
return decodeURIComponent(utf8); // 将 UTF-8 字符串解码回正常字符串
|
|
149
|
+
return base64ToBinary(string);
|
|
89
150
|
}
|
|
90
151
|
/**
|
|
91
|
-
* 将base64编码的字符串转换为原始字符串,包括对中文内容的处理(高性能,且支持Web、Node、小程序等任意平台)
|
|
92
|
-
* @param base64 base64编码的字符串
|
|
152
|
+
* 将 base64 编码的字符串转换为原始字符串,包括对中文内容的处理 (高性能,且支持 Web、Node、小程序等任意平台)
|
|
153
|
+
* @param base64 base64 编码的字符串
|
|
93
154
|
* @returns 原始字符串,包括中文内容
|
|
94
155
|
*/
|
|
95
156
|
function b64decode(base64) {
|
|
96
|
-
|
|
157
|
+
// 优先使用原生方法(性能最优)
|
|
158
|
+
if (!type.isNullOrUnDef(func.getGlobal('atob')) && !type.isNullOrUnDef(func.getGlobal('TextDecoder'))) {
|
|
159
|
+
try {
|
|
160
|
+
const binaryString = func.getGlobal('atob')(base64);
|
|
161
|
+
const len = binaryString.length;
|
|
162
|
+
const bytes = new Uint8Array(len);
|
|
163
|
+
for (let i = 0; i < len; i++) {
|
|
164
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
165
|
+
}
|
|
166
|
+
return new (func.getGlobal('TextDecoder'))('utf-8').decode(bytes);
|
|
167
|
+
} catch (e) {
|
|
168
|
+
// 如果原生方法失败,使用降级方案
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// 降级方案:使用自定义实现
|
|
172
|
+
const binaryString = base64ToBinary(base64);
|
|
97
173
|
const len = binaryString.length;
|
|
98
174
|
const bytes = new Uint8Array(len);
|
|
99
175
|
for (let i = 0; i < len; i++) {
|
|
100
176
|
bytes[i] = binaryString.charCodeAt(i);
|
|
101
177
|
}
|
|
102
|
-
|
|
103
|
-
return !type.isNullOrUnDef(func.getGlobal('TextDecoder'))
|
|
104
|
-
? new (func.getGlobal('TextDecoder'))('utf-8').decode(bytes)
|
|
105
|
-
: uint8ArrayToString(bytes);
|
|
178
|
+
return uint8ArrayToString(bytes);
|
|
106
179
|
}
|
|
107
180
|
/**
|
|
108
|
-
* 将原始字符串,包括中文内容,转换为base64编码的字符串(高性能,且支持Web、Node、小程序等任意平台)
|
|
181
|
+
* 将原始字符串,包括中文内容,转换为 base64 编码的字符串 (高性能,且支持 Web、Node、小程序等任意平台)
|
|
109
182
|
* @param rawStr 原始字符串,包括中文内容
|
|
110
|
-
* @returns base64编码的字符串
|
|
183
|
+
* @returns base64 编码的字符串
|
|
111
184
|
*/
|
|
112
185
|
function b64encode(rawStr) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
186
|
+
// 优先使用原生方法(性能最优)
|
|
187
|
+
if (!type.isNullOrUnDef(func.getGlobal('btoa')) && !type.isNullOrUnDef(func.getGlobal('TextEncoder'))) {
|
|
188
|
+
try {
|
|
189
|
+
const utf8Array = new (func.getGlobal('TextEncoder'))().encode(rawStr);
|
|
190
|
+
let binaryString = '';
|
|
191
|
+
const len = utf8Array.length;
|
|
192
|
+
for (let i = 0; i < len; i++) {
|
|
193
|
+
binaryString += String.fromCharCode(utf8Array[i]);
|
|
194
|
+
}
|
|
195
|
+
return func.getGlobal('btoa')(binaryString);
|
|
196
|
+
} catch (e) {
|
|
197
|
+
// 如果原生方法失败,使用降级方案
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// 降级方案:使用自定义实现
|
|
201
|
+
const utf8Array = stringToUint8Array(rawStr);
|
|
116
202
|
// 将 Uint8Array 转换为二进制字符串
|
|
117
203
|
let binaryString = '';
|
|
118
204
|
const len = utf8Array.length;
|
|
119
205
|
for (let i = 0; i < len; i++) {
|
|
120
206
|
binaryString += String.fromCharCode(utf8Array[i]);
|
|
121
207
|
}
|
|
122
|
-
// 将二进制字符串转换为base64
|
|
123
|
-
return
|
|
208
|
+
// 将二进制字符串转换为 base64 编码
|
|
209
|
+
return binaryToBase64(binaryString);
|
|
124
210
|
}
|
|
125
211
|
var base64 = {
|
|
126
212
|
weBtoa,
|
package/dist/cjs/clipboard.cjs
CHANGED
package/dist/cjs/cloneDeep.cjs
CHANGED
package/dist/cjs/cookie.cjs
CHANGED
package/dist/cjs/date.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.19.
|
|
2
|
+
* sculp-js v1.19.3
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -115,19 +115,25 @@ function dateToEnd(value) {
|
|
|
115
115
|
return dateParse(d.getTime() - 1);
|
|
116
116
|
}
|
|
117
117
|
/**
|
|
118
|
-
* 格式化为日期对象(带自定义格式化模板)
|
|
118
|
+
* 格式化为日期对象 (带自定义格式化模板)
|
|
119
119
|
* @param {Date} value - 可以是数值、字符串或 Date 对象
|
|
120
120
|
* @param {string} [format] - 模板,默认是 YYYY-MM-DD HH:mm:ss,模板字符:
|
|
121
|
-
* - YYYY:年
|
|
122
|
-
* -
|
|
123
|
-
* -
|
|
124
|
-
* - DD
|
|
125
|
-
* -
|
|
126
|
-
* - HH:时(24
|
|
127
|
-
* -
|
|
128
|
-
* -
|
|
129
|
-
* -
|
|
130
|
-
* -
|
|
121
|
+
* - YYYY/yyyy:年
|
|
122
|
+
* - MM:月(补零)
|
|
123
|
+
* - M:月(不补零)
|
|
124
|
+
* - DD/dd:日(补零)
|
|
125
|
+
* - D/d:日(不补零)
|
|
126
|
+
* - HH:时(24 小时制,补零)
|
|
127
|
+
* - H:时(24 小时制,不补零)
|
|
128
|
+
* - mm:分(补零)
|
|
129
|
+
* - m:分(不补零)
|
|
130
|
+
* - ss:秒(补零)
|
|
131
|
+
* - s:秒(不补零)
|
|
132
|
+
* - SSS:毫秒(3 位)
|
|
133
|
+
* - SS:毫秒(2 位)
|
|
134
|
+
* - S:毫秒(1 位)
|
|
135
|
+
* - ww:中文完整星期(如:周日)
|
|
136
|
+
* - w:中文星期(如:周日)
|
|
131
137
|
* @returns {string} 格式化后的日期字符串
|
|
132
138
|
*/
|
|
133
139
|
function formatDate(value, format = 'YYYY-MM-DD HH:mm:ss') {
|
|
@@ -156,61 +162,113 @@ function formatDate(value, format = 'YYYY-MM-DD HH:mm:ss') {
|
|
|
156
162
|
return fmt;
|
|
157
163
|
}
|
|
158
164
|
/**
|
|
159
|
-
*
|
|
160
|
-
* @param {DateValue} originDate -
|
|
161
|
-
* @param {
|
|
162
|
-
* @
|
|
163
|
-
* @
|
|
165
|
+
* 调整日期(增加或减少特定时间单位)
|
|
166
|
+
* @param {DateValue} originDate - 参考日期,可以是 Date 对象、时间戳或日期字符串
|
|
167
|
+
* @param {CalculateDateOptions} options - 配置项,支持多种时间单位
|
|
168
|
+
* @returns {string | Date} 计算后的日期/日期时间字符串或 Date 对象
|
|
169
|
+
* @example
|
|
170
|
+
* // 基础用法(向后 2 天)
|
|
171
|
+
* adjustDate('2024-01-01', { days: 2 }) // '2024-01-03'
|
|
172
|
+
*
|
|
173
|
+
* // 向前 2 天
|
|
174
|
+
* adjustDate('2024-01-01', { days: -2 }) // '2023-12-30'
|
|
175
|
+
*
|
|
176
|
+
* // 向后 1 年 2 个月 3 天
|
|
177
|
+
* adjustDate('2024-01-01', { years: 1, months: 2, days: 3 }) // '2025-03-04'
|
|
178
|
+
*
|
|
179
|
+
* // 向后 2 周
|
|
180
|
+
* adjustDate('2024-01-01', { weeks: 2 }) // '2024-01-15'
|
|
181
|
+
*
|
|
182
|
+
* // 包含时间(向后 2 天 3 小时 30 分钟)
|
|
183
|
+
* adjustDate('2024-01-01 10:30:00', { days: 2, hours: 3, minutes: 30 }) // '2024-01-03 14:00'
|
|
184
|
+
*
|
|
185
|
+
* // 自定义格式
|
|
186
|
+
* adjustDate('2024-01-01', { days: 2, format: 'YYYY/MM/DD' }) // '2024/01/03'
|
|
187
|
+
* adjustDate('2024-01-01', { days: 2, format: 'YYYY 年 MM 月 DD 日' }) // '2024 年 01 月 03 日'
|
|
188
|
+
*
|
|
189
|
+
* // 时间戳输入
|
|
190
|
+
* adjustDate(1717330884896, { days: 2 }) // '2024-06-04'
|
|
191
|
+
*
|
|
192
|
+
* // 精确到毫秒
|
|
193
|
+
* adjustDate('2024-01-01 10:30:00', { hours: 1, minutes: 30, seconds: 45, milliseconds: 500 })
|
|
194
|
+
*
|
|
195
|
+
* // 返回 Date 对象
|
|
196
|
+
* adjustDate('2024-01-01', { days: 2, returnDate: true }) // Date 对象
|
|
164
197
|
*/
|
|
165
|
-
function
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
198
|
+
function adjustDate(originDate, options = {}) {
|
|
199
|
+
const {
|
|
200
|
+
format,
|
|
201
|
+
returnDate = false,
|
|
202
|
+
years = 0,
|
|
203
|
+
months = 0,
|
|
204
|
+
weeks = 0,
|
|
205
|
+
days = 0,
|
|
206
|
+
hours = 0,
|
|
207
|
+
minutes = 0,
|
|
208
|
+
seconds = 0,
|
|
209
|
+
milliseconds = 0
|
|
210
|
+
} = options;
|
|
211
|
+
const date = dateParse(originDate);
|
|
212
|
+
const targetDate = new Date(date);
|
|
213
|
+
// 保存原始日期以便处理月末边界
|
|
214
|
+
const originalDay = date.getDate();
|
|
215
|
+
const originalMonthDays = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
216
|
+
const isEndOfMonth = originalDay === originalMonthDays;
|
|
217
|
+
targetDate.setFullYear(targetDate.getFullYear() + years);
|
|
218
|
+
// 处理月末边界:如果原始日期是月末,需要特殊处理
|
|
219
|
+
if (months !== 0) {
|
|
220
|
+
const targetMonthIndex = targetDate.getMonth() + months;
|
|
221
|
+
const targetMonthDays = new Date(targetDate.getFullYear(), targetMonthIndex + 1, 0).getDate();
|
|
222
|
+
// 先将日期设为 1 号,避免 setMonth 时因日期过大而自动进位
|
|
223
|
+
targetDate.setDate(1);
|
|
224
|
+
targetDate.setMonth(targetMonthIndex);
|
|
225
|
+
// 如果原始日期是月末,则调整为目标月份的月末
|
|
226
|
+
if (isEndOfMonth) {
|
|
227
|
+
targetDate.setDate(targetMonthDays);
|
|
228
|
+
} else if (originalDay > targetMonthDays) {
|
|
229
|
+
// 如果原始日期大于目标月份的最大天数,也调整为目标月份的月末
|
|
230
|
+
targetDate.setDate(targetMonthDays);
|
|
231
|
+
} else {
|
|
232
|
+
// 否则保持原始日期
|
|
233
|
+
targetDate.setDate(originalDay);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// 处理天数(不包括月份变化)
|
|
237
|
+
if (days !== 0 || weeks !== 0) {
|
|
238
|
+
targetDate.setDate(targetDate.getDate() + days + weeks * 7);
|
|
239
|
+
}
|
|
240
|
+
targetDate.setHours(targetDate.getHours() + hours);
|
|
241
|
+
targetDate.setMinutes(targetDate.getMinutes() + minutes);
|
|
242
|
+
targetDate.setSeconds(targetDate.getSeconds() + seconds);
|
|
243
|
+
targetDate.setMilliseconds(targetDate.getMilliseconds() + milliseconds);
|
|
244
|
+
if (returnDate) {
|
|
245
|
+
return targetDate;
|
|
246
|
+
}
|
|
247
|
+
if (format) {
|
|
248
|
+
return formatDate(targetDate, format);
|
|
249
|
+
}
|
|
250
|
+
const year = targetDate.getFullYear();
|
|
251
|
+
const month = String(targetDate.getMonth() + 1).padStart(2, '0');
|
|
252
|
+
const day = String(targetDate.getDate()).padStart(2, '0');
|
|
253
|
+
const hoursStr = String(targetDate.getHours()).padStart(2, '0');
|
|
254
|
+
const minutesStr = String(targetDate.getMinutes()).padStart(2, '0');
|
|
255
|
+
const secondsStr = String(targetDate.getSeconds()).padStart(2, '0');
|
|
256
|
+
const hasTimeParam =
|
|
257
|
+
options.hasOwnProperty('hours') ||
|
|
258
|
+
options.hasOwnProperty('minutes') ||
|
|
259
|
+
options.hasOwnProperty('seconds') ||
|
|
260
|
+
options.hasOwnProperty('milliseconds');
|
|
261
|
+
if (hasTimeParam) {
|
|
262
|
+
if (options.hasOwnProperty('milliseconds')) {
|
|
263
|
+
const msStr = String(targetDate.getMilliseconds()).padStart(3, '0');
|
|
264
|
+
return `${year}-${month}-${day} ${hoursStr}:${minutesStr}:${secondsStr}.${msStr}`;
|
|
265
|
+
}
|
|
266
|
+
if (options.hasOwnProperty('seconds')) {
|
|
267
|
+
return `${year}-${month}-${day} ${hoursStr}:${minutesStr}:${secondsStr}`;
|
|
268
|
+
}
|
|
269
|
+
return `${year}-${month}-${day} ${hoursStr}:${minutesStr}`;
|
|
270
|
+
}
|
|
271
|
+
return `${year}-${month}-${day}`;
|
|
214
272
|
}
|
|
215
273
|
var date = {
|
|
216
274
|
isValidDate,
|
|
@@ -218,12 +276,14 @@ var date = {
|
|
|
218
276
|
dateToStart,
|
|
219
277
|
dateToEnd,
|
|
220
278
|
formatDate,
|
|
221
|
-
|
|
222
|
-
|
|
279
|
+
adjustDate,
|
|
280
|
+
/**
|
|
281
|
+
* @deprecated 已废弃,请使用 adjustDate
|
|
282
|
+
*/
|
|
283
|
+
calculateDate: adjustDate
|
|
223
284
|
};
|
|
224
285
|
|
|
225
|
-
exports.
|
|
226
|
-
exports.calculateDateTime = calculateDateTime;
|
|
286
|
+
exports.adjustDate = adjustDate;
|
|
227
287
|
exports.dateParse = dateParse;
|
|
228
288
|
exports.dateToEnd = dateToEnd;
|
|
229
289
|
exports.dateToStart = dateToStart;
|
package/dist/cjs/dom.cjs
CHANGED
package/dist/cjs/download.cjs
CHANGED
package/dist/cjs/file.cjs
CHANGED
package/dist/cjs/func.cjs
CHANGED
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.19.
|
|
2
|
+
* sculp-js v1.19.3
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -79,8 +79,7 @@ exports.fallbackCopyText = clipboard.fallbackCopyText;
|
|
|
79
79
|
exports.cookieDel = cookie.cookieDel;
|
|
80
80
|
exports.cookieGet = cookie.cookieGet;
|
|
81
81
|
exports.cookieSet = cookie.cookieSet;
|
|
82
|
-
exports.
|
|
83
|
-
exports.calculateDateTime = date.calculateDateTime;
|
|
82
|
+
exports.adjustDate = date.adjustDate;
|
|
84
83
|
exports.dateParse = date.dateParse;
|
|
85
84
|
exports.dateToEnd = date.dateToEnd;
|
|
86
85
|
exports.dateToStart = date.dateToStart;
|
|
@@ -124,14 +123,20 @@ exports.stringFill = string.stringFill;
|
|
|
124
123
|
exports.stringFormat = string.stringFormat;
|
|
125
124
|
exports.stringKebabCase = string.stringKebabCase;
|
|
126
125
|
exports.arrayLike = type.arrayLike;
|
|
126
|
+
exports.is = type.is;
|
|
127
|
+
exports.isArguments = type.isArguments;
|
|
127
128
|
exports.isArray = type.isArray;
|
|
129
|
+
exports.isArrayBuffer = type.isArrayBuffer;
|
|
130
|
+
exports.isAsyncFunction = type.isAsyncFunction;
|
|
128
131
|
exports.isBigInt = type.isBigInt;
|
|
129
132
|
exports.isBoolean = type.isBoolean;
|
|
133
|
+
exports.isDataView = type.isDataView;
|
|
130
134
|
exports.isDate = type.isDate;
|
|
131
135
|
exports.isEmpty = type.isEmpty;
|
|
132
136
|
exports.isError = type.isError;
|
|
133
137
|
exports.isFunction = type.isFunction;
|
|
134
138
|
exports.isJsonString = type.isJsonString;
|
|
139
|
+
exports.isMap = type.isMap;
|
|
135
140
|
exports.isNaN = type.isNaN;
|
|
136
141
|
exports.isNodeList = type.isNodeList;
|
|
137
142
|
exports.isNull = type.isNull;
|
|
@@ -140,9 +145,12 @@ exports.isNullish = type.isNullOrUnDef;
|
|
|
140
145
|
exports.isNumber = type.isNumber;
|
|
141
146
|
exports.isObject = type.isObject;
|
|
142
147
|
exports.isPrimitive = type.isPrimitive;
|
|
148
|
+
exports.isPromise = type.isPromise;
|
|
143
149
|
exports.isRegExp = type.isRegExp;
|
|
150
|
+
exports.isSet = type.isSet;
|
|
144
151
|
exports.isString = type.isString;
|
|
145
152
|
exports.isSymbol = type.isSymbol;
|
|
153
|
+
exports.isTypedArray = type.isTypedArray;
|
|
146
154
|
exports.isUndefined = type.isUndefined;
|
|
147
155
|
exports.objectHas = type.objectHas;
|
|
148
156
|
exports.typeIs = type.typeIs;
|
package/dist/cjs/isEqual.cjs
CHANGED
package/dist/cjs/math.cjs
CHANGED
package/dist/cjs/number.cjs
CHANGED
package/dist/cjs/object.cjs
CHANGED
package/dist/cjs/path.cjs
CHANGED