@cloudcome/utils-core 1.15.7 → 1.17.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 +54 -33
- package/dist/array.cjs.map +1 -1
- package/dist/array.d.ts +27 -9
- package/dist/array.mjs +54 -33
- package/dist/array.mjs.map +1 -1
- package/dist/core.cjs +44 -40
- package/dist/core.cjs.map +1 -1
- package/dist/core.mjs +44 -40
- package/dist/core.mjs.map +1 -1
- package/dist/date/core.d.ts +3 -3
- package/dist/date/timezone.d.ts +28 -20
- package/dist/date.cjs +1 -1
- package/dist/date.mjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/dist/array.cjs
CHANGED
|
@@ -71,59 +71,80 @@ function arrayMove(array, from, to) {
|
|
|
71
71
|
array2.splice(to, 0, item);
|
|
72
72
|
return array2;
|
|
73
73
|
}
|
|
74
|
-
function arrayDiff(refArray, curArray) {
|
|
74
|
+
function arrayDiff(refArray, curArray, options) {
|
|
75
|
+
const { getItemKey = (item) => item } = options || {};
|
|
76
|
+
const toKeyIndexes = (map, item) => {
|
|
77
|
+
const key = getItemKey(item);
|
|
78
|
+
return {
|
|
79
|
+
key,
|
|
80
|
+
indexes: map.get(key) || []
|
|
81
|
+
};
|
|
82
|
+
};
|
|
75
83
|
const buildMap = (arr) => {
|
|
76
84
|
const map = /* @__PURE__ */ new Map();
|
|
77
85
|
arr.forEach((item, index) => {
|
|
78
|
-
const indexes = map
|
|
86
|
+
const { key, indexes } = toKeyIndexes(map, item);
|
|
79
87
|
indexes.push(index);
|
|
80
|
-
map.set(
|
|
88
|
+
map.set(key, indexes);
|
|
81
89
|
});
|
|
82
90
|
return map;
|
|
83
91
|
};
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
const toIndexesArr = (arr, indexes) => {
|
|
93
|
+
return indexes.map((index) => arr[index]);
|
|
94
|
+
};
|
|
95
|
+
const refMap = buildMap(refArray);
|
|
96
|
+
const curMap = buildMap(curArray);
|
|
97
|
+
const deleteSet = /* @__PURE__ */ new Set();
|
|
98
|
+
const addSet = /* @__PURE__ */ new Set();
|
|
99
|
+
const equalSet = /* @__PURE__ */ new Set();
|
|
100
|
+
for (const key of refMap.keys()) {
|
|
101
|
+
if (curMap.has(key)) {
|
|
102
|
+
equalSet.add(key);
|
|
92
103
|
} else {
|
|
93
|
-
|
|
104
|
+
deleteSet.add(key);
|
|
94
105
|
}
|
|
95
106
|
}
|
|
96
|
-
for (const key of
|
|
97
|
-
if (!
|
|
98
|
-
|
|
107
|
+
for (const key of curMap.keys()) {
|
|
108
|
+
if (!refMap.has(key)) {
|
|
109
|
+
addSet.add(key);
|
|
99
110
|
}
|
|
100
111
|
}
|
|
101
112
|
return {
|
|
102
|
-
deletes: [...
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
113
|
+
deletes: [...deleteSet].map((key) => {
|
|
114
|
+
const indexes = refMap.get(key) || [];
|
|
115
|
+
return {
|
|
116
|
+
refIndexes: indexes,
|
|
117
|
+
refValues: toIndexesArr(refArray, indexes)
|
|
118
|
+
};
|
|
119
|
+
}),
|
|
120
|
+
adds: [...addSet].map((key) => {
|
|
121
|
+
const indexes = curMap.get(key) || [];
|
|
122
|
+
return {
|
|
123
|
+
curIndexes: indexes,
|
|
124
|
+
curValues: toIndexesArr(curArray, indexes)
|
|
125
|
+
};
|
|
126
|
+
}),
|
|
127
|
+
equals: [...equalSet].map((key) => {
|
|
128
|
+
const refIndexes = refMap.get(key) || [];
|
|
129
|
+
const curIndexes = curMap.get(key) || [];
|
|
130
|
+
return {
|
|
131
|
+
refIndexes,
|
|
132
|
+
curIndexes,
|
|
133
|
+
refValues: toIndexesArr(refArray, refIndexes),
|
|
134
|
+
curValues: toIndexesArr(curArray, curIndexes)
|
|
135
|
+
};
|
|
136
|
+
})
|
|
120
137
|
};
|
|
121
138
|
}
|
|
139
|
+
function arrayRemove(array, indexes) {
|
|
140
|
+
return array.filter((item, index) => !indexes.includes(index));
|
|
141
|
+
}
|
|
122
142
|
exports.arrayDiff = arrayDiff;
|
|
123
143
|
exports.arrayEach = arrayEach;
|
|
124
144
|
exports.arrayEachAsync = arrayEachAsync;
|
|
125
145
|
exports.arrayMove = arrayMove;
|
|
126
146
|
exports.arrayOmit = arrayOmit;
|
|
127
147
|
exports.arrayPick = arrayPick;
|
|
148
|
+
exports.arrayRemove = arrayRemove;
|
|
128
149
|
exports.isArrayLike = isArrayLike;
|
|
129
150
|
//# sourceMappingURL=array.cjs.map
|
package/dist/array.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.cjs","sources":["../src/array.ts"],"sourcesContent":["import { isArray, isObject } from './type';\nimport type { MaybePromise } from './types';\n\n/**\n * 检查给定的值是否为类数组对象。\n *\n * 类数组对象是指具有 `length` 属性且 `length` 属性为非负数的对象。\n *\n * @param unknown - 要检查的值。\n * @returns 如果值是类数组对象,则返回 `true`,否则返回 `false`。\n */\nexport function isArrayLike(unknown: unknown) {\n if (isArray(unknown)) return true;\n\n if (isObject(unknown)) {\n const arrayLike = unknown as { length: unknown };\n return typeof arrayLike.length === 'number' && arrayLike.length >= 0;\n }\n\n return false;\n}\n\n/**\n * 从数组中选择指定索引的元素。\n *\n * @param array - 要从中选择元素的数组。\n * @param indexes - 要选择的元素的索引数组。\n * @returns 包含指定索引元素的新数组。\n */\nexport function arrayPick<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return false;\n indexes2.splice(index, 1);\n return true;\n });\n}\n\n/**\n * 从数组中排除指定索引的元素。\n *\n * @param array - 要从中排除元素的数组。\n * @param indexes - 要排除的元素的索引数组。\n * @returns 包含排除指定索引元素后的新数组。\n */\nexport function arrayOmit<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return true;\n indexes2.splice(index, 1);\n return false;\n });\n}\n\n/**\n * 遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * arrayEach(arr, (item, index) => {\n * console.log(item, index);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport function arrayEach<T>(array: T[], iterator: (item: T, index: number) => false | unknown, reverse = false) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 异步遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的异步回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * await arrayEachAsync(arr, async (item, index) => {\n * await someAsyncOperation(item);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport async function arrayEachAsync<T>(\n array: T[],\n iterator: (item: T, index: number) => MaybePromise<false | unknown>,\n reverse = false,\n) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 将数组中的元素移动到指定位置。\n *\n * @param array - 要移动元素的数组。\n * @param from - 要移动的元素的起始位置。\n * @param to - 要移动的元素的目标位置。\n * @returns 新的数组,其中包含移动后的元素。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3, 4, 5];\n * const newArr = arrayMove(arr, 1, 3);\n * // 返回 [1, 3, 4, 2, 5]\n * ```\n */\nexport function arrayMove<T>(array: T[], from: number, to: number) {\n const array2 = [...array];\n\n if (from < 0 || from >= array2.length || to < 0 || to >= array2.length) {\n return array2;\n }\n\n const item = array2[from];\n\n array2.splice(from, 1);\n array2.splice(to, 0, item);\n\n return array2;\n}\n\n/**\n * 比较两个数组的差异,返回包含删除、新增和相同元素信息的对象\n *\n * @template T - 数组元素的类型\n * @param {T[]} refArray - 参考数组(原始数组)\n * @param {T[]} curArray - 当前数组(比较数组)\n * @returns {ArrayDiffs<T>} 包含差异信息的对象\n *\n * @example\n * ```typescript\n * const ref = [1, 2, 3];\n * const cur = [2, 3, 4];\n * const diff = arrayDiff(ref, cur);\n * // 返回结果:\n * // {\n * // deletes: [{refIndexes: [0], refValue: 1}],\n * // adds: [{curIndexes: [2], curValue: 4}],\n * // equals: [\n * // {refIndexes: [1], curIndexes: [0], refValue: 2, curValue: 2},\n * // {refIndexes: [2], curIndexes: [1], refValue: 3, curValue: 3}\n * // ]\n * // }\n * ```\n */\nexport type ArrayDiffs<T> = {\n /**\n * 被删除的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {T} refValue - 被删除的元素值\n */\n deletes: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 被删除的元素值\n * @type {T}\n */\n refValue: T;\n }[];\n\n /**\n * 新增的元素列表\n * @type {Array}\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} curValue - 新增的元素值\n */\n adds: {\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 新增的元素值\n * @type {T}\n */\n curValue: T;\n }[];\n\n /**\n * 相同的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} refValue - 参考数组中的元素值\n * @property {T} curValue - 当前数组中的元素值\n */\n equals: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 参考数组中的元素值\n * @type {T}\n */\n refValue: T;\n /**\n * 当前数组中的元素值\n * @type {T}\n */\n curValue: T;\n }[];\n};\n\nexport function arrayDiff<T>(refArray: T[], curArray: T[]): ArrayDiffs<T> {\n const buildMap = (arr: T[]) => {\n const map = new Map<T, number[]>();\n\n arr.forEach((item, index) => {\n const indexes = map.get(item) || [];\n indexes.push(index);\n map.set(item, indexes);\n });\n\n return map;\n };\n const map1 = buildMap(refArray);\n const map2 = buildMap(curArray);\n const deletes = new Set<T>();\n const adds = new Set<T>();\n const equals = new Set<T>();\n\n for (const key of map1.keys()) {\n if (map2.has(key)) {\n equals.add(key);\n } else {\n deletes.add(key);\n }\n }\n\n for (const key of map2.keys()) {\n if (!map1.has(key)) {\n adds.add(key);\n }\n }\n\n return {\n deletes: [...deletes].map((it) => ({\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n refIndexes: map1.get(it)!,\n refValue: it,\n })),\n\n adds: [...adds].map((it) => ({\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n curIndexes: map2.get(it)!,\n curValue: it,\n })),\n\n equals: [...equals].map((it) => ({\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n refIndexes: map1.get(it)!,\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n curIndexes: map2.get(it)!,\n refValue: it,\n curValue: it,\n })),\n };\n}\n"],"names":["isArray","isObject"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"array.cjs","sources":["../src/array.ts"],"sourcesContent":["import { isArray, isObject } from './type';\nimport type { MaybePromise } from './types';\n\n/**\n * 检查给定的值是否为类数组对象。\n *\n * 类数组对象是指具有 `length` 属性且 `length` 属性为非负数的对象。\n *\n * @param unknown - 要检查的值。\n * @returns 如果值是类数组对象,则返回 `true`,否则返回 `false`。\n */\nexport function isArrayLike(unknown: unknown) {\n if (isArray(unknown)) return true;\n\n if (isObject(unknown)) {\n const arrayLike = unknown as { length: unknown };\n return typeof arrayLike.length === 'number' && arrayLike.length >= 0;\n }\n\n return false;\n}\n\n/**\n * 从数组中选择指定索引的元素。\n *\n * @param array - 要从中选择元素的数组。\n * @param indexes - 要选择的元素的索引数组。\n * @returns 包含指定索引元素的新数组。\n */\nexport function arrayPick<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return false;\n indexes2.splice(index, 1);\n return true;\n });\n}\n\n/**\n * 从数组中排除指定索引的元素。\n *\n * @param array - 要从中排除元素的数组。\n * @param indexes - 要排除的元素的索引数组。\n * @returns 包含排除指定索引元素后的新数组。\n */\nexport function arrayOmit<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return true;\n indexes2.splice(index, 1);\n return false;\n });\n}\n\n/**\n * 遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * arrayEach(arr, (item, index) => {\n * console.log(item, index);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport function arrayEach<T>(array: T[], iterator: (item: T, index: number) => false | unknown, reverse = false) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 异步遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的异步回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * await arrayEachAsync(arr, async (item, index) => {\n * await someAsyncOperation(item);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport async function arrayEachAsync<T>(\n array: T[],\n iterator: (item: T, index: number) => MaybePromise<false | unknown>,\n reverse = false,\n) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 将数组中的元素移动到指定位置。\n *\n * @param array - 要移动元素的数组。\n * @param from - 要移动的元素的起始位置。\n * @param to - 要移动的元素的目标位置。\n * @returns 新的数组,其中包含移动后的元素。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3, 4, 5];\n * const newArr = arrayMove(arr, 1, 3);\n * // 返回 [1, 3, 4, 2, 5]\n * ```\n */\nexport function arrayMove<T>(array: T[], from: number, to: number) {\n const array2 = [...array];\n\n if (from < 0 || from >= array2.length || to < 0 || to >= array2.length) {\n return array2;\n }\n\n const item = array2[from];\n\n array2.splice(from, 1);\n array2.splice(to, 0, item);\n\n return array2;\n}\n\n/**\n * 比较两个数组的差异,返回包含删除、新增和相同元素信息的对象\n *\n * @template T - 数组元素的类型\n * @param {T[]} refArray - 参考数组(原始数组)\n * @param {T[]} curArray - 当前数组(比较数组)\n * @returns {ArrayDiffs<T>} 包含差异信息的对象\n *\n * @example\n * ```typescript\n * const ref = [1, 2, 3];\n * const cur = [2, 3, 4];\n * const diff = arrayDiff(ref, cur);\n * // 返回结果:\n * // {\n * // deletes: [{refIndexes: [0], refValue: 1}],\n * // adds: [{curIndexes: [2], curValue: 4}],\n * // equals: [\n * // {refIndexes: [1], curIndexes: [0], refValue: 2, curValue: 2},\n * // {refIndexes: [2], curIndexes: [1], refValue: 3, curValue: 3}\n * // ]\n * // }\n * ```\n */\nexport type ArrayDiffs<T> = {\n /**\n * 被删除的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {T} refValue - 被删除的元素值\n */\n deletes: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 被删除的元素值\n * @type {T[]}\n */\n refValues: T[];\n }[];\n\n /**\n * 新增的元素列表\n * @type {Array}\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} curValue - 新增的元素值\n */\n adds: {\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 新增的元素值\n * @type {T[]}\n */\n curValues: T[];\n }[];\n\n /**\n * 相同的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} refValue - 参考数组中的元素值\n * @property {T} curValue - 当前数组中的元素值\n */\n equals: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 参考数组中的元素值\n * @type {T[]}\n */\n refValues: T[];\n /**\n * 当前数组中的元素值\n * @type {T[]}\n */\n curValues: T[];\n }[];\n};\n\nexport type ArrayDiffOptions<T> = {\n getItemKey: (item: T) => unknown;\n};\n\nexport function arrayDiff<T>(refArray: T[], curArray: T[], options?: ArrayDiffOptions<T>): ArrayDiffs<T> {\n const { getItemKey = (item: T) => item } = options || {};\n\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n type Key = any;\n\n const toKeyIndexes = (map: Map<Key, number[]>, item: T) => {\n const key = getItemKey(item);\n return {\n key,\n indexes: map.get(key) || [],\n };\n };\n\n const buildMap = (arr: T[]) => {\n const map = new Map<Key, number[]>();\n\n arr.forEach((item, index) => {\n const { key, indexes } = toKeyIndexes(map, item);\n indexes.push(index);\n map.set(key, indexes);\n });\n\n return map;\n };\n\n const toIndexesArr = (arr: T[], indexes: number[]) => {\n return indexes.map((index) => arr[index]);\n };\n\n const refMap = buildMap(refArray);\n const curMap = buildMap(curArray);\n const deleteSet = new Set<Key>();\n const addSet = new Set<Key>();\n const equalSet = new Set<Key>();\n\n for (const key of refMap.keys()) {\n if (curMap.has(key)) {\n equalSet.add(key);\n } else {\n deleteSet.add(key);\n }\n }\n\n for (const key of curMap.keys()) {\n if (!refMap.has(key)) {\n addSet.add(key);\n }\n }\n\n return {\n deletes: [...deleteSet].map((key) => {\n const indexes = refMap.get(key) || [];\n return {\n refIndexes: indexes,\n refValues: toIndexesArr(refArray, indexes),\n };\n }),\n\n adds: [...addSet].map((key) => {\n const indexes = curMap.get(key) || [];\n return {\n curIndexes: indexes,\n curValues: toIndexesArr(curArray, indexes),\n };\n }),\n\n equals: [...equalSet].map((key) => {\n const refIndexes = refMap.get(key) || [];\n const curIndexes = curMap.get(key) || [];\n return {\n refIndexes,\n curIndexes,\n refValues: toIndexesArr(refArray, refIndexes),\n curValues: toIndexesArr(curArray, curIndexes),\n };\n }),\n };\n}\n\n/**\n * 从数组中移除指定索引的元素\n * @template T - 数组元素的类型\n * @param {T[]} array - 原始数组\n * @param {number[]} indexes - 要移除的元素索引数组\n * @returns {T[]} 移除指定索引元素后的新数组\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3, 4, 5];\n * const newArr = arrayRemove(arr, [1, 3]);\n * // 返回结果: [1, 3, 5]\n * ```\n */\nexport function arrayRemove<T>(array: T[], indexes: number[]) {\n return array.filter((item, index) => !indexes.includes(index));\n}\n"],"names":["isArray","isObject"],"mappings":"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"}
|
package/dist/array.d.ts
CHANGED
|
@@ -115,9 +115,9 @@ export type ArrayDiffs<T> = {
|
|
|
115
115
|
refIndexes: number[];
|
|
116
116
|
/**
|
|
117
117
|
* 被删除的元素值
|
|
118
|
-
* @type {T}
|
|
118
|
+
* @type {T[]}
|
|
119
119
|
*/
|
|
120
|
-
|
|
120
|
+
refValues: T[];
|
|
121
121
|
}[];
|
|
122
122
|
/**
|
|
123
123
|
* 新增的元素列表
|
|
@@ -133,9 +133,9 @@ export type ArrayDiffs<T> = {
|
|
|
133
133
|
curIndexes: number[];
|
|
134
134
|
/**
|
|
135
135
|
* 新增的元素值
|
|
136
|
-
* @type {T}
|
|
136
|
+
* @type {T[]}
|
|
137
137
|
*/
|
|
138
|
-
|
|
138
|
+
curValues: T[];
|
|
139
139
|
}[];
|
|
140
140
|
/**
|
|
141
141
|
* 相同的元素列表
|
|
@@ -158,14 +158,32 @@ export type ArrayDiffs<T> = {
|
|
|
158
158
|
curIndexes: number[];
|
|
159
159
|
/**
|
|
160
160
|
* 参考数组中的元素值
|
|
161
|
-
* @type {T}
|
|
161
|
+
* @type {T[]}
|
|
162
162
|
*/
|
|
163
|
-
|
|
163
|
+
refValues: T[];
|
|
164
164
|
/**
|
|
165
165
|
* 当前数组中的元素值
|
|
166
|
-
* @type {T}
|
|
166
|
+
* @type {T[]}
|
|
167
167
|
*/
|
|
168
|
-
|
|
168
|
+
curValues: T[];
|
|
169
169
|
}[];
|
|
170
170
|
};
|
|
171
|
-
export
|
|
171
|
+
export type ArrayDiffOptions<T> = {
|
|
172
|
+
getItemKey: (item: T) => unknown;
|
|
173
|
+
};
|
|
174
|
+
export declare function arrayDiff<T>(refArray: T[], curArray: T[], options?: ArrayDiffOptions<T>): ArrayDiffs<T>;
|
|
175
|
+
/**
|
|
176
|
+
* 从数组中移除指定索引的元素
|
|
177
|
+
* @template T - 数组元素的类型
|
|
178
|
+
* @param {T[]} array - 原始数组
|
|
179
|
+
* @param {number[]} indexes - 要移除的元素索引数组
|
|
180
|
+
* @returns {T[]} 移除指定索引元素后的新数组
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* const arr = [1, 2, 3, 4, 5];
|
|
185
|
+
* const newArr = arrayRemove(arr, [1, 3]);
|
|
186
|
+
* // 返回结果: [1, 3, 5]
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
export declare function arrayRemove<T>(array: T[], indexes: number[]): T[];
|
package/dist/array.mjs
CHANGED
|
@@ -69,54 +69,74 @@ function arrayMove(array, from, to) {
|
|
|
69
69
|
array2.splice(to, 0, item);
|
|
70
70
|
return array2;
|
|
71
71
|
}
|
|
72
|
-
function arrayDiff(refArray, curArray) {
|
|
72
|
+
function arrayDiff(refArray, curArray, options) {
|
|
73
|
+
const { getItemKey = (item) => item } = options || {};
|
|
74
|
+
const toKeyIndexes = (map, item) => {
|
|
75
|
+
const key = getItemKey(item);
|
|
76
|
+
return {
|
|
77
|
+
key,
|
|
78
|
+
indexes: map.get(key) || []
|
|
79
|
+
};
|
|
80
|
+
};
|
|
73
81
|
const buildMap = (arr) => {
|
|
74
82
|
const map = /* @__PURE__ */ new Map();
|
|
75
83
|
arr.forEach((item, index) => {
|
|
76
|
-
const indexes = map
|
|
84
|
+
const { key, indexes } = toKeyIndexes(map, item);
|
|
77
85
|
indexes.push(index);
|
|
78
|
-
map.set(
|
|
86
|
+
map.set(key, indexes);
|
|
79
87
|
});
|
|
80
88
|
return map;
|
|
81
89
|
};
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
const toIndexesArr = (arr, indexes) => {
|
|
91
|
+
return indexes.map((index) => arr[index]);
|
|
92
|
+
};
|
|
93
|
+
const refMap = buildMap(refArray);
|
|
94
|
+
const curMap = buildMap(curArray);
|
|
95
|
+
const deleteSet = /* @__PURE__ */ new Set();
|
|
96
|
+
const addSet = /* @__PURE__ */ new Set();
|
|
97
|
+
const equalSet = /* @__PURE__ */ new Set();
|
|
98
|
+
for (const key of refMap.keys()) {
|
|
99
|
+
if (curMap.has(key)) {
|
|
100
|
+
equalSet.add(key);
|
|
90
101
|
} else {
|
|
91
|
-
|
|
102
|
+
deleteSet.add(key);
|
|
92
103
|
}
|
|
93
104
|
}
|
|
94
|
-
for (const key of
|
|
95
|
-
if (!
|
|
96
|
-
|
|
105
|
+
for (const key of curMap.keys()) {
|
|
106
|
+
if (!refMap.has(key)) {
|
|
107
|
+
addSet.add(key);
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
return {
|
|
100
|
-
deletes: [...
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
deletes: [...deleteSet].map((key) => {
|
|
112
|
+
const indexes = refMap.get(key) || [];
|
|
113
|
+
return {
|
|
114
|
+
refIndexes: indexes,
|
|
115
|
+
refValues: toIndexesArr(refArray, indexes)
|
|
116
|
+
};
|
|
117
|
+
}),
|
|
118
|
+
adds: [...addSet].map((key) => {
|
|
119
|
+
const indexes = curMap.get(key) || [];
|
|
120
|
+
return {
|
|
121
|
+
curIndexes: indexes,
|
|
122
|
+
curValues: toIndexesArr(curArray, indexes)
|
|
123
|
+
};
|
|
124
|
+
}),
|
|
125
|
+
equals: [...equalSet].map((key) => {
|
|
126
|
+
const refIndexes = refMap.get(key) || [];
|
|
127
|
+
const curIndexes = curMap.get(key) || [];
|
|
128
|
+
return {
|
|
129
|
+
refIndexes,
|
|
130
|
+
curIndexes,
|
|
131
|
+
refValues: toIndexesArr(refArray, refIndexes),
|
|
132
|
+
curValues: toIndexesArr(curArray, curIndexes)
|
|
133
|
+
};
|
|
134
|
+
})
|
|
118
135
|
};
|
|
119
136
|
}
|
|
137
|
+
function arrayRemove(array, indexes) {
|
|
138
|
+
return array.filter((item, index) => !indexes.includes(index));
|
|
139
|
+
}
|
|
120
140
|
export {
|
|
121
141
|
arrayDiff,
|
|
122
142
|
arrayEach,
|
|
@@ -124,6 +144,7 @@ export {
|
|
|
124
144
|
arrayMove,
|
|
125
145
|
arrayOmit,
|
|
126
146
|
arrayPick,
|
|
147
|
+
arrayRemove,
|
|
127
148
|
isArrayLike
|
|
128
149
|
};
|
|
129
150
|
//# sourceMappingURL=array.mjs.map
|
package/dist/array.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.mjs","sources":["../src/array.ts"],"sourcesContent":["import { isArray, isObject } from './type';\nimport type { MaybePromise } from './types';\n\n/**\n * 检查给定的值是否为类数组对象。\n *\n * 类数组对象是指具有 `length` 属性且 `length` 属性为非负数的对象。\n *\n * @param unknown - 要检查的值。\n * @returns 如果值是类数组对象,则返回 `true`,否则返回 `false`。\n */\nexport function isArrayLike(unknown: unknown) {\n if (isArray(unknown)) return true;\n\n if (isObject(unknown)) {\n const arrayLike = unknown as { length: unknown };\n return typeof arrayLike.length === 'number' && arrayLike.length >= 0;\n }\n\n return false;\n}\n\n/**\n * 从数组中选择指定索引的元素。\n *\n * @param array - 要从中选择元素的数组。\n * @param indexes - 要选择的元素的索引数组。\n * @returns 包含指定索引元素的新数组。\n */\nexport function arrayPick<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return false;\n indexes2.splice(index, 1);\n return true;\n });\n}\n\n/**\n * 从数组中排除指定索引的元素。\n *\n * @param array - 要从中排除元素的数组。\n * @param indexes - 要排除的元素的索引数组。\n * @returns 包含排除指定索引元素后的新数组。\n */\nexport function arrayOmit<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return true;\n indexes2.splice(index, 1);\n return false;\n });\n}\n\n/**\n * 遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * arrayEach(arr, (item, index) => {\n * console.log(item, index);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport function arrayEach<T>(array: T[], iterator: (item: T, index: number) => false | unknown, reverse = false) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 异步遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的异步回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * await arrayEachAsync(arr, async (item, index) => {\n * await someAsyncOperation(item);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport async function arrayEachAsync<T>(\n array: T[],\n iterator: (item: T, index: number) => MaybePromise<false | unknown>,\n reverse = false,\n) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 将数组中的元素移动到指定位置。\n *\n * @param array - 要移动元素的数组。\n * @param from - 要移动的元素的起始位置。\n * @param to - 要移动的元素的目标位置。\n * @returns 新的数组,其中包含移动后的元素。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3, 4, 5];\n * const newArr = arrayMove(arr, 1, 3);\n * // 返回 [1, 3, 4, 2, 5]\n * ```\n */\nexport function arrayMove<T>(array: T[], from: number, to: number) {\n const array2 = [...array];\n\n if (from < 0 || from >= array2.length || to < 0 || to >= array2.length) {\n return array2;\n }\n\n const item = array2[from];\n\n array2.splice(from, 1);\n array2.splice(to, 0, item);\n\n return array2;\n}\n\n/**\n * 比较两个数组的差异,返回包含删除、新增和相同元素信息的对象\n *\n * @template T - 数组元素的类型\n * @param {T[]} refArray - 参考数组(原始数组)\n * @param {T[]} curArray - 当前数组(比较数组)\n * @returns {ArrayDiffs<T>} 包含差异信息的对象\n *\n * @example\n * ```typescript\n * const ref = [1, 2, 3];\n * const cur = [2, 3, 4];\n * const diff = arrayDiff(ref, cur);\n * // 返回结果:\n * // {\n * // deletes: [{refIndexes: [0], refValue: 1}],\n * // adds: [{curIndexes: [2], curValue: 4}],\n * // equals: [\n * // {refIndexes: [1], curIndexes: [0], refValue: 2, curValue: 2},\n * // {refIndexes: [2], curIndexes: [1], refValue: 3, curValue: 3}\n * // ]\n * // }\n * ```\n */\nexport type ArrayDiffs<T> = {\n /**\n * 被删除的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {T} refValue - 被删除的元素值\n */\n deletes: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 被删除的元素值\n * @type {T}\n */\n refValue: T;\n }[];\n\n /**\n * 新增的元素列表\n * @type {Array}\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} curValue - 新增的元素值\n */\n adds: {\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 新增的元素值\n * @type {T}\n */\n curValue: T;\n }[];\n\n /**\n * 相同的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} refValue - 参考数组中的元素值\n * @property {T} curValue - 当前数组中的元素值\n */\n equals: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 参考数组中的元素值\n * @type {T}\n */\n refValue: T;\n /**\n * 当前数组中的元素值\n * @type {T}\n */\n curValue: T;\n }[];\n};\n\nexport function arrayDiff<T>(refArray: T[], curArray: T[]): ArrayDiffs<T> {\n const buildMap = (arr: T[]) => {\n const map = new Map<T, number[]>();\n\n arr.forEach((item, index) => {\n const indexes = map.get(item) || [];\n indexes.push(index);\n map.set(item, indexes);\n });\n\n return map;\n };\n const map1 = buildMap(refArray);\n const map2 = buildMap(curArray);\n const deletes = new Set<T>();\n const adds = new Set<T>();\n const equals = new Set<T>();\n\n for (const key of map1.keys()) {\n if (map2.has(key)) {\n equals.add(key);\n } else {\n deletes.add(key);\n }\n }\n\n for (const key of map2.keys()) {\n if (!map1.has(key)) {\n adds.add(key);\n }\n }\n\n return {\n deletes: [...deletes].map((it) => ({\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n refIndexes: map1.get(it)!,\n refValue: it,\n })),\n\n adds: [...adds].map((it) => ({\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n curIndexes: map2.get(it)!,\n curValue: it,\n })),\n\n equals: [...equals].map((it) => ({\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n refIndexes: map1.get(it)!,\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n curIndexes: map2.get(it)!,\n refValue: it,\n curValue: it,\n })),\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"array.mjs","sources":["../src/array.ts"],"sourcesContent":["import { isArray, isObject } from './type';\nimport type { MaybePromise } from './types';\n\n/**\n * 检查给定的值是否为类数组对象。\n *\n * 类数组对象是指具有 `length` 属性且 `length` 属性为非负数的对象。\n *\n * @param unknown - 要检查的值。\n * @returns 如果值是类数组对象,则返回 `true`,否则返回 `false`。\n */\nexport function isArrayLike(unknown: unknown) {\n if (isArray(unknown)) return true;\n\n if (isObject(unknown)) {\n const arrayLike = unknown as { length: unknown };\n return typeof arrayLike.length === 'number' && arrayLike.length >= 0;\n }\n\n return false;\n}\n\n/**\n * 从数组中选择指定索引的元素。\n *\n * @param array - 要从中选择元素的数组。\n * @param indexes - 要选择的元素的索引数组。\n * @returns 包含指定索引元素的新数组。\n */\nexport function arrayPick<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return false;\n indexes2.splice(index, 1);\n return true;\n });\n}\n\n/**\n * 从数组中排除指定索引的元素。\n *\n * @param array - 要从中排除元素的数组。\n * @param indexes - 要排除的元素的索引数组。\n * @returns 包含排除指定索引元素后的新数组。\n */\nexport function arrayOmit<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return true;\n indexes2.splice(index, 1);\n return false;\n });\n}\n\n/**\n * 遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * arrayEach(arr, (item, index) => {\n * console.log(item, index);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport function arrayEach<T>(array: T[], iterator: (item: T, index: number) => false | unknown, reverse = false) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 异步遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的异步回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * await arrayEachAsync(arr, async (item, index) => {\n * await someAsyncOperation(item);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport async function arrayEachAsync<T>(\n array: T[],\n iterator: (item: T, index: number) => MaybePromise<false | unknown>,\n reverse = false,\n) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 将数组中的元素移动到指定位置。\n *\n * @param array - 要移动元素的数组。\n * @param from - 要移动的元素的起始位置。\n * @param to - 要移动的元素的目标位置。\n * @returns 新的数组,其中包含移动后的元素。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3, 4, 5];\n * const newArr = arrayMove(arr, 1, 3);\n * // 返回 [1, 3, 4, 2, 5]\n * ```\n */\nexport function arrayMove<T>(array: T[], from: number, to: number) {\n const array2 = [...array];\n\n if (from < 0 || from >= array2.length || to < 0 || to >= array2.length) {\n return array2;\n }\n\n const item = array2[from];\n\n array2.splice(from, 1);\n array2.splice(to, 0, item);\n\n return array2;\n}\n\n/**\n * 比较两个数组的差异,返回包含删除、新增和相同元素信息的对象\n *\n * @template T - 数组元素的类型\n * @param {T[]} refArray - 参考数组(原始数组)\n * @param {T[]} curArray - 当前数组(比较数组)\n * @returns {ArrayDiffs<T>} 包含差异信息的对象\n *\n * @example\n * ```typescript\n * const ref = [1, 2, 3];\n * const cur = [2, 3, 4];\n * const diff = arrayDiff(ref, cur);\n * // 返回结果:\n * // {\n * // deletes: [{refIndexes: [0], refValue: 1}],\n * // adds: [{curIndexes: [2], curValue: 4}],\n * // equals: [\n * // {refIndexes: [1], curIndexes: [0], refValue: 2, curValue: 2},\n * // {refIndexes: [2], curIndexes: [1], refValue: 3, curValue: 3}\n * // ]\n * // }\n * ```\n */\nexport type ArrayDiffs<T> = {\n /**\n * 被删除的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {T} refValue - 被删除的元素值\n */\n deletes: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 被删除的元素值\n * @type {T[]}\n */\n refValues: T[];\n }[];\n\n /**\n * 新增的元素列表\n * @type {Array}\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} curValue - 新增的元素值\n */\n adds: {\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 新增的元素值\n * @type {T[]}\n */\n curValues: T[];\n }[];\n\n /**\n * 相同的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} refValue - 参考数组中的元素值\n * @property {T} curValue - 当前数组中的元素值\n */\n equals: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 参考数组中的元素值\n * @type {T[]}\n */\n refValues: T[];\n /**\n * 当前数组中的元素值\n * @type {T[]}\n */\n curValues: T[];\n }[];\n};\n\nexport type ArrayDiffOptions<T> = {\n getItemKey: (item: T) => unknown;\n};\n\nexport function arrayDiff<T>(refArray: T[], curArray: T[], options?: ArrayDiffOptions<T>): ArrayDiffs<T> {\n const { getItemKey = (item: T) => item } = options || {};\n\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n type Key = any;\n\n const toKeyIndexes = (map: Map<Key, number[]>, item: T) => {\n const key = getItemKey(item);\n return {\n key,\n indexes: map.get(key) || [],\n };\n };\n\n const buildMap = (arr: T[]) => {\n const map = new Map<Key, number[]>();\n\n arr.forEach((item, index) => {\n const { key, indexes } = toKeyIndexes(map, item);\n indexes.push(index);\n map.set(key, indexes);\n });\n\n return map;\n };\n\n const toIndexesArr = (arr: T[], indexes: number[]) => {\n return indexes.map((index) => arr[index]);\n };\n\n const refMap = buildMap(refArray);\n const curMap = buildMap(curArray);\n const deleteSet = new Set<Key>();\n const addSet = new Set<Key>();\n const equalSet = new Set<Key>();\n\n for (const key of refMap.keys()) {\n if (curMap.has(key)) {\n equalSet.add(key);\n } else {\n deleteSet.add(key);\n }\n }\n\n for (const key of curMap.keys()) {\n if (!refMap.has(key)) {\n addSet.add(key);\n }\n }\n\n return {\n deletes: [...deleteSet].map((key) => {\n const indexes = refMap.get(key) || [];\n return {\n refIndexes: indexes,\n refValues: toIndexesArr(refArray, indexes),\n };\n }),\n\n adds: [...addSet].map((key) => {\n const indexes = curMap.get(key) || [];\n return {\n curIndexes: indexes,\n curValues: toIndexesArr(curArray, indexes),\n };\n }),\n\n equals: [...equalSet].map((key) => {\n const refIndexes = refMap.get(key) || [];\n const curIndexes = curMap.get(key) || [];\n return {\n refIndexes,\n curIndexes,\n refValues: toIndexesArr(refArray, refIndexes),\n curValues: toIndexesArr(curArray, curIndexes),\n };\n }),\n };\n}\n\n/**\n * 从数组中移除指定索引的元素\n * @template T - 数组元素的类型\n * @param {T[]} array - 原始数组\n * @param {number[]} indexes - 要移除的元素索引数组\n * @returns {T[]} 移除指定索引元素后的新数组\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3, 4, 5];\n * const newArr = arrayRemove(arr, [1, 3]);\n * // 返回结果: [1, 3, 5]\n * ```\n */\nexport function arrayRemove<T>(array: T[], indexes: number[]) {\n return array.filter((item, index) => !indexes.includes(index));\n}\n"],"names":[],"mappings":"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"}
|
package/dist/core.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const type = require("./type.cjs");
|
|
3
|
-
const
|
|
4
|
-
class
|
|
3
|
+
const TIMEZONE_OFFSET_MS = 60 * 1e3;
|
|
4
|
+
class TimezoneDate {
|
|
5
5
|
/**
|
|
6
6
|
* 内部时间戳
|
|
7
7
|
*/
|
|
@@ -17,35 +17,35 @@ class TzDate {
|
|
|
17
17
|
/**
|
|
18
18
|
* 本地时区偏移量(分钟)
|
|
19
19
|
*/
|
|
20
|
-
#
|
|
20
|
+
#localTimezoneOffset = TimezoneDate.getTimezoneOffset();
|
|
21
21
|
/**
|
|
22
22
|
* 本地时区偏移量(毫秒)
|
|
23
23
|
*/
|
|
24
|
-
#
|
|
24
|
+
#localTimezoneOffsetMS = this.#localTimezoneOffset * TIMEZONE_OFFSET_MS;
|
|
25
25
|
/**
|
|
26
26
|
* 目标时区偏移量(分钟)
|
|
27
27
|
*/
|
|
28
|
-
#
|
|
28
|
+
#targetTimezoneOffset = 0;
|
|
29
29
|
/**
|
|
30
30
|
* 目标时区偏移量(毫秒)
|
|
31
31
|
*/
|
|
32
|
-
#
|
|
32
|
+
#targetTimezoneOffsetMS = 0;
|
|
33
33
|
/**
|
|
34
34
|
* 构造函数选项
|
|
35
35
|
*/
|
|
36
36
|
#options;
|
|
37
37
|
/**
|
|
38
|
-
* 构造一个
|
|
38
|
+
* 构造一个 TimezoneDate 实例
|
|
39
39
|
* @param options - 配置选项
|
|
40
40
|
*/
|
|
41
41
|
constructor(options) {
|
|
42
|
-
this.#options = (options instanceof
|
|
42
|
+
this.#options = (options instanceof TimezoneDate ? {
|
|
43
43
|
timestamp: options.getTime(),
|
|
44
|
-
|
|
44
|
+
utcOffset: options.getUTCOffset()
|
|
45
45
|
} : options) || {};
|
|
46
|
-
const {
|
|
47
|
-
this.#
|
|
48
|
-
this.#
|
|
46
|
+
const { utcOffset, timestamp, value } = this.#options;
|
|
47
|
+
this.#targetTimezoneOffset = type.isNumber(utcOffset) ? TimezoneDate.getTimezoneOffset(utcOffset) : this.#localTimezoneOffset;
|
|
48
|
+
this.#targetTimezoneOffsetMS = this.#targetTimezoneOffset * TIMEZONE_OFFSET_MS;
|
|
49
49
|
if (Array.isArray(value) && value.length > 0) {
|
|
50
50
|
const [fullYear, month, day, hours, minutes, seconds, milliseconds] = value;
|
|
51
51
|
const timestamp2 = Date.UTC(
|
|
@@ -57,33 +57,33 @@ class TzDate {
|
|
|
57
57
|
seconds ?? 0,
|
|
58
58
|
milliseconds ?? 0
|
|
59
59
|
);
|
|
60
|
-
this.#timestamp = timestamp2 + this.#
|
|
60
|
+
this.#timestamp = timestamp2 + this.#targetTimezoneOffsetMS;
|
|
61
61
|
} else {
|
|
62
62
|
this.#timestamp = timestamp || Date.now();
|
|
63
63
|
}
|
|
64
|
-
this.#targetDate = new Date(this.#timestamp + this.#
|
|
65
|
-
this.#utcDate = new Date(this.#timestamp + this.#
|
|
64
|
+
this.#targetDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS - this.#targetTimezoneOffsetMS);
|
|
65
|
+
this.#utcDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS);
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
68
|
* 更新内部时间戳
|
|
69
69
|
*/
|
|
70
70
|
#updateTimestamp() {
|
|
71
|
-
this.#timestamp = this.#targetDate.getTime() + this.#
|
|
72
|
-
this.#utcDate = new Date(this.#timestamp + this.#
|
|
71
|
+
this.#timestamp = this.#targetDate.getTime() + this.#targetTimezoneOffsetMS - this.#localTimezoneOffsetMS;
|
|
72
|
+
this.#utcDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS);
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
75
|
* 获取时区偏移量(分钟)
|
|
76
76
|
* @returns 时区偏移量
|
|
77
77
|
*/
|
|
78
78
|
getTimezoneOffset() {
|
|
79
|
-
return this.#
|
|
79
|
+
return this.#targetTimezoneOffset;
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
|
-
*
|
|
82
|
+
* 获取时区偏移量(UTC)
|
|
83
83
|
* @returns 时区序号
|
|
84
84
|
*/
|
|
85
|
-
|
|
86
|
-
return
|
|
85
|
+
getUTCOffset() {
|
|
86
|
+
return TimezoneDate.getUTCOffset(this.#targetTimezoneOffset);
|
|
87
87
|
}
|
|
88
88
|
/**
|
|
89
89
|
* 获取年份
|
|
@@ -244,40 +244,44 @@ class TzDate {
|
|
|
244
244
|
return dateFormat(this.#utcDate, "YYYY-MM-DDTHH:mm:ss.SSSZ");
|
|
245
245
|
}
|
|
246
246
|
/**
|
|
247
|
-
*
|
|
247
|
+
* 转换为指定时区的 TimezoneDate 对象
|
|
248
248
|
* @param td - 需要转换的日期对象
|
|
249
249
|
* @param offset - 目标时区分钟偏移量,默认为当前时区
|
|
250
|
-
* @returns 返回一个
|
|
250
|
+
* @returns 返回一个 TimezoneDate 对象
|
|
251
251
|
* @example
|
|
252
252
|
* ```js
|
|
253
|
-
*
|
|
253
|
+
* // 转换为 UTC 时间
|
|
254
|
+
* const utc0Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 0);
|
|
255
|
+
*
|
|
256
|
+
* // 转换为东八区时间
|
|
257
|
+
* const utc8Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 8);
|
|
254
258
|
* ```
|
|
255
259
|
*/
|
|
256
|
-
static
|
|
257
|
-
return new
|
|
258
|
-
|
|
260
|
+
static changeUtcOffset(td, utcOffset) {
|
|
261
|
+
return new TimezoneDate({
|
|
262
|
+
utcOffset,
|
|
259
263
|
timestamp: td.getTime()
|
|
260
264
|
});
|
|
261
265
|
}
|
|
262
266
|
/**
|
|
263
|
-
*
|
|
264
|
-
* @param
|
|
265
|
-
* @returns
|
|
267
|
+
* 获取时区分钟偏移量
|
|
268
|
+
* @param utcOffset - 默认使用当前时区
|
|
269
|
+
* @returns 时区分钟偏移量
|
|
266
270
|
*/
|
|
267
|
-
static
|
|
268
|
-
return
|
|
271
|
+
static getTimezoneOffset(utcOffset) {
|
|
272
|
+
return type.isNumber(utcOffset) ? utcOffset * -60 : (/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
269
273
|
}
|
|
270
274
|
/**
|
|
271
|
-
*
|
|
272
|
-
* @param
|
|
273
|
-
* @returns
|
|
275
|
+
* 获取时区序号
|
|
276
|
+
* @param timezoneOffset - 默认使用当前时区分钟偏移量
|
|
277
|
+
* @returns 时区序号
|
|
274
278
|
*/
|
|
275
|
-
static
|
|
276
|
-
return
|
|
279
|
+
static getUTCOffset(timezoneOffset = TimezoneDate.getTimezoneOffset()) {
|
|
280
|
+
return timezoneOffset / -60;
|
|
277
281
|
}
|
|
278
282
|
}
|
|
279
283
|
function isValidDate(unknown) {
|
|
280
|
-
return unknown instanceof Date && !Number.isNaN(unknown.getTime()) || unknown instanceof
|
|
284
|
+
return unknown instanceof Date && !Number.isNaN(unknown.getTime()) || unknown instanceof TimezoneDate && !Number.isNaN(unknown.getTime());
|
|
281
285
|
}
|
|
282
286
|
function _guessDateSeparator(value) {
|
|
283
287
|
if (!type.isString(value)) return;
|
|
@@ -301,7 +305,7 @@ function _guessDateTimezone(value) {
|
|
|
301
305
|
return d;
|
|
302
306
|
}
|
|
303
307
|
function dateParse(dateValue) {
|
|
304
|
-
const d1 = type.isDate(dateValue) ? new Date(dateValue) : dateValue instanceof
|
|
308
|
+
const d1 = type.isDate(dateValue) ? new Date(dateValue) : dateValue instanceof TimezoneDate ? new TimezoneDate(dateValue) : new Date(dateValue);
|
|
305
309
|
if (isValidDate(d1)) return d1;
|
|
306
310
|
const d2 = _guessDateSeparator(dateValue);
|
|
307
311
|
if (isValidDate(d2)) return d2;
|
|
@@ -351,7 +355,7 @@ function dateFormat(dateValue, format = "YYYY-MM-DD HH:mm:ss") {
|
|
|
351
355
|
}
|
|
352
356
|
return result;
|
|
353
357
|
}
|
|
354
|
-
exports.
|
|
358
|
+
exports.TimezoneDate = TimezoneDate;
|
|
355
359
|
exports.dateFormat = dateFormat;
|
|
356
360
|
exports.dateParse = dateParse;
|
|
357
361
|
exports.isValidDate = isValidDate;
|
package/dist/core.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.cjs","sources":["../src/date/timezone.ts","../src/date/core.ts"],"sourcesContent":["import { isNumber } from '../type';\nimport { dateFormat } from './core';\n\nexport type TzDateOptions = {\n /**\n * 时间戳\n * @default Date.now()\n */\n timestamp?: number;\n\n /**\n * 日期值\n */\n value?: readonly [\n year?: number,\n month?: number,\n day?: number,\n hours?: number,\n minutes?: number,\n seconds?: number,\n milliseconds?: number,\n ];\n\n /**\n * 时区偏移量,单位为分钟,默认为当前时区\n */\n offset?: number;\n};\n\n/**\n * 时区偏移量毫秒常量(1分钟 = 60 * 1000 毫秒)\n */\nconst TZ_OFFSET_MS = 60 * 1000;\n\n/**\n * 时区日期类,用于处理不同时区的日期时间\n */\nexport class TzDate {\n /**\n * 内部时间戳\n */\n #timestamp: number;\n\n /**\n * 目标时区的日期对象\n */\n #targetDate: Date;\n\n /**\n * UTC 日期对象\n */\n #utcDate: Date;\n\n /**\n * 本地时区偏移量(分钟)\n */\n #localTZOffset = TzDate.getOffset();\n\n /**\n * 本地时区偏移量(毫秒)\n */\n #localTzOffsetMS = this.#localTZOffset * TZ_OFFSET_MS;\n\n /**\n * 目标时区偏移量(分钟)\n */\n #targetTzOffset = 0;\n\n /**\n * 目标时区偏移量(毫秒)\n */\n #targetTzOffsetMS = 0;\n\n /**\n * 构造函数选项\n */\n #options: TzDateOptions;\n\n /**\n * 构造一个 TzDate 实例\n * @param options - 配置选项\n */\n constructor(options?: TzDateOptions | TzDate) {\n this.#options =\n (options instanceof TzDate\n ? {\n timestamp: options.getTime(),\n offset: options.getTimezoneOffset(),\n }\n : options) || {};\n const { offset, timestamp, value } = this.#options;\n this.#targetTzOffset = isNumber(offset) ? offset : this.#localTZOffset;\n this.#targetTzOffsetMS = this.#targetTzOffset * TZ_OFFSET_MS;\n\n if (Array.isArray(value) && value.length > 0) {\n const [fullYear, month, day, hours, minutes, seconds, milliseconds] = value;\n const timestamp = Date.UTC(\n fullYear ?? 0,\n month ?? 0,\n day ?? 1,\n hours ?? 0,\n minutes ?? 0,\n seconds ?? 0,\n milliseconds ?? 0,\n );\n\n this.#timestamp = timestamp + this.#targetTzOffsetMS;\n } else {\n this.#timestamp = timestamp || Date.now();\n }\n\n this.#targetDate = new Date(this.#timestamp + this.#localTzOffsetMS - this.#targetTzOffsetMS);\n this.#utcDate = new Date(this.#timestamp + this.#localTzOffsetMS);\n }\n\n /**\n * 更新内部时间戳\n */\n #updateTimestamp() {\n this.#timestamp = this.#targetDate.getTime() + this.#targetTzOffsetMS - this.#localTzOffsetMS;\n this.#utcDate = new Date(this.#timestamp + this.#localTzOffsetMS);\n }\n\n /**\n * 获取时区偏移量(分钟)\n * @returns 时区偏移量\n */\n getTimezoneOffset() {\n return this.#targetTzOffset;\n }\n\n /**\n * 获取时区序号\n * @returns 时区序号\n */\n getTimezoneOrder() {\n return TzDate.getOrder(this.#targetTzOffset);\n }\n\n /**\n * 获取年份\n * @returns 年份\n */\n getFullYear() {\n return this.#targetDate.getFullYear();\n }\n\n /**\n * 获取月份\n * @returns 月份 (0-11)\n */\n getMonth() {\n return this.#targetDate.getMonth();\n }\n\n /**\n * 获取日期\n * @returns 日期 (1-31)\n */\n getDate() {\n return this.#targetDate.getDate();\n }\n\n /**\n * 获取小时\n * @returns 小时 (0-23)\n */\n getHours() {\n return this.#targetDate.getHours();\n }\n\n /**\n * 获取分钟\n * @returns 分钟 (0-59)\n */\n getMinutes() {\n return this.#targetDate.getMinutes();\n }\n\n /**\n * 获取秒数\n * @returns 秒数 (0-59)\n */\n getSeconds() {\n return this.#targetDate.getSeconds();\n }\n\n /**\n * 获取毫秒\n * @returns 毫秒 (0-999)\n */\n getMilliseconds() {\n return this.#targetDate.getMilliseconds();\n }\n\n /**\n * 设置年份\n * @param year - 年份\n * @param month - 月份\n * @param date - 日期\n * @returns 时间戳\n */\n setFullYear(year: number, month?: number, date?: number) {\n this.#targetDate.setFullYear(year);\n this.#updateTimestamp();\n\n if (isNumber(month)) this.setMonth(month);\n if (isNumber(date)) this.setDate(date);\n\n return this.getTime();\n }\n\n /**\n * 设置月份\n * @param month - 月份\n * @param date - 日期\n * @returns 时间戳\n */\n setMonth(month: number, date?: number) {\n this.#targetDate.setMonth(month);\n this.#updateTimestamp();\n\n if (isNumber(date)) this.setDate(date);\n\n return this.getTime();\n }\n\n /**\n * 设置日期\n * @param date - 日期\n * @returns 时间戳\n */\n setDate(date: number) {\n this.#targetDate.setDate(date);\n this.#updateTimestamp();\n\n return this.getTime();\n }\n\n /**\n * 设置小时\n * @param hours - 小时\n * @param minutes - 分钟\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setHours(hours: number, minutes?: number, seconds?: number, milliseconds?: number) {\n this.#targetDate.setHours(hours);\n this.#updateTimestamp();\n\n if (isNumber(minutes)) this.setMinutes(minutes);\n if (isNumber(seconds)) this.setSeconds(seconds);\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置分钟\n * @param minutes - 分钟\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setMinutes(minutes: number, seconds?: number, milliseconds?: number) {\n this.#targetDate.setMinutes(minutes);\n this.#updateTimestamp();\n\n if (isNumber(seconds)) this.setSeconds(seconds);\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置秒数\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setSeconds(seconds: number, milliseconds?: number) {\n this.#targetDate.setSeconds(seconds);\n this.#updateTimestamp();\n\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置毫秒\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setMilliseconds(milliseconds: number) {\n this.#targetDate.setMilliseconds(milliseconds);\n this.#updateTimestamp();\n\n return this.getTime();\n }\n\n /**\n * 获取时间戳\n * @returns 时间戳\n */\n getTime() {\n return this.#timestamp;\n }\n\n /**\n * 获取星期几\n * @returns 星期几 (0-6, 0表示周日)\n */\n getDay() {\n return this.#targetDate.getDay();\n }\n\n /**\n * 转换为 ISO 格式的字符串\n * @returns ISO 格式的时间字符串\n */\n toISOString() {\n return dateFormat(this.#utcDate, 'YYYY-MM-DDTHH:mm:ss.SSSZ');\n }\n\n /**\n * 创建一个 TzDate 对象\n * @param td - 需要转换的日期对象\n * @param offset - 目标时区分钟偏移量,默认为当前时区\n * @returns 返回一个 TzDate 对象\n * @example\n * ```js\n * const tzDate = TzDate.from(new TzDate());\n * ```\n */\n static from(td: TzDate, offset = TzDate.getOffset()) {\n return new TzDate({\n offset: offset,\n timestamp: td.getTime(),\n });\n }\n\n /**\n * 获取时区序号\n * @param offset - 默认使用当前时区分钟偏移量\n * @returns 时区序号\n */\n static getOrder(offset = TzDate.getOffset()) {\n return offset / -60;\n }\n\n /**\n * 获取时区分钟偏移量\n * @param gmtOrder - 默认使用当前时区序号\n * @returns 时区分钟偏移量\n */\n static getOffset(gmtOrder?: number) {\n return isNumber(gmtOrder) ? gmtOrder * -60 : new Date().getTimezoneOffset();\n }\n}\n","import { objectEach } from '@/object';\nimport { isDate, isString } from '@/type';\nimport { TzDate } from './timezone';\n\n/**\n * 判断一个值是否为有效的日期对象\n * @param unknown - 需要判断的值\n * @returns 如果值是有效的日期对象则返回 true,否则返回 false\n * @example\n * ```typescript\n * isValidDate(new Date()); // true\n * isValidDate('2023-01-01'); // false\n * isValidDate(NaN); // false\n * ```\n */\nexport function isValidDate(unknown: unknown): unknown is Date | TzDate {\n return (\n (unknown instanceof Date && !Number.isNaN(unknown.getTime())) ||\n (unknown instanceof TzDate && !Number.isNaN(unknown.getTime()))\n );\n}\n\nexport type DateLike = Date | TzDate;\nexport type DateValue = number | string | DateLike;\n\nfunction _guessDateSeparator(value: DateValue): Date | undefined {\n if (!isString(value)) return;\n\n const value2 = value.replace(/-/g, '/');\n\n return new Date(value2);\n}\n\nfunction _guessDateTimezone(value: DateValue): Date | undefined {\n if (!isString(value)) return;\n\n const re = /([+-])(\\d\\d)(\\d\\d)$/;\n\n const matches = re.exec(value);\n\n if (!matches) return;\n\n const value2 = value.replace(re, 'Z');\n const d = new Date(value2);\n\n if (!isValidDate(d)) return;\n\n const [, flag, hours, minutes] = matches;\n const hours2 = Number.parseInt(hours, 10);\n const minutes2 = Number.parseInt(minutes, 10);\n const offset = (a: number, b: number): number => (flag === '+' ? a - b : a + b);\n\n d.setHours(offset(d.getHours(), hours2));\n d.setMinutes(offset(d.getMinutes(), minutes2));\n\n return d;\n}\n\n/**\n * 解析为Date对象\n * @param dateValue - 可以是数值、字符串或 Date 对象\n * @returns 解析后的 Date 对象\n * @throws {SyntaxError} 如果无法解析为有效的日期对象,则抛出错误\n * @example\n * ```typescript\n * dateParse('2023-01-01'); // Date对象\n * dateParse(1672531200000); // Date对象\n * dateParse(new Date()); // Date对象\n * dateParse('invalid date'); // 抛出 SyntaxError\n * ```\n */\nexport function dateParse(dateValue: DateValue): DateLike {\n // 传入的 Date 对象有 Date、TzDate\n // @ts-ignore\n const d1 = isDate(dateValue)\n ? new Date(dateValue)\n : dateValue instanceof TzDate\n ? new TzDate(dateValue)\n : new Date(dateValue);\n if (isValidDate(d1)) return d1;\n\n // safari 浏览器的日期解析有问题\n // new Date('2020-06-26 18:06:15') 返回值是一个非法日期对象\n const d2 = _guessDateSeparator(dateValue);\n if (isValidDate(d2)) return d2;\n\n // safari 浏览器的日期解析有问题\n // new Date('2020-06-26T18:06:15.000+0800') 返回值是一个非法日期对象\n const d3 = _guessDateTimezone(dateValue);\n if (isValidDate(d3)) return d3;\n\n throw new SyntaxError(`${dateValue.toString()} 不是一个合法的日期值`);\n}\n\nfunction _pad(num: number, len = 2) {\n return `${num}`.padStart(len, '0');\n}\n\nconst rules: [RegExp, (date: DateLike) => number | string][] = [\n [/Y{4}/gi, (date) => date.getFullYear()],\n [/Y{2}/gi, (date) => date.getFullYear() % 100],\n [/M{2}/g, (date) => _pad(date.getMonth() + 1)],\n [/M{1}/g, (date) => date.getMonth() + 1],\n [/D{2}/gi, (date) => _pad(date.getDate())],\n [/D{1}/gi, (date) => date.getDate()],\n [/H{2}/g, (date) => _pad(date.getHours())],\n [/H{1}/g, (date) => date.getHours()],\n [\n /h{2}/g,\n (date) => {\n const h = date.getHours();\n return _pad(h > 12 ? h - 12 : h);\n },\n ],\n [\n /h{1}/g,\n (date) => {\n const h = date.getHours();\n return h > 12 ? h - 12 : h;\n },\n ],\n [/m{2}/g, (date) => _pad(date.getMinutes())],\n [/m{1}/g, (date) => date.getMinutes()],\n [/s{2}/g, (date) => _pad(date.getSeconds())],\n [/s{1}/g, (date) => date.getSeconds()],\n [/S{3}/g, (date) => _pad(date.getMilliseconds(), 3)],\n [/S{2}/g, (date) => _pad(date.getMilliseconds(), 2)],\n [/S{1}/g, (date) => date.getMilliseconds()],\n];\n\n/**\n * 格式化为日期字符串(带自定义格式化模板)\n * @param dateValue - 可以是数值、字符串或 Date 对象\n * @param format - 模板,默认是 'YYYY-MM-DD HH:mm:ss',模板字符:\n * - YYYY:年\n * - yyyy: 年\n * - MM:月\n * - DD:日\n * - dd: 日\n * - HH:时(24 小时制)\n * - hh:时(12 小时制)\n * - mm:分\n * - ss:秒\n * - SSS:毫秒\n * @returns 格式化后的日期字符串\n * @example\n * ```typescript\n * dateFormat(new Date(), 'YYYY-MM-DD'); // '2023-01-01'\n * dateFormat(1672531200000, 'YYYY/MM/DD HH:mm:ss'); // '2023/01/01 00:00:00'\n * dateFormat('2023-01-01', 'YYYY年MM月DD日'); // '2023年01月01日'\n * ```\n */\nexport function dateFormat(dateValue: DateValue, format = 'YYYY-MM-DD HH:mm:ss'): string {\n const date = dateParse(dateValue);\n let result = format;\n\n for (const rule of rules) {\n result = result.replace(rule[0], String(rule[1](date)));\n }\n\n return result;\n}\n"],"names":["isNumber","timestamp","isString","isDate"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core.cjs","sources":["../src/date/timezone.ts","../src/date/core.ts"],"sourcesContent":["import { isNumber } from '../type';\nimport { dateFormat } from './core';\n\nexport type TimezoneDateOptions = {\n /**\n * 时间戳\n * @default Date.now()\n */\n timestamp?: number;\n\n /**\n * 日期值\n */\n value?: readonly [\n year?: number,\n month?: number,\n day?: number,\n hours?: number,\n minutes?: number,\n seconds?: number,\n milliseconds?: number,\n ];\n\n /**\n * UTC 时区,支持负数和小数,例如:\n * - 8 表示 UTC+8\n * - -12 表示 UTC-12\n * - 0 表示 UTC 时间\n * - 12.5 表示 UTC+12:30\n */\n utcOffset?: number;\n};\n\n/**\n * 时区偏移量毫秒常量(1分钟 = 60 * 1000 毫秒)\n */\nconst TIMEZONE_OFFSET_MS = 60 * 1000;\n\n/**\n * 时区日期类,用于处理不同时区的日期时间\n */\nexport class TimezoneDate {\n /**\n * 内部时间戳\n */\n #timestamp: number;\n\n /**\n * 目标时区的日期对象\n */\n #targetDate: Date;\n\n /**\n * UTC 日期对象\n */\n #utcDate: Date;\n\n /**\n * 本地时区偏移量(分钟)\n */\n #localTimezoneOffset = TimezoneDate.getTimezoneOffset();\n\n /**\n * 本地时区偏移量(毫秒)\n */\n #localTimezoneOffsetMS = this.#localTimezoneOffset * TIMEZONE_OFFSET_MS;\n\n /**\n * 目标时区偏移量(分钟)\n */\n #targetTimezoneOffset = 0;\n\n /**\n * 目标时区偏移量(毫秒)\n */\n #targetTimezoneOffsetMS = 0;\n\n /**\n * 构造函数选项\n */\n #options: TimezoneDateOptions;\n\n /**\n * 构造一个 TimezoneDate 实例\n * @param options - 配置选项\n */\n constructor(options?: TimezoneDateOptions | TimezoneDate) {\n this.#options =\n (options instanceof TimezoneDate\n ? {\n timestamp: options.getTime(),\n utcOffset: options.getUTCOffset(),\n }\n : options) || {};\n const { utcOffset, timestamp, value } = this.#options;\n this.#targetTimezoneOffset = isNumber(utcOffset)\n ? TimezoneDate.getTimezoneOffset(utcOffset)\n : this.#localTimezoneOffset;\n this.#targetTimezoneOffsetMS = this.#targetTimezoneOffset * TIMEZONE_OFFSET_MS;\n\n if (Array.isArray(value) && value.length > 0) {\n const [fullYear, month, day, hours, minutes, seconds, milliseconds] = value;\n const timestamp = Date.UTC(\n fullYear ?? 0,\n month ?? 0,\n day ?? 1,\n hours ?? 0,\n minutes ?? 0,\n seconds ?? 0,\n milliseconds ?? 0,\n );\n\n this.#timestamp = timestamp + this.#targetTimezoneOffsetMS;\n } else {\n this.#timestamp = timestamp || Date.now();\n }\n\n this.#targetDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS - this.#targetTimezoneOffsetMS);\n this.#utcDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS);\n }\n\n /**\n * 更新内部时间戳\n */\n #updateTimestamp() {\n this.#timestamp = this.#targetDate.getTime() + this.#targetTimezoneOffsetMS - this.#localTimezoneOffsetMS;\n this.#utcDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS);\n }\n\n /**\n * 获取时区偏移量(分钟)\n * @returns 时区偏移量\n */\n getTimezoneOffset() {\n return this.#targetTimezoneOffset;\n }\n\n /**\n * 获取时区偏移量(UTC)\n * @returns 时区序号\n */\n getUTCOffset() {\n return TimezoneDate.getUTCOffset(this.#targetTimezoneOffset);\n }\n\n /**\n * 获取年份\n * @returns 年份\n */\n getFullYear() {\n return this.#targetDate.getFullYear();\n }\n\n /**\n * 获取月份\n * @returns 月份 (0-11)\n */\n getMonth() {\n return this.#targetDate.getMonth();\n }\n\n /**\n * 获取日期\n * @returns 日期 (1-31)\n */\n getDate() {\n return this.#targetDate.getDate();\n }\n\n /**\n * 获取小时\n * @returns 小时 (0-23)\n */\n getHours() {\n return this.#targetDate.getHours();\n }\n\n /**\n * 获取分钟\n * @returns 分钟 (0-59)\n */\n getMinutes() {\n return this.#targetDate.getMinutes();\n }\n\n /**\n * 获取秒数\n * @returns 秒数 (0-59)\n */\n getSeconds() {\n return this.#targetDate.getSeconds();\n }\n\n /**\n * 获取毫秒\n * @returns 毫秒 (0-999)\n */\n getMilliseconds() {\n return this.#targetDate.getMilliseconds();\n }\n\n /**\n * 设置年份\n * @param year - 年份\n * @param month - 月份\n * @param date - 日期\n * @returns 时间戳\n */\n setFullYear(year: number, month?: number, date?: number) {\n this.#targetDate.setFullYear(year);\n this.#updateTimestamp();\n\n if (isNumber(month)) this.setMonth(month);\n if (isNumber(date)) this.setDate(date);\n\n return this.getTime();\n }\n\n /**\n * 设置月份\n * @param month - 月份\n * @param date - 日期\n * @returns 时间戳\n */\n setMonth(month: number, date?: number) {\n this.#targetDate.setMonth(month);\n this.#updateTimestamp();\n\n if (isNumber(date)) this.setDate(date);\n\n return this.getTime();\n }\n\n /**\n * 设置日期\n * @param date - 日期\n * @returns 时间戳\n */\n setDate(date: number) {\n this.#targetDate.setDate(date);\n this.#updateTimestamp();\n\n return this.getTime();\n }\n\n /**\n * 设置小时\n * @param hours - 小时\n * @param minutes - 分钟\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setHours(hours: number, minutes?: number, seconds?: number, milliseconds?: number) {\n this.#targetDate.setHours(hours);\n this.#updateTimestamp();\n\n if (isNumber(minutes)) this.setMinutes(minutes);\n if (isNumber(seconds)) this.setSeconds(seconds);\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置分钟\n * @param minutes - 分钟\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setMinutes(minutes: number, seconds?: number, milliseconds?: number) {\n this.#targetDate.setMinutes(minutes);\n this.#updateTimestamp();\n\n if (isNumber(seconds)) this.setSeconds(seconds);\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置秒数\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setSeconds(seconds: number, milliseconds?: number) {\n this.#targetDate.setSeconds(seconds);\n this.#updateTimestamp();\n\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置毫秒\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setMilliseconds(milliseconds: number) {\n this.#targetDate.setMilliseconds(milliseconds);\n this.#updateTimestamp();\n\n return this.getTime();\n }\n\n /**\n * 获取时间戳\n * @returns 时间戳\n */\n getTime() {\n return this.#timestamp;\n }\n\n /**\n * 获取星期几\n * @returns 星期几 (0-6, 0表示周日)\n */\n getDay() {\n return this.#targetDate.getDay();\n }\n\n /**\n * 转换为 ISO 格式的字符串\n * @returns ISO 格式的时间字符串\n */\n toISOString() {\n return dateFormat(this.#utcDate, 'YYYY-MM-DDTHH:mm:ss.SSSZ');\n }\n\n /**\n * 转换为指定时区的 TimezoneDate 对象\n * @param td - 需要转换的日期对象\n * @param offset - 目标时区分钟偏移量,默认为当前时区\n * @returns 返回一个 TimezoneDate 对象\n * @example\n * ```js\n * // 转换为 UTC 时间\n * const utc0Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 0);\n *\n * // 转换为东八区时间\n * const utc8Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 8);\n * ```\n */\n static changeUtcOffset(td: TimezoneDate, utcOffset: number) {\n return new TimezoneDate({\n utcOffset,\n timestamp: td.getTime(),\n });\n }\n\n /**\n * 获取时区分钟偏移量\n * @param utcOffset - 默认使用当前时区\n * @returns 时区分钟偏移量\n */\n static getTimezoneOffset(utcOffset?: number) {\n return isNumber(utcOffset) ? utcOffset * -60 : new Date().getTimezoneOffset();\n }\n\n /**\n * 获取时区序号\n * @param timezoneOffset - 默认使用当前时区分钟偏移量\n * @returns 时区序号\n */\n static getUTCOffset(timezoneOffset = TimezoneDate.getTimezoneOffset()) {\n return timezoneOffset / -60;\n }\n}\n","import { objectEach } from '@/object';\nimport { isDate, isString } from '@/type';\nimport { TimezoneDate } from './timezone';\n\n/**\n * 判断一个值是否为有效的日期对象\n * @param unknown - 需要判断的值\n * @returns 如果值是有效的日期对象则返回 true,否则返回 false\n * @example\n * ```typescript\n * isValidDate(new Date()); // true\n * isValidDate('2023-01-01'); // false\n * isValidDate(NaN); // false\n * ```\n */\nexport function isValidDate(unknown: unknown): unknown is Date | TimezoneDate {\n return (\n (unknown instanceof Date && !Number.isNaN(unknown.getTime())) ||\n (unknown instanceof TimezoneDate && !Number.isNaN(unknown.getTime()))\n );\n}\n\nexport type DateLike = Date | TimezoneDate;\nexport type DateValue = number | string | DateLike;\n\nfunction _guessDateSeparator(value: DateValue): Date | undefined {\n if (!isString(value)) return;\n\n const value2 = value.replace(/-/g, '/');\n\n return new Date(value2);\n}\n\nfunction _guessDateTimezone(value: DateValue): Date | undefined {\n if (!isString(value)) return;\n\n const re = /([+-])(\\d\\d)(\\d\\d)$/;\n\n const matches = re.exec(value);\n\n if (!matches) return;\n\n const value2 = value.replace(re, 'Z');\n const d = new Date(value2);\n\n if (!isValidDate(d)) return;\n\n const [, flag, hours, minutes] = matches;\n const hours2 = Number.parseInt(hours, 10);\n const minutes2 = Number.parseInt(minutes, 10);\n const offset = (a: number, b: number): number => (flag === '+' ? a - b : a + b);\n\n d.setHours(offset(d.getHours(), hours2));\n d.setMinutes(offset(d.getMinutes(), minutes2));\n\n return d;\n}\n\n/**\n * 解析为Date对象\n * @param dateValue - 可以是数值、字符串或 Date 对象\n * @returns 解析后的 Date 对象\n * @throws {SyntaxError} 如果无法解析为有效的日期对象,则抛出错误\n * @example\n * ```typescript\n * dateParse('2023-01-01'); // Date对象\n * dateParse(1672531200000); // Date对象\n * dateParse(new Date()); // Date对象\n * dateParse('invalid date'); // 抛出 SyntaxError\n * ```\n */\nexport function dateParse(dateValue: DateValue): DateLike {\n // 传入的 Date 对象有 Date、TimezoneDate\n // @ts-ignore\n const d1 = isDate(dateValue)\n ? new Date(dateValue)\n : dateValue instanceof TimezoneDate\n ? new TimezoneDate(dateValue)\n : new Date(dateValue);\n if (isValidDate(d1)) return d1;\n\n // safari 浏览器的日期解析有问题\n // new Date('2020-06-26 18:06:15') 返回值是一个非法日期对象\n const d2 = _guessDateSeparator(dateValue);\n if (isValidDate(d2)) return d2;\n\n // safari 浏览器的日期解析有问题\n // new Date('2020-06-26T18:06:15.000+0800') 返回值是一个非法日期对象\n const d3 = _guessDateTimezone(dateValue);\n if (isValidDate(d3)) return d3;\n\n throw new SyntaxError(`${dateValue.toString()} 不是一个合法的日期值`);\n}\n\nfunction _pad(num: number, len = 2) {\n return `${num}`.padStart(len, '0');\n}\n\nconst rules: [RegExp, (date: DateLike) => number | string][] = [\n [/Y{4}/gi, (date) => date.getFullYear()],\n [/Y{2}/gi, (date) => date.getFullYear() % 100],\n [/M{2}/g, (date) => _pad(date.getMonth() + 1)],\n [/M{1}/g, (date) => date.getMonth() + 1],\n [/D{2}/gi, (date) => _pad(date.getDate())],\n [/D{1}/gi, (date) => date.getDate()],\n [/H{2}/g, (date) => _pad(date.getHours())],\n [/H{1}/g, (date) => date.getHours()],\n [\n /h{2}/g,\n (date) => {\n const h = date.getHours();\n return _pad(h > 12 ? h - 12 : h);\n },\n ],\n [\n /h{1}/g,\n (date) => {\n const h = date.getHours();\n return h > 12 ? h - 12 : h;\n },\n ],\n [/m{2}/g, (date) => _pad(date.getMinutes())],\n [/m{1}/g, (date) => date.getMinutes()],\n [/s{2}/g, (date) => _pad(date.getSeconds())],\n [/s{1}/g, (date) => date.getSeconds()],\n [/S{3}/g, (date) => _pad(date.getMilliseconds(), 3)],\n [/S{2}/g, (date) => _pad(date.getMilliseconds(), 2)],\n [/S{1}/g, (date) => date.getMilliseconds()],\n];\n\n/**\n * 格式化为日期字符串(带自定义格式化模板)\n * @param dateValue - 可以是数值、字符串或 Date 对象\n * @param format - 模板,默认是 'YYYY-MM-DD HH:mm:ss',模板字符:\n * - YYYY:年\n * - yyyy: 年\n * - MM:月\n * - DD:日\n * - dd: 日\n * - HH:时(24 小时制)\n * - hh:时(12 小时制)\n * - mm:分\n * - ss:秒\n * - SSS:毫秒\n * @returns 格式化后的日期字符串\n * @example\n * ```typescript\n * dateFormat(new Date(), 'YYYY-MM-DD'); // '2023-01-01'\n * dateFormat(1672531200000, 'YYYY/MM/DD HH:mm:ss'); // '2023/01/01 00:00:00'\n * dateFormat('2023-01-01', 'YYYY年MM月DD日'); // '2023年01月01日'\n * ```\n */\nexport function dateFormat(dateValue: DateValue, format = 'YYYY-MM-DD HH:mm:ss'): string {\n const date = dateParse(dateValue);\n let result = format;\n\n for (const rule of rules) {\n result = result.replace(rule[0], String(rule[1](date)));\n }\n\n return result;\n}\n"],"names":["isNumber","timestamp","isString","isDate"],"mappings":";;AAoCA,MAAM,qBAAqB,KAAK;AAKzB,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA,EAIxB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,aAAa,kBAAkB;AAAA;AAAA;AAAA;AAAA,EAKtD,yBAAyB,KAAK,uBAAuB;AAAA;AAAA;AAAA;AAAA,EAKrD,wBAAwB;AAAA;AAAA;AAAA;AAAA,EAKxB,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAK1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,SAA8C;AACnD,SAAA,YACF,mBAAmB,eAChB;AAAA,MACE,WAAW,QAAQ,QAAQ;AAAA,MAC3B,WAAW,QAAQ,aAAa;AAAA,IAClC,IACA,YAAY,CAAC;AACnB,UAAM,EAAE,WAAW,WAAW,UAAU,KAAK;AACxC,SAAA,wBAAwBA,cAAS,SAAS,IAC3C,aAAa,kBAAkB,SAAS,IACxC,KAAK;AACJ,SAAA,0BAA0B,KAAK,wBAAwB;AAE5D,QAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,GAAG;AACtC,YAAA,CAAC,UAAU,OAAO,KAAK,OAAO,SAAS,SAAS,YAAY,IAAI;AACtE,YAAMC,aAAY,KAAK;AAAA,QACrB,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,QACX,gBAAgB;AAAA,MAClB;AAEK,WAAA,aAAaA,aAAY,KAAK;AAAA,IAAA,OAC9B;AACA,WAAA,aAAa,aAAa,KAAK,IAAI;AAAA,IAAA;AAGrC,SAAA,cAAc,IAAI,KAAK,KAAK,aAAa,KAAK,yBAAyB,KAAK,uBAAuB;AACxG,SAAK,WAAW,IAAI,KAAK,KAAK,aAAa,KAAK,sBAAsB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMxE,mBAAmB;AACjB,SAAK,aAAa,KAAK,YAAY,YAAY,KAAK,0BAA0B,KAAK;AACnF,SAAK,WAAW,IAAI,KAAK,KAAK,aAAa,KAAK,sBAAsB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxE,oBAAoB;AAClB,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,eAAe;AACN,WAAA,aAAa,aAAa,KAAK,qBAAqB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7D,cAAc;AACL,WAAA,KAAK,YAAY,YAAY;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtC,WAAW;AACF,WAAA,KAAK,YAAY,SAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnC,UAAU;AACD,WAAA,KAAK,YAAY,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlC,WAAW;AACF,WAAA,KAAK,YAAY,SAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnC,aAAa;AACJ,WAAA,KAAK,YAAY,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,aAAa;AACJ,WAAA,KAAK,YAAY,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,kBAAkB;AACT,WAAA,KAAK,YAAY,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU1C,YAAY,MAAc,OAAgB,MAAe;AAClD,SAAA,YAAY,YAAY,IAAI;AACjC,SAAK,iBAAiB;AAEtB,QAAID,KAAS,SAAA,KAAK,EAAG,MAAK,SAAS,KAAK;AACxC,QAAIA,KAAS,SAAA,IAAI,EAAG,MAAK,QAAQ,IAAI;AAErC,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStB,SAAS,OAAe,MAAe;AAChC,SAAA,YAAY,SAAS,KAAK;AAC/B,SAAK,iBAAiB;AAEtB,QAAIA,KAAS,SAAA,IAAI,EAAG,MAAK,QAAQ,IAAI;AAErC,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,QAAQ,MAAc;AACf,SAAA,YAAY,QAAQ,IAAI;AAC7B,SAAK,iBAAiB;AAEtB,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWtB,SAAS,OAAe,SAAkB,SAAkB,cAAuB;AAC5E,SAAA,YAAY,SAAS,KAAK;AAC/B,SAAK,iBAAiB;AAEtB,QAAIA,KAAS,SAAA,OAAO,EAAG,MAAK,WAAW,OAAO;AAC9C,QAAIA,KAAS,SAAA,OAAO,EAAG,MAAK,WAAW,OAAO;AAC9C,QAAIA,KAAS,SAAA,YAAY,EAAG,MAAK,gBAAgB,YAAY;AAE7D,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUtB,WAAW,SAAiB,SAAkB,cAAuB;AAC9D,SAAA,YAAY,WAAW,OAAO;AACnC,SAAK,iBAAiB;AAEtB,QAAIA,KAAS,SAAA,OAAO,EAAG,MAAK,WAAW,OAAO;AAC9C,QAAIA,KAAS,SAAA,YAAY,EAAG,MAAK,gBAAgB,YAAY;AAE7D,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStB,WAAW,SAAiB,cAAuB;AAC5C,SAAA,YAAY,WAAW,OAAO;AACnC,SAAK,iBAAiB;AAEtB,QAAIA,KAAS,SAAA,YAAY,EAAG,MAAK,gBAAgB,YAAY;AAE7D,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,gBAAgB,cAAsB;AAC/B,SAAA,YAAY,gBAAgB,YAAY;AAC7C,SAAK,iBAAiB;AAEtB,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtB,UAAU;AACR,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,SAAS;AACA,WAAA,KAAK,YAAY,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjC,cAAc;AACL,WAAA,WAAW,KAAK,UAAU,0BAA0B;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiB7D,OAAO,gBAAgB,IAAkB,WAAmB;AAC1D,WAAO,IAAI,aAAa;AAAA,MACtB;AAAA,MACA,WAAW,GAAG,QAAQ;AAAA,IAAA,CACvB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQH,OAAO,kBAAkB,WAAoB;AACpC,WAAAA,KAAA,SAAS,SAAS,IAAI,YAAY,OAAU,oBAAA,QAAO,kBAAkB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ9E,OAAO,aAAa,iBAAiB,aAAa,qBAAqB;AACrE,WAAO,iBAAiB;AAAA,EAAA;AAE5B;ACnWO,SAAS,YAAY,SAAkD;AAC5E,SACG,mBAAmB,QAAQ,CAAC,OAAO,MAAM,QAAQ,QAAQ,CAAC,KAC1D,mBAAmB,gBAAgB,CAAC,OAAO,MAAM,QAAQ,SAAS;AAEvE;AAKA,SAAS,oBAAoB,OAAoC;AAC3D,MAAA,CAACE,KAAAA,SAAS,KAAK,EAAG;AAEtB,QAAM,SAAS,MAAM,QAAQ,MAAM,GAAG;AAE/B,SAAA,IAAI,KAAK,MAAM;AACxB;AAEA,SAAS,mBAAmB,OAAoC;AAC1D,MAAA,CAACA,KAAAA,SAAS,KAAK,EAAG;AAEtB,QAAM,KAAK;AAEL,QAAA,UAAU,GAAG,KAAK,KAAK;AAE7B,MAAI,CAAC,QAAS;AAEd,QAAM,SAAS,MAAM,QAAQ,IAAI,GAAG;AAC9B,QAAA,IAAI,IAAI,KAAK,MAAM;AAErB,MAAA,CAAC,YAAY,CAAC,EAAG;AAErB,QAAM,GAAG,MAAM,OAAO,OAAO,IAAI;AACjC,QAAM,SAAS,OAAO,SAAS,OAAO,EAAE;AACxC,QAAM,WAAW,OAAO,SAAS,SAAS,EAAE;AACtC,QAAA,SAAS,CAAC,GAAW,MAAuB,SAAS,MAAM,IAAI,IAAI,IAAI;AAE7E,IAAE,SAAS,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;AACvC,IAAE,WAAW,OAAO,EAAE,WAAW,GAAG,QAAQ,CAAC;AAEtC,SAAA;AACT;AAeO,SAAS,UAAU,WAAgC;AAGxD,QAAM,KAAKC,KAAAA,OAAO,SAAS,IACvB,IAAI,KAAK,SAAS,IAClB,qBAAqB,eACnB,IAAI,aAAa,SAAS,IAC1B,IAAI,KAAK,SAAS;AACpB,MAAA,YAAY,EAAE,EAAU,QAAA;AAItB,QAAA,KAAK,oBAAoB,SAAS;AACpC,MAAA,YAAY,EAAE,EAAU,QAAA;AAItB,QAAA,KAAK,mBAAmB,SAAS;AACnC,MAAA,YAAY,EAAE,EAAU,QAAA;AAE5B,QAAM,IAAI,YAAY,GAAG,UAAU,SAAA,CAAU,aAAa;AAC5D;AAEA,SAAS,KAAK,KAAa,MAAM,GAAG;AAClC,SAAO,GAAG,GAAG,GAAG,SAAS,KAAK,GAAG;AACnC;AAEA,MAAM,QAAyD;AAAA,EAC7D,CAAC,UAAU,CAAC,SAAS,KAAK,aAAa;AAAA,EACvC,CAAC,UAAU,CAAC,SAAS,KAAK,YAAA,IAAgB,GAAG;AAAA,EAC7C,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,SAAA,IAAa,CAAC,CAAC;AAAA,EAC7C,CAAC,SAAS,CAAC,SAAS,KAAK,SAAA,IAAa,CAAC;AAAA,EACvC,CAAC,UAAU,CAAC,SAAS,KAAK,KAAK,QAAA,CAAS,CAAC;AAAA,EACzC,CAAC,UAAU,CAAC,SAAS,KAAK,SAAS;AAAA,EACnC,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,SAAA,CAAU,CAAC;AAAA,EACzC,CAAC,SAAS,CAAC,SAAS,KAAK,UAAU;AAAA,EACnC;AAAA,IACE;AAAA,IACA,CAAC,SAAS;AACF,YAAA,IAAI,KAAK,SAAS;AACxB,aAAO,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAAA,IAAA;AAAA,EAEnC;AAAA,EACA;AAAA,IACE;AAAA,IACA,CAAC,SAAS;AACF,YAAA,IAAI,KAAK,SAAS;AACjB,aAAA,IAAI,KAAK,IAAI,KAAK;AAAA,IAAA;AAAA,EAE7B;AAAA,EACA,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,WAAA,CAAY,CAAC;AAAA,EAC3C,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY;AAAA,EACrC,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,WAAA,CAAY,CAAC;AAAA,EAC3C,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY;AAAA,EACrC,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,gBAAA,GAAmB,CAAC,CAAC;AAAA,EACnD,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,gBAAA,GAAmB,CAAC,CAAC;AAAA,EACnD,CAAC,SAAS,CAAC,SAAS,KAAK,gBAAiB,CAAA;AAC5C;AAwBgB,SAAA,WAAW,WAAsB,SAAS,uBAA+B;AACjF,QAAA,OAAO,UAAU,SAAS;AAChC,MAAI,SAAS;AAEb,aAAW,QAAQ,OAAO;AACf,aAAA,OAAO,QAAQ,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;AAAA,EAAA;AAGjD,SAAA;AACT;;;;;"}
|
package/dist/core.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isNumber, isDate, isString } from "./type.mjs";
|
|
2
|
-
const
|
|
3
|
-
class
|
|
2
|
+
const TIMEZONE_OFFSET_MS = 60 * 1e3;
|
|
3
|
+
class TimezoneDate {
|
|
4
4
|
/**
|
|
5
5
|
* 内部时间戳
|
|
6
6
|
*/
|
|
@@ -16,35 +16,35 @@ class TzDate {
|
|
|
16
16
|
/**
|
|
17
17
|
* 本地时区偏移量(分钟)
|
|
18
18
|
*/
|
|
19
|
-
#
|
|
19
|
+
#localTimezoneOffset = TimezoneDate.getTimezoneOffset();
|
|
20
20
|
/**
|
|
21
21
|
* 本地时区偏移量(毫秒)
|
|
22
22
|
*/
|
|
23
|
-
#
|
|
23
|
+
#localTimezoneOffsetMS = this.#localTimezoneOffset * TIMEZONE_OFFSET_MS;
|
|
24
24
|
/**
|
|
25
25
|
* 目标时区偏移量(分钟)
|
|
26
26
|
*/
|
|
27
|
-
#
|
|
27
|
+
#targetTimezoneOffset = 0;
|
|
28
28
|
/**
|
|
29
29
|
* 目标时区偏移量(毫秒)
|
|
30
30
|
*/
|
|
31
|
-
#
|
|
31
|
+
#targetTimezoneOffsetMS = 0;
|
|
32
32
|
/**
|
|
33
33
|
* 构造函数选项
|
|
34
34
|
*/
|
|
35
35
|
#options;
|
|
36
36
|
/**
|
|
37
|
-
* 构造一个
|
|
37
|
+
* 构造一个 TimezoneDate 实例
|
|
38
38
|
* @param options - 配置选项
|
|
39
39
|
*/
|
|
40
40
|
constructor(options) {
|
|
41
|
-
this.#options = (options instanceof
|
|
41
|
+
this.#options = (options instanceof TimezoneDate ? {
|
|
42
42
|
timestamp: options.getTime(),
|
|
43
|
-
|
|
43
|
+
utcOffset: options.getUTCOffset()
|
|
44
44
|
} : options) || {};
|
|
45
|
-
const {
|
|
46
|
-
this.#
|
|
47
|
-
this.#
|
|
45
|
+
const { utcOffset, timestamp, value } = this.#options;
|
|
46
|
+
this.#targetTimezoneOffset = isNumber(utcOffset) ? TimezoneDate.getTimezoneOffset(utcOffset) : this.#localTimezoneOffset;
|
|
47
|
+
this.#targetTimezoneOffsetMS = this.#targetTimezoneOffset * TIMEZONE_OFFSET_MS;
|
|
48
48
|
if (Array.isArray(value) && value.length > 0) {
|
|
49
49
|
const [fullYear, month, day, hours, minutes, seconds, milliseconds] = value;
|
|
50
50
|
const timestamp2 = Date.UTC(
|
|
@@ -56,33 +56,33 @@ class TzDate {
|
|
|
56
56
|
seconds ?? 0,
|
|
57
57
|
milliseconds ?? 0
|
|
58
58
|
);
|
|
59
|
-
this.#timestamp = timestamp2 + this.#
|
|
59
|
+
this.#timestamp = timestamp2 + this.#targetTimezoneOffsetMS;
|
|
60
60
|
} else {
|
|
61
61
|
this.#timestamp = timestamp || Date.now();
|
|
62
62
|
}
|
|
63
|
-
this.#targetDate = new Date(this.#timestamp + this.#
|
|
64
|
-
this.#utcDate = new Date(this.#timestamp + this.#
|
|
63
|
+
this.#targetDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS - this.#targetTimezoneOffsetMS);
|
|
64
|
+
this.#utcDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS);
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
67
|
* 更新内部时间戳
|
|
68
68
|
*/
|
|
69
69
|
#updateTimestamp() {
|
|
70
|
-
this.#timestamp = this.#targetDate.getTime() + this.#
|
|
71
|
-
this.#utcDate = new Date(this.#timestamp + this.#
|
|
70
|
+
this.#timestamp = this.#targetDate.getTime() + this.#targetTimezoneOffsetMS - this.#localTimezoneOffsetMS;
|
|
71
|
+
this.#utcDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS);
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
74
|
* 获取时区偏移量(分钟)
|
|
75
75
|
* @returns 时区偏移量
|
|
76
76
|
*/
|
|
77
77
|
getTimezoneOffset() {
|
|
78
|
-
return this.#
|
|
78
|
+
return this.#targetTimezoneOffset;
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
*
|
|
81
|
+
* 获取时区偏移量(UTC)
|
|
82
82
|
* @returns 时区序号
|
|
83
83
|
*/
|
|
84
|
-
|
|
85
|
-
return
|
|
84
|
+
getUTCOffset() {
|
|
85
|
+
return TimezoneDate.getUTCOffset(this.#targetTimezoneOffset);
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
88
88
|
* 获取年份
|
|
@@ -243,40 +243,44 @@ class TzDate {
|
|
|
243
243
|
return dateFormat(this.#utcDate, "YYYY-MM-DDTHH:mm:ss.SSSZ");
|
|
244
244
|
}
|
|
245
245
|
/**
|
|
246
|
-
*
|
|
246
|
+
* 转换为指定时区的 TimezoneDate 对象
|
|
247
247
|
* @param td - 需要转换的日期对象
|
|
248
248
|
* @param offset - 目标时区分钟偏移量,默认为当前时区
|
|
249
|
-
* @returns 返回一个
|
|
249
|
+
* @returns 返回一个 TimezoneDate 对象
|
|
250
250
|
* @example
|
|
251
251
|
* ```js
|
|
252
|
-
*
|
|
252
|
+
* // 转换为 UTC 时间
|
|
253
|
+
* const utc0Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 0);
|
|
254
|
+
*
|
|
255
|
+
* // 转换为东八区时间
|
|
256
|
+
* const utc8Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 8);
|
|
253
257
|
* ```
|
|
254
258
|
*/
|
|
255
|
-
static
|
|
256
|
-
return new
|
|
257
|
-
|
|
259
|
+
static changeUtcOffset(td, utcOffset) {
|
|
260
|
+
return new TimezoneDate({
|
|
261
|
+
utcOffset,
|
|
258
262
|
timestamp: td.getTime()
|
|
259
263
|
});
|
|
260
264
|
}
|
|
261
265
|
/**
|
|
262
|
-
*
|
|
263
|
-
* @param
|
|
264
|
-
* @returns
|
|
266
|
+
* 获取时区分钟偏移量
|
|
267
|
+
* @param utcOffset - 默认使用当前时区
|
|
268
|
+
* @returns 时区分钟偏移量
|
|
265
269
|
*/
|
|
266
|
-
static
|
|
267
|
-
return
|
|
270
|
+
static getTimezoneOffset(utcOffset) {
|
|
271
|
+
return isNumber(utcOffset) ? utcOffset * -60 : (/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
268
272
|
}
|
|
269
273
|
/**
|
|
270
|
-
*
|
|
271
|
-
* @param
|
|
272
|
-
* @returns
|
|
274
|
+
* 获取时区序号
|
|
275
|
+
* @param timezoneOffset - 默认使用当前时区分钟偏移量
|
|
276
|
+
* @returns 时区序号
|
|
273
277
|
*/
|
|
274
|
-
static
|
|
275
|
-
return
|
|
278
|
+
static getUTCOffset(timezoneOffset = TimezoneDate.getTimezoneOffset()) {
|
|
279
|
+
return timezoneOffset / -60;
|
|
276
280
|
}
|
|
277
281
|
}
|
|
278
282
|
function isValidDate(unknown) {
|
|
279
|
-
return unknown instanceof Date && !Number.isNaN(unknown.getTime()) || unknown instanceof
|
|
283
|
+
return unknown instanceof Date && !Number.isNaN(unknown.getTime()) || unknown instanceof TimezoneDate && !Number.isNaN(unknown.getTime());
|
|
280
284
|
}
|
|
281
285
|
function _guessDateSeparator(value) {
|
|
282
286
|
if (!isString(value)) return;
|
|
@@ -300,7 +304,7 @@ function _guessDateTimezone(value) {
|
|
|
300
304
|
return d;
|
|
301
305
|
}
|
|
302
306
|
function dateParse(dateValue) {
|
|
303
|
-
const d1 = isDate(dateValue) ? new Date(dateValue) : dateValue instanceof
|
|
307
|
+
const d1 = isDate(dateValue) ? new Date(dateValue) : dateValue instanceof TimezoneDate ? new TimezoneDate(dateValue) : new Date(dateValue);
|
|
304
308
|
if (isValidDate(d1)) return d1;
|
|
305
309
|
const d2 = _guessDateSeparator(dateValue);
|
|
306
310
|
if (isValidDate(d2)) return d2;
|
|
@@ -351,7 +355,7 @@ function dateFormat(dateValue, format = "YYYY-MM-DD HH:mm:ss") {
|
|
|
351
355
|
return result;
|
|
352
356
|
}
|
|
353
357
|
export {
|
|
354
|
-
|
|
358
|
+
TimezoneDate as T,
|
|
355
359
|
dateFormat as a,
|
|
356
360
|
dateParse as d,
|
|
357
361
|
isValidDate as i
|
package/dist/core.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.mjs","sources":["../src/date/timezone.ts","../src/date/core.ts"],"sourcesContent":["import { isNumber } from '../type';\nimport { dateFormat } from './core';\n\nexport type TzDateOptions = {\n /**\n * 时间戳\n * @default Date.now()\n */\n timestamp?: number;\n\n /**\n * 日期值\n */\n value?: readonly [\n year?: number,\n month?: number,\n day?: number,\n hours?: number,\n minutes?: number,\n seconds?: number,\n milliseconds?: number,\n ];\n\n /**\n * 时区偏移量,单位为分钟,默认为当前时区\n */\n offset?: number;\n};\n\n/**\n * 时区偏移量毫秒常量(1分钟 = 60 * 1000 毫秒)\n */\nconst TZ_OFFSET_MS = 60 * 1000;\n\n/**\n * 时区日期类,用于处理不同时区的日期时间\n */\nexport class TzDate {\n /**\n * 内部时间戳\n */\n #timestamp: number;\n\n /**\n * 目标时区的日期对象\n */\n #targetDate: Date;\n\n /**\n * UTC 日期对象\n */\n #utcDate: Date;\n\n /**\n * 本地时区偏移量(分钟)\n */\n #localTZOffset = TzDate.getOffset();\n\n /**\n * 本地时区偏移量(毫秒)\n */\n #localTzOffsetMS = this.#localTZOffset * TZ_OFFSET_MS;\n\n /**\n * 目标时区偏移量(分钟)\n */\n #targetTzOffset = 0;\n\n /**\n * 目标时区偏移量(毫秒)\n */\n #targetTzOffsetMS = 0;\n\n /**\n * 构造函数选项\n */\n #options: TzDateOptions;\n\n /**\n * 构造一个 TzDate 实例\n * @param options - 配置选项\n */\n constructor(options?: TzDateOptions | TzDate) {\n this.#options =\n (options instanceof TzDate\n ? {\n timestamp: options.getTime(),\n offset: options.getTimezoneOffset(),\n }\n : options) || {};\n const { offset, timestamp, value } = this.#options;\n this.#targetTzOffset = isNumber(offset) ? offset : this.#localTZOffset;\n this.#targetTzOffsetMS = this.#targetTzOffset * TZ_OFFSET_MS;\n\n if (Array.isArray(value) && value.length > 0) {\n const [fullYear, month, day, hours, minutes, seconds, milliseconds] = value;\n const timestamp = Date.UTC(\n fullYear ?? 0,\n month ?? 0,\n day ?? 1,\n hours ?? 0,\n minutes ?? 0,\n seconds ?? 0,\n milliseconds ?? 0,\n );\n\n this.#timestamp = timestamp + this.#targetTzOffsetMS;\n } else {\n this.#timestamp = timestamp || Date.now();\n }\n\n this.#targetDate = new Date(this.#timestamp + this.#localTzOffsetMS - this.#targetTzOffsetMS);\n this.#utcDate = new Date(this.#timestamp + this.#localTzOffsetMS);\n }\n\n /**\n * 更新内部时间戳\n */\n #updateTimestamp() {\n this.#timestamp = this.#targetDate.getTime() + this.#targetTzOffsetMS - this.#localTzOffsetMS;\n this.#utcDate = new Date(this.#timestamp + this.#localTzOffsetMS);\n }\n\n /**\n * 获取时区偏移量(分钟)\n * @returns 时区偏移量\n */\n getTimezoneOffset() {\n return this.#targetTzOffset;\n }\n\n /**\n * 获取时区序号\n * @returns 时区序号\n */\n getTimezoneOrder() {\n return TzDate.getOrder(this.#targetTzOffset);\n }\n\n /**\n * 获取年份\n * @returns 年份\n */\n getFullYear() {\n return this.#targetDate.getFullYear();\n }\n\n /**\n * 获取月份\n * @returns 月份 (0-11)\n */\n getMonth() {\n return this.#targetDate.getMonth();\n }\n\n /**\n * 获取日期\n * @returns 日期 (1-31)\n */\n getDate() {\n return this.#targetDate.getDate();\n }\n\n /**\n * 获取小时\n * @returns 小时 (0-23)\n */\n getHours() {\n return this.#targetDate.getHours();\n }\n\n /**\n * 获取分钟\n * @returns 分钟 (0-59)\n */\n getMinutes() {\n return this.#targetDate.getMinutes();\n }\n\n /**\n * 获取秒数\n * @returns 秒数 (0-59)\n */\n getSeconds() {\n return this.#targetDate.getSeconds();\n }\n\n /**\n * 获取毫秒\n * @returns 毫秒 (0-999)\n */\n getMilliseconds() {\n return this.#targetDate.getMilliseconds();\n }\n\n /**\n * 设置年份\n * @param year - 年份\n * @param month - 月份\n * @param date - 日期\n * @returns 时间戳\n */\n setFullYear(year: number, month?: number, date?: number) {\n this.#targetDate.setFullYear(year);\n this.#updateTimestamp();\n\n if (isNumber(month)) this.setMonth(month);\n if (isNumber(date)) this.setDate(date);\n\n return this.getTime();\n }\n\n /**\n * 设置月份\n * @param month - 月份\n * @param date - 日期\n * @returns 时间戳\n */\n setMonth(month: number, date?: number) {\n this.#targetDate.setMonth(month);\n this.#updateTimestamp();\n\n if (isNumber(date)) this.setDate(date);\n\n return this.getTime();\n }\n\n /**\n * 设置日期\n * @param date - 日期\n * @returns 时间戳\n */\n setDate(date: number) {\n this.#targetDate.setDate(date);\n this.#updateTimestamp();\n\n return this.getTime();\n }\n\n /**\n * 设置小时\n * @param hours - 小时\n * @param minutes - 分钟\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setHours(hours: number, minutes?: number, seconds?: number, milliseconds?: number) {\n this.#targetDate.setHours(hours);\n this.#updateTimestamp();\n\n if (isNumber(minutes)) this.setMinutes(minutes);\n if (isNumber(seconds)) this.setSeconds(seconds);\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置分钟\n * @param minutes - 分钟\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setMinutes(minutes: number, seconds?: number, milliseconds?: number) {\n this.#targetDate.setMinutes(minutes);\n this.#updateTimestamp();\n\n if (isNumber(seconds)) this.setSeconds(seconds);\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置秒数\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setSeconds(seconds: number, milliseconds?: number) {\n this.#targetDate.setSeconds(seconds);\n this.#updateTimestamp();\n\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置毫秒\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setMilliseconds(milliseconds: number) {\n this.#targetDate.setMilliseconds(milliseconds);\n this.#updateTimestamp();\n\n return this.getTime();\n }\n\n /**\n * 获取时间戳\n * @returns 时间戳\n */\n getTime() {\n return this.#timestamp;\n }\n\n /**\n * 获取星期几\n * @returns 星期几 (0-6, 0表示周日)\n */\n getDay() {\n return this.#targetDate.getDay();\n }\n\n /**\n * 转换为 ISO 格式的字符串\n * @returns ISO 格式的时间字符串\n */\n toISOString() {\n return dateFormat(this.#utcDate, 'YYYY-MM-DDTHH:mm:ss.SSSZ');\n }\n\n /**\n * 创建一个 TzDate 对象\n * @param td - 需要转换的日期对象\n * @param offset - 目标时区分钟偏移量,默认为当前时区\n * @returns 返回一个 TzDate 对象\n * @example\n * ```js\n * const tzDate = TzDate.from(new TzDate());\n * ```\n */\n static from(td: TzDate, offset = TzDate.getOffset()) {\n return new TzDate({\n offset: offset,\n timestamp: td.getTime(),\n });\n }\n\n /**\n * 获取时区序号\n * @param offset - 默认使用当前时区分钟偏移量\n * @returns 时区序号\n */\n static getOrder(offset = TzDate.getOffset()) {\n return offset / -60;\n }\n\n /**\n * 获取时区分钟偏移量\n * @param gmtOrder - 默认使用当前时区序号\n * @returns 时区分钟偏移量\n */\n static getOffset(gmtOrder?: number) {\n return isNumber(gmtOrder) ? gmtOrder * -60 : new Date().getTimezoneOffset();\n }\n}\n","import { objectEach } from '@/object';\nimport { isDate, isString } from '@/type';\nimport { TzDate } from './timezone';\n\n/**\n * 判断一个值是否为有效的日期对象\n * @param unknown - 需要判断的值\n * @returns 如果值是有效的日期对象则返回 true,否则返回 false\n * @example\n * ```typescript\n * isValidDate(new Date()); // true\n * isValidDate('2023-01-01'); // false\n * isValidDate(NaN); // false\n * ```\n */\nexport function isValidDate(unknown: unknown): unknown is Date | TzDate {\n return (\n (unknown instanceof Date && !Number.isNaN(unknown.getTime())) ||\n (unknown instanceof TzDate && !Number.isNaN(unknown.getTime()))\n );\n}\n\nexport type DateLike = Date | TzDate;\nexport type DateValue = number | string | DateLike;\n\nfunction _guessDateSeparator(value: DateValue): Date | undefined {\n if (!isString(value)) return;\n\n const value2 = value.replace(/-/g, '/');\n\n return new Date(value2);\n}\n\nfunction _guessDateTimezone(value: DateValue): Date | undefined {\n if (!isString(value)) return;\n\n const re = /([+-])(\\d\\d)(\\d\\d)$/;\n\n const matches = re.exec(value);\n\n if (!matches) return;\n\n const value2 = value.replace(re, 'Z');\n const d = new Date(value2);\n\n if (!isValidDate(d)) return;\n\n const [, flag, hours, minutes] = matches;\n const hours2 = Number.parseInt(hours, 10);\n const minutes2 = Number.parseInt(minutes, 10);\n const offset = (a: number, b: number): number => (flag === '+' ? a - b : a + b);\n\n d.setHours(offset(d.getHours(), hours2));\n d.setMinutes(offset(d.getMinutes(), minutes2));\n\n return d;\n}\n\n/**\n * 解析为Date对象\n * @param dateValue - 可以是数值、字符串或 Date 对象\n * @returns 解析后的 Date 对象\n * @throws {SyntaxError} 如果无法解析为有效的日期对象,则抛出错误\n * @example\n * ```typescript\n * dateParse('2023-01-01'); // Date对象\n * dateParse(1672531200000); // Date对象\n * dateParse(new Date()); // Date对象\n * dateParse('invalid date'); // 抛出 SyntaxError\n * ```\n */\nexport function dateParse(dateValue: DateValue): DateLike {\n // 传入的 Date 对象有 Date、TzDate\n // @ts-ignore\n const d1 = isDate(dateValue)\n ? new Date(dateValue)\n : dateValue instanceof TzDate\n ? new TzDate(dateValue)\n : new Date(dateValue);\n if (isValidDate(d1)) return d1;\n\n // safari 浏览器的日期解析有问题\n // new Date('2020-06-26 18:06:15') 返回值是一个非法日期对象\n const d2 = _guessDateSeparator(dateValue);\n if (isValidDate(d2)) return d2;\n\n // safari 浏览器的日期解析有问题\n // new Date('2020-06-26T18:06:15.000+0800') 返回值是一个非法日期对象\n const d3 = _guessDateTimezone(dateValue);\n if (isValidDate(d3)) return d3;\n\n throw new SyntaxError(`${dateValue.toString()} 不是一个合法的日期值`);\n}\n\nfunction _pad(num: number, len = 2) {\n return `${num}`.padStart(len, '0');\n}\n\nconst rules: [RegExp, (date: DateLike) => number | string][] = [\n [/Y{4}/gi, (date) => date.getFullYear()],\n [/Y{2}/gi, (date) => date.getFullYear() % 100],\n [/M{2}/g, (date) => _pad(date.getMonth() + 1)],\n [/M{1}/g, (date) => date.getMonth() + 1],\n [/D{2}/gi, (date) => _pad(date.getDate())],\n [/D{1}/gi, (date) => date.getDate()],\n [/H{2}/g, (date) => _pad(date.getHours())],\n [/H{1}/g, (date) => date.getHours()],\n [\n /h{2}/g,\n (date) => {\n const h = date.getHours();\n return _pad(h > 12 ? h - 12 : h);\n },\n ],\n [\n /h{1}/g,\n (date) => {\n const h = date.getHours();\n return h > 12 ? h - 12 : h;\n },\n ],\n [/m{2}/g, (date) => _pad(date.getMinutes())],\n [/m{1}/g, (date) => date.getMinutes()],\n [/s{2}/g, (date) => _pad(date.getSeconds())],\n [/s{1}/g, (date) => date.getSeconds()],\n [/S{3}/g, (date) => _pad(date.getMilliseconds(), 3)],\n [/S{2}/g, (date) => _pad(date.getMilliseconds(), 2)],\n [/S{1}/g, (date) => date.getMilliseconds()],\n];\n\n/**\n * 格式化为日期字符串(带自定义格式化模板)\n * @param dateValue - 可以是数值、字符串或 Date 对象\n * @param format - 模板,默认是 'YYYY-MM-DD HH:mm:ss',模板字符:\n * - YYYY:年\n * - yyyy: 年\n * - MM:月\n * - DD:日\n * - dd: 日\n * - HH:时(24 小时制)\n * - hh:时(12 小时制)\n * - mm:分\n * - ss:秒\n * - SSS:毫秒\n * @returns 格式化后的日期字符串\n * @example\n * ```typescript\n * dateFormat(new Date(), 'YYYY-MM-DD'); // '2023-01-01'\n * dateFormat(1672531200000, 'YYYY/MM/DD HH:mm:ss'); // '2023/01/01 00:00:00'\n * dateFormat('2023-01-01', 'YYYY年MM月DD日'); // '2023年01月01日'\n * ```\n */\nexport function dateFormat(dateValue: DateValue, format = 'YYYY-MM-DD HH:mm:ss'): string {\n const date = dateParse(dateValue);\n let result = format;\n\n for (const rule of rules) {\n result = result.replace(rule[0], String(rule[1](date)));\n }\n\n return result;\n}\n"],"names":["timestamp"],"mappings":";AAgCA,MAAM,eAAe,KAAK;AAKnB,MAAM,OAAO;AAAA;AAAA;AAAA;AAAA,EAIlB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,OAAO,UAAU;AAAA;AAAA;AAAA;AAAA,EAKlC,mBAAmB,KAAK,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAKzC,kBAAkB;AAAA;AAAA;AAAA;AAAA,EAKlB,oBAAoB;AAAA;AAAA;AAAA;AAAA,EAKpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,SAAkC;AACvC,SAAA,YACF,mBAAmB,SAChB;AAAA,MACE,WAAW,QAAQ,QAAQ;AAAA,MAC3B,QAAQ,QAAQ,kBAAkB;AAAA,IACpC,IACA,YAAY,CAAC;AACnB,UAAM,EAAE,QAAQ,WAAW,UAAU,KAAK;AAC1C,SAAK,kBAAkB,SAAS,MAAM,IAAI,SAAS,KAAK;AACnD,SAAA,oBAAoB,KAAK,kBAAkB;AAEhD,QAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,GAAG;AACtC,YAAA,CAAC,UAAU,OAAO,KAAK,OAAO,SAAS,SAAS,YAAY,IAAI;AACtE,YAAMA,aAAY,KAAK;AAAA,QACrB,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,QACX,gBAAgB;AAAA,MAClB;AAEK,WAAA,aAAaA,aAAY,KAAK;AAAA,IAAA,OAC9B;AACA,WAAA,aAAa,aAAa,KAAK,IAAI;AAAA,IAAA;AAGrC,SAAA,cAAc,IAAI,KAAK,KAAK,aAAa,KAAK,mBAAmB,KAAK,iBAAiB;AAC5F,SAAK,WAAW,IAAI,KAAK,KAAK,aAAa,KAAK,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMlE,mBAAmB;AACjB,SAAK,aAAa,KAAK,YAAY,YAAY,KAAK,oBAAoB,KAAK;AAC7E,SAAK,WAAW,IAAI,KAAK,KAAK,aAAa,KAAK,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlE,oBAAoB;AAClB,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,mBAAmB;AACV,WAAA,OAAO,SAAS,KAAK,eAAe;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7C,cAAc;AACL,WAAA,KAAK,YAAY,YAAY;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtC,WAAW;AACF,WAAA,KAAK,YAAY,SAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnC,UAAU;AACD,WAAA,KAAK,YAAY,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlC,WAAW;AACF,WAAA,KAAK,YAAY,SAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnC,aAAa;AACJ,WAAA,KAAK,YAAY,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,aAAa;AACJ,WAAA,KAAK,YAAY,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,kBAAkB;AACT,WAAA,KAAK,YAAY,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU1C,YAAY,MAAc,OAAgB,MAAe;AAClD,SAAA,YAAY,YAAY,IAAI;AACjC,SAAK,iBAAiB;AAEtB,QAAI,SAAS,KAAK,EAAG,MAAK,SAAS,KAAK;AACxC,QAAI,SAAS,IAAI,EAAG,MAAK,QAAQ,IAAI;AAErC,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStB,SAAS,OAAe,MAAe;AAChC,SAAA,YAAY,SAAS,KAAK;AAC/B,SAAK,iBAAiB;AAEtB,QAAI,SAAS,IAAI,EAAG,MAAK,QAAQ,IAAI;AAErC,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,QAAQ,MAAc;AACf,SAAA,YAAY,QAAQ,IAAI;AAC7B,SAAK,iBAAiB;AAEtB,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWtB,SAAS,OAAe,SAAkB,SAAkB,cAAuB;AAC5E,SAAA,YAAY,SAAS,KAAK;AAC/B,SAAK,iBAAiB;AAEtB,QAAI,SAAS,OAAO,EAAG,MAAK,WAAW,OAAO;AAC9C,QAAI,SAAS,OAAO,EAAG,MAAK,WAAW,OAAO;AAC9C,QAAI,SAAS,YAAY,EAAG,MAAK,gBAAgB,YAAY;AAE7D,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUtB,WAAW,SAAiB,SAAkB,cAAuB;AAC9D,SAAA,YAAY,WAAW,OAAO;AACnC,SAAK,iBAAiB;AAEtB,QAAI,SAAS,OAAO,EAAG,MAAK,WAAW,OAAO;AAC9C,QAAI,SAAS,YAAY,EAAG,MAAK,gBAAgB,YAAY;AAE7D,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStB,WAAW,SAAiB,cAAuB;AAC5C,SAAA,YAAY,WAAW,OAAO;AACnC,SAAK,iBAAiB;AAEtB,QAAI,SAAS,YAAY,EAAG,MAAK,gBAAgB,YAAY;AAE7D,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,gBAAgB,cAAsB;AAC/B,SAAA,YAAY,gBAAgB,YAAY;AAC7C,SAAK,iBAAiB;AAEtB,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtB,UAAU;AACR,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,SAAS;AACA,WAAA,KAAK,YAAY,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjC,cAAc;AACL,WAAA,WAAW,KAAK,UAAU,0BAA0B;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAa7D,OAAO,KAAK,IAAY,SAAS,OAAO,aAAa;AACnD,WAAO,IAAI,OAAO;AAAA,MAChB;AAAA,MACA,WAAW,GAAG,QAAQ;AAAA,IAAA,CACvB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQH,OAAO,SAAS,SAAS,OAAO,aAAa;AAC3C,WAAO,SAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQlB,OAAO,UAAU,UAAmB;AAC3B,WAAA,SAAS,QAAQ,IAAI,WAAW,OAAU,oBAAA,QAAO,kBAAkB;AAAA,EAAA;AAE9E;ACzVO,SAAS,YAAY,SAA4C;AACtE,SACG,mBAAmB,QAAQ,CAAC,OAAO,MAAM,QAAQ,QAAQ,CAAC,KAC1D,mBAAmB,UAAU,CAAC,OAAO,MAAM,QAAQ,SAAS;AAEjE;AAKA,SAAS,oBAAoB,OAAoC;AAC3D,MAAA,CAAC,SAAS,KAAK,EAAG;AAEtB,QAAM,SAAS,MAAM,QAAQ,MAAM,GAAG;AAE/B,SAAA,IAAI,KAAK,MAAM;AACxB;AAEA,SAAS,mBAAmB,OAAoC;AAC1D,MAAA,CAAC,SAAS,KAAK,EAAG;AAEtB,QAAM,KAAK;AAEL,QAAA,UAAU,GAAG,KAAK,KAAK;AAE7B,MAAI,CAAC,QAAS;AAEd,QAAM,SAAS,MAAM,QAAQ,IAAI,GAAG;AAC9B,QAAA,IAAI,IAAI,KAAK,MAAM;AAErB,MAAA,CAAC,YAAY,CAAC,EAAG;AAErB,QAAM,GAAG,MAAM,OAAO,OAAO,IAAI;AACjC,QAAM,SAAS,OAAO,SAAS,OAAO,EAAE;AACxC,QAAM,WAAW,OAAO,SAAS,SAAS,EAAE;AACtC,QAAA,SAAS,CAAC,GAAW,MAAuB,SAAS,MAAM,IAAI,IAAI,IAAI;AAE7E,IAAE,SAAS,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;AACvC,IAAE,WAAW,OAAO,EAAE,WAAW,GAAG,QAAQ,CAAC;AAEtC,SAAA;AACT;AAeO,SAAS,UAAU,WAAgC;AAGxD,QAAM,KAAK,OAAO,SAAS,IACvB,IAAI,KAAK,SAAS,IAClB,qBAAqB,SACnB,IAAI,OAAO,SAAS,IACpB,IAAI,KAAK,SAAS;AACpB,MAAA,YAAY,EAAE,EAAU,QAAA;AAItB,QAAA,KAAK,oBAAoB,SAAS;AACpC,MAAA,YAAY,EAAE,EAAU,QAAA;AAItB,QAAA,KAAK,mBAAmB,SAAS;AACnC,MAAA,YAAY,EAAE,EAAU,QAAA;AAE5B,QAAM,IAAI,YAAY,GAAG,UAAU,SAAA,CAAU,aAAa;AAC5D;AAEA,SAAS,KAAK,KAAa,MAAM,GAAG;AAClC,SAAO,GAAG,GAAG,GAAG,SAAS,KAAK,GAAG;AACnC;AAEA,MAAM,QAAyD;AAAA,EAC7D,CAAC,UAAU,CAAC,SAAS,KAAK,aAAa;AAAA,EACvC,CAAC,UAAU,CAAC,SAAS,KAAK,YAAA,IAAgB,GAAG;AAAA,EAC7C,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,SAAA,IAAa,CAAC,CAAC;AAAA,EAC7C,CAAC,SAAS,CAAC,SAAS,KAAK,SAAA,IAAa,CAAC;AAAA,EACvC,CAAC,UAAU,CAAC,SAAS,KAAK,KAAK,QAAA,CAAS,CAAC;AAAA,EACzC,CAAC,UAAU,CAAC,SAAS,KAAK,SAAS;AAAA,EACnC,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,SAAA,CAAU,CAAC;AAAA,EACzC,CAAC,SAAS,CAAC,SAAS,KAAK,UAAU;AAAA,EACnC;AAAA,IACE;AAAA,IACA,CAAC,SAAS;AACF,YAAA,IAAI,KAAK,SAAS;AACxB,aAAO,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAAA,IAAA;AAAA,EAEnC;AAAA,EACA;AAAA,IACE;AAAA,IACA,CAAC,SAAS;AACF,YAAA,IAAI,KAAK,SAAS;AACjB,aAAA,IAAI,KAAK,IAAI,KAAK;AAAA,IAAA;AAAA,EAE7B;AAAA,EACA,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,WAAA,CAAY,CAAC;AAAA,EAC3C,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY;AAAA,EACrC,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,WAAA,CAAY,CAAC;AAAA,EAC3C,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY;AAAA,EACrC,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,gBAAA,GAAmB,CAAC,CAAC;AAAA,EACnD,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,gBAAA,GAAmB,CAAC,CAAC;AAAA,EACnD,CAAC,SAAS,CAAC,SAAS,KAAK,gBAAiB,CAAA;AAC5C;AAwBgB,SAAA,WAAW,WAAsB,SAAS,uBAA+B;AACjF,QAAA,OAAO,UAAU,SAAS;AAChC,MAAI,SAAS;AAEb,aAAW,QAAQ,OAAO;AACf,aAAA,OAAO,QAAQ,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;AAAA,EAAA;AAGjD,SAAA;AACT;"}
|
|
1
|
+
{"version":3,"file":"core.mjs","sources":["../src/date/timezone.ts","../src/date/core.ts"],"sourcesContent":["import { isNumber } from '../type';\nimport { dateFormat } from './core';\n\nexport type TimezoneDateOptions = {\n /**\n * 时间戳\n * @default Date.now()\n */\n timestamp?: number;\n\n /**\n * 日期值\n */\n value?: readonly [\n year?: number,\n month?: number,\n day?: number,\n hours?: number,\n minutes?: number,\n seconds?: number,\n milliseconds?: number,\n ];\n\n /**\n * UTC 时区,支持负数和小数,例如:\n * - 8 表示 UTC+8\n * - -12 表示 UTC-12\n * - 0 表示 UTC 时间\n * - 12.5 表示 UTC+12:30\n */\n utcOffset?: number;\n};\n\n/**\n * 时区偏移量毫秒常量(1分钟 = 60 * 1000 毫秒)\n */\nconst TIMEZONE_OFFSET_MS = 60 * 1000;\n\n/**\n * 时区日期类,用于处理不同时区的日期时间\n */\nexport class TimezoneDate {\n /**\n * 内部时间戳\n */\n #timestamp: number;\n\n /**\n * 目标时区的日期对象\n */\n #targetDate: Date;\n\n /**\n * UTC 日期对象\n */\n #utcDate: Date;\n\n /**\n * 本地时区偏移量(分钟)\n */\n #localTimezoneOffset = TimezoneDate.getTimezoneOffset();\n\n /**\n * 本地时区偏移量(毫秒)\n */\n #localTimezoneOffsetMS = this.#localTimezoneOffset * TIMEZONE_OFFSET_MS;\n\n /**\n * 目标时区偏移量(分钟)\n */\n #targetTimezoneOffset = 0;\n\n /**\n * 目标时区偏移量(毫秒)\n */\n #targetTimezoneOffsetMS = 0;\n\n /**\n * 构造函数选项\n */\n #options: TimezoneDateOptions;\n\n /**\n * 构造一个 TimezoneDate 实例\n * @param options - 配置选项\n */\n constructor(options?: TimezoneDateOptions | TimezoneDate) {\n this.#options =\n (options instanceof TimezoneDate\n ? {\n timestamp: options.getTime(),\n utcOffset: options.getUTCOffset(),\n }\n : options) || {};\n const { utcOffset, timestamp, value } = this.#options;\n this.#targetTimezoneOffset = isNumber(utcOffset)\n ? TimezoneDate.getTimezoneOffset(utcOffset)\n : this.#localTimezoneOffset;\n this.#targetTimezoneOffsetMS = this.#targetTimezoneOffset * TIMEZONE_OFFSET_MS;\n\n if (Array.isArray(value) && value.length > 0) {\n const [fullYear, month, day, hours, minutes, seconds, milliseconds] = value;\n const timestamp = Date.UTC(\n fullYear ?? 0,\n month ?? 0,\n day ?? 1,\n hours ?? 0,\n minutes ?? 0,\n seconds ?? 0,\n milliseconds ?? 0,\n );\n\n this.#timestamp = timestamp + this.#targetTimezoneOffsetMS;\n } else {\n this.#timestamp = timestamp || Date.now();\n }\n\n this.#targetDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS - this.#targetTimezoneOffsetMS);\n this.#utcDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS);\n }\n\n /**\n * 更新内部时间戳\n */\n #updateTimestamp() {\n this.#timestamp = this.#targetDate.getTime() + this.#targetTimezoneOffsetMS - this.#localTimezoneOffsetMS;\n this.#utcDate = new Date(this.#timestamp + this.#localTimezoneOffsetMS);\n }\n\n /**\n * 获取时区偏移量(分钟)\n * @returns 时区偏移量\n */\n getTimezoneOffset() {\n return this.#targetTimezoneOffset;\n }\n\n /**\n * 获取时区偏移量(UTC)\n * @returns 时区序号\n */\n getUTCOffset() {\n return TimezoneDate.getUTCOffset(this.#targetTimezoneOffset);\n }\n\n /**\n * 获取年份\n * @returns 年份\n */\n getFullYear() {\n return this.#targetDate.getFullYear();\n }\n\n /**\n * 获取月份\n * @returns 月份 (0-11)\n */\n getMonth() {\n return this.#targetDate.getMonth();\n }\n\n /**\n * 获取日期\n * @returns 日期 (1-31)\n */\n getDate() {\n return this.#targetDate.getDate();\n }\n\n /**\n * 获取小时\n * @returns 小时 (0-23)\n */\n getHours() {\n return this.#targetDate.getHours();\n }\n\n /**\n * 获取分钟\n * @returns 分钟 (0-59)\n */\n getMinutes() {\n return this.#targetDate.getMinutes();\n }\n\n /**\n * 获取秒数\n * @returns 秒数 (0-59)\n */\n getSeconds() {\n return this.#targetDate.getSeconds();\n }\n\n /**\n * 获取毫秒\n * @returns 毫秒 (0-999)\n */\n getMilliseconds() {\n return this.#targetDate.getMilliseconds();\n }\n\n /**\n * 设置年份\n * @param year - 年份\n * @param month - 月份\n * @param date - 日期\n * @returns 时间戳\n */\n setFullYear(year: number, month?: number, date?: number) {\n this.#targetDate.setFullYear(year);\n this.#updateTimestamp();\n\n if (isNumber(month)) this.setMonth(month);\n if (isNumber(date)) this.setDate(date);\n\n return this.getTime();\n }\n\n /**\n * 设置月份\n * @param month - 月份\n * @param date - 日期\n * @returns 时间戳\n */\n setMonth(month: number, date?: number) {\n this.#targetDate.setMonth(month);\n this.#updateTimestamp();\n\n if (isNumber(date)) this.setDate(date);\n\n return this.getTime();\n }\n\n /**\n * 设置日期\n * @param date - 日期\n * @returns 时间戳\n */\n setDate(date: number) {\n this.#targetDate.setDate(date);\n this.#updateTimestamp();\n\n return this.getTime();\n }\n\n /**\n * 设置小时\n * @param hours - 小时\n * @param minutes - 分钟\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setHours(hours: number, minutes?: number, seconds?: number, milliseconds?: number) {\n this.#targetDate.setHours(hours);\n this.#updateTimestamp();\n\n if (isNumber(minutes)) this.setMinutes(minutes);\n if (isNumber(seconds)) this.setSeconds(seconds);\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置分钟\n * @param minutes - 分钟\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setMinutes(minutes: number, seconds?: number, milliseconds?: number) {\n this.#targetDate.setMinutes(minutes);\n this.#updateTimestamp();\n\n if (isNumber(seconds)) this.setSeconds(seconds);\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置秒数\n * @param seconds - 秒数\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setSeconds(seconds: number, milliseconds?: number) {\n this.#targetDate.setSeconds(seconds);\n this.#updateTimestamp();\n\n if (isNumber(milliseconds)) this.setMilliseconds(milliseconds);\n\n return this.getTime();\n }\n\n /**\n * 设置毫秒\n * @param milliseconds - 毫秒\n * @returns 时间戳\n */\n setMilliseconds(milliseconds: number) {\n this.#targetDate.setMilliseconds(milliseconds);\n this.#updateTimestamp();\n\n return this.getTime();\n }\n\n /**\n * 获取时间戳\n * @returns 时间戳\n */\n getTime() {\n return this.#timestamp;\n }\n\n /**\n * 获取星期几\n * @returns 星期几 (0-6, 0表示周日)\n */\n getDay() {\n return this.#targetDate.getDay();\n }\n\n /**\n * 转换为 ISO 格式的字符串\n * @returns ISO 格式的时间字符串\n */\n toISOString() {\n return dateFormat(this.#utcDate, 'YYYY-MM-DDTHH:mm:ss.SSSZ');\n }\n\n /**\n * 转换为指定时区的 TimezoneDate 对象\n * @param td - 需要转换的日期对象\n * @param offset - 目标时区分钟偏移量,默认为当前时区\n * @returns 返回一个 TimezoneDate 对象\n * @example\n * ```js\n * // 转换为 UTC 时间\n * const utc0Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 0);\n *\n * // 转换为东八区时间\n * const utc8Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 8);\n * ```\n */\n static changeUtcOffset(td: TimezoneDate, utcOffset: number) {\n return new TimezoneDate({\n utcOffset,\n timestamp: td.getTime(),\n });\n }\n\n /**\n * 获取时区分钟偏移量\n * @param utcOffset - 默认使用当前时区\n * @returns 时区分钟偏移量\n */\n static getTimezoneOffset(utcOffset?: number) {\n return isNumber(utcOffset) ? utcOffset * -60 : new Date().getTimezoneOffset();\n }\n\n /**\n * 获取时区序号\n * @param timezoneOffset - 默认使用当前时区分钟偏移量\n * @returns 时区序号\n */\n static getUTCOffset(timezoneOffset = TimezoneDate.getTimezoneOffset()) {\n return timezoneOffset / -60;\n }\n}\n","import { objectEach } from '@/object';\nimport { isDate, isString } from '@/type';\nimport { TimezoneDate } from './timezone';\n\n/**\n * 判断一个值是否为有效的日期对象\n * @param unknown - 需要判断的值\n * @returns 如果值是有效的日期对象则返回 true,否则返回 false\n * @example\n * ```typescript\n * isValidDate(new Date()); // true\n * isValidDate('2023-01-01'); // false\n * isValidDate(NaN); // false\n * ```\n */\nexport function isValidDate(unknown: unknown): unknown is Date | TimezoneDate {\n return (\n (unknown instanceof Date && !Number.isNaN(unknown.getTime())) ||\n (unknown instanceof TimezoneDate && !Number.isNaN(unknown.getTime()))\n );\n}\n\nexport type DateLike = Date | TimezoneDate;\nexport type DateValue = number | string | DateLike;\n\nfunction _guessDateSeparator(value: DateValue): Date | undefined {\n if (!isString(value)) return;\n\n const value2 = value.replace(/-/g, '/');\n\n return new Date(value2);\n}\n\nfunction _guessDateTimezone(value: DateValue): Date | undefined {\n if (!isString(value)) return;\n\n const re = /([+-])(\\d\\d)(\\d\\d)$/;\n\n const matches = re.exec(value);\n\n if (!matches) return;\n\n const value2 = value.replace(re, 'Z');\n const d = new Date(value2);\n\n if (!isValidDate(d)) return;\n\n const [, flag, hours, minutes] = matches;\n const hours2 = Number.parseInt(hours, 10);\n const minutes2 = Number.parseInt(minutes, 10);\n const offset = (a: number, b: number): number => (flag === '+' ? a - b : a + b);\n\n d.setHours(offset(d.getHours(), hours2));\n d.setMinutes(offset(d.getMinutes(), minutes2));\n\n return d;\n}\n\n/**\n * 解析为Date对象\n * @param dateValue - 可以是数值、字符串或 Date 对象\n * @returns 解析后的 Date 对象\n * @throws {SyntaxError} 如果无法解析为有效的日期对象,则抛出错误\n * @example\n * ```typescript\n * dateParse('2023-01-01'); // Date对象\n * dateParse(1672531200000); // Date对象\n * dateParse(new Date()); // Date对象\n * dateParse('invalid date'); // 抛出 SyntaxError\n * ```\n */\nexport function dateParse(dateValue: DateValue): DateLike {\n // 传入的 Date 对象有 Date、TimezoneDate\n // @ts-ignore\n const d1 = isDate(dateValue)\n ? new Date(dateValue)\n : dateValue instanceof TimezoneDate\n ? new TimezoneDate(dateValue)\n : new Date(dateValue);\n if (isValidDate(d1)) return d1;\n\n // safari 浏览器的日期解析有问题\n // new Date('2020-06-26 18:06:15') 返回值是一个非法日期对象\n const d2 = _guessDateSeparator(dateValue);\n if (isValidDate(d2)) return d2;\n\n // safari 浏览器的日期解析有问题\n // new Date('2020-06-26T18:06:15.000+0800') 返回值是一个非法日期对象\n const d3 = _guessDateTimezone(dateValue);\n if (isValidDate(d3)) return d3;\n\n throw new SyntaxError(`${dateValue.toString()} 不是一个合法的日期值`);\n}\n\nfunction _pad(num: number, len = 2) {\n return `${num}`.padStart(len, '0');\n}\n\nconst rules: [RegExp, (date: DateLike) => number | string][] = [\n [/Y{4}/gi, (date) => date.getFullYear()],\n [/Y{2}/gi, (date) => date.getFullYear() % 100],\n [/M{2}/g, (date) => _pad(date.getMonth() + 1)],\n [/M{1}/g, (date) => date.getMonth() + 1],\n [/D{2}/gi, (date) => _pad(date.getDate())],\n [/D{1}/gi, (date) => date.getDate()],\n [/H{2}/g, (date) => _pad(date.getHours())],\n [/H{1}/g, (date) => date.getHours()],\n [\n /h{2}/g,\n (date) => {\n const h = date.getHours();\n return _pad(h > 12 ? h - 12 : h);\n },\n ],\n [\n /h{1}/g,\n (date) => {\n const h = date.getHours();\n return h > 12 ? h - 12 : h;\n },\n ],\n [/m{2}/g, (date) => _pad(date.getMinutes())],\n [/m{1}/g, (date) => date.getMinutes()],\n [/s{2}/g, (date) => _pad(date.getSeconds())],\n [/s{1}/g, (date) => date.getSeconds()],\n [/S{3}/g, (date) => _pad(date.getMilliseconds(), 3)],\n [/S{2}/g, (date) => _pad(date.getMilliseconds(), 2)],\n [/S{1}/g, (date) => date.getMilliseconds()],\n];\n\n/**\n * 格式化为日期字符串(带自定义格式化模板)\n * @param dateValue - 可以是数值、字符串或 Date 对象\n * @param format - 模板,默认是 'YYYY-MM-DD HH:mm:ss',模板字符:\n * - YYYY:年\n * - yyyy: 年\n * - MM:月\n * - DD:日\n * - dd: 日\n * - HH:时(24 小时制)\n * - hh:时(12 小时制)\n * - mm:分\n * - ss:秒\n * - SSS:毫秒\n * @returns 格式化后的日期字符串\n * @example\n * ```typescript\n * dateFormat(new Date(), 'YYYY-MM-DD'); // '2023-01-01'\n * dateFormat(1672531200000, 'YYYY/MM/DD HH:mm:ss'); // '2023/01/01 00:00:00'\n * dateFormat('2023-01-01', 'YYYY年MM月DD日'); // '2023年01月01日'\n * ```\n */\nexport function dateFormat(dateValue: DateValue, format = 'YYYY-MM-DD HH:mm:ss'): string {\n const date = dateParse(dateValue);\n let result = format;\n\n for (const rule of rules) {\n result = result.replace(rule[0], String(rule[1](date)));\n }\n\n return result;\n}\n"],"names":["timestamp"],"mappings":";AAoCA,MAAM,qBAAqB,KAAK;AAKzB,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA,EAIxB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,aAAa,kBAAkB;AAAA;AAAA;AAAA;AAAA,EAKtD,yBAAyB,KAAK,uBAAuB;AAAA;AAAA;AAAA;AAAA,EAKrD,wBAAwB;AAAA;AAAA;AAAA;AAAA,EAKxB,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAK1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,SAA8C;AACnD,SAAA,YACF,mBAAmB,eAChB;AAAA,MACE,WAAW,QAAQ,QAAQ;AAAA,MAC3B,WAAW,QAAQ,aAAa;AAAA,IAClC,IACA,YAAY,CAAC;AACnB,UAAM,EAAE,WAAW,WAAW,UAAU,KAAK;AACxC,SAAA,wBAAwB,SAAS,SAAS,IAC3C,aAAa,kBAAkB,SAAS,IACxC,KAAK;AACJ,SAAA,0BAA0B,KAAK,wBAAwB;AAE5D,QAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,GAAG;AACtC,YAAA,CAAC,UAAU,OAAO,KAAK,OAAO,SAAS,SAAS,YAAY,IAAI;AACtE,YAAMA,aAAY,KAAK;AAAA,QACrB,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,QACX,gBAAgB;AAAA,MAClB;AAEK,WAAA,aAAaA,aAAY,KAAK;AAAA,IAAA,OAC9B;AACA,WAAA,aAAa,aAAa,KAAK,IAAI;AAAA,IAAA;AAGrC,SAAA,cAAc,IAAI,KAAK,KAAK,aAAa,KAAK,yBAAyB,KAAK,uBAAuB;AACxG,SAAK,WAAW,IAAI,KAAK,KAAK,aAAa,KAAK,sBAAsB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMxE,mBAAmB;AACjB,SAAK,aAAa,KAAK,YAAY,YAAY,KAAK,0BAA0B,KAAK;AACnF,SAAK,WAAW,IAAI,KAAK,KAAK,aAAa,KAAK,sBAAsB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxE,oBAAoB;AAClB,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,eAAe;AACN,WAAA,aAAa,aAAa,KAAK,qBAAqB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7D,cAAc;AACL,WAAA,KAAK,YAAY,YAAY;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtC,WAAW;AACF,WAAA,KAAK,YAAY,SAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnC,UAAU;AACD,WAAA,KAAK,YAAY,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlC,WAAW;AACF,WAAA,KAAK,YAAY,SAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnC,aAAa;AACJ,WAAA,KAAK,YAAY,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,aAAa;AACJ,WAAA,KAAK,YAAY,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,kBAAkB;AACT,WAAA,KAAK,YAAY,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU1C,YAAY,MAAc,OAAgB,MAAe;AAClD,SAAA,YAAY,YAAY,IAAI;AACjC,SAAK,iBAAiB;AAEtB,QAAI,SAAS,KAAK,EAAG,MAAK,SAAS,KAAK;AACxC,QAAI,SAAS,IAAI,EAAG,MAAK,QAAQ,IAAI;AAErC,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStB,SAAS,OAAe,MAAe;AAChC,SAAA,YAAY,SAAS,KAAK;AAC/B,SAAK,iBAAiB;AAEtB,QAAI,SAAS,IAAI,EAAG,MAAK,QAAQ,IAAI;AAErC,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,QAAQ,MAAc;AACf,SAAA,YAAY,QAAQ,IAAI;AAC7B,SAAK,iBAAiB;AAEtB,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWtB,SAAS,OAAe,SAAkB,SAAkB,cAAuB;AAC5E,SAAA,YAAY,SAAS,KAAK;AAC/B,SAAK,iBAAiB;AAEtB,QAAI,SAAS,OAAO,EAAG,MAAK,WAAW,OAAO;AAC9C,QAAI,SAAS,OAAO,EAAG,MAAK,WAAW,OAAO;AAC9C,QAAI,SAAS,YAAY,EAAG,MAAK,gBAAgB,YAAY;AAE7D,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUtB,WAAW,SAAiB,SAAkB,cAAuB;AAC9D,SAAA,YAAY,WAAW,OAAO;AACnC,SAAK,iBAAiB;AAEtB,QAAI,SAAS,OAAO,EAAG,MAAK,WAAW,OAAO;AAC9C,QAAI,SAAS,YAAY,EAAG,MAAK,gBAAgB,YAAY;AAE7D,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStB,WAAW,SAAiB,cAAuB;AAC5C,SAAA,YAAY,WAAW,OAAO;AACnC,SAAK,iBAAiB;AAEtB,QAAI,SAAS,YAAY,EAAG,MAAK,gBAAgB,YAAY;AAE7D,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,gBAAgB,cAAsB;AAC/B,SAAA,YAAY,gBAAgB,YAAY;AAC7C,SAAK,iBAAiB;AAEtB,WAAO,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtB,UAAU;AACR,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,SAAS;AACA,WAAA,KAAK,YAAY,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjC,cAAc;AACL,WAAA,WAAW,KAAK,UAAU,0BAA0B;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiB7D,OAAO,gBAAgB,IAAkB,WAAmB;AAC1D,WAAO,IAAI,aAAa;AAAA,MACtB;AAAA,MACA,WAAW,GAAG,QAAQ;AAAA,IAAA,CACvB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQH,OAAO,kBAAkB,WAAoB;AACpC,WAAA,SAAS,SAAS,IAAI,YAAY,OAAU,oBAAA,QAAO,kBAAkB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ9E,OAAO,aAAa,iBAAiB,aAAa,qBAAqB;AACrE,WAAO,iBAAiB;AAAA,EAAA;AAE5B;ACnWO,SAAS,YAAY,SAAkD;AAC5E,SACG,mBAAmB,QAAQ,CAAC,OAAO,MAAM,QAAQ,QAAQ,CAAC,KAC1D,mBAAmB,gBAAgB,CAAC,OAAO,MAAM,QAAQ,SAAS;AAEvE;AAKA,SAAS,oBAAoB,OAAoC;AAC3D,MAAA,CAAC,SAAS,KAAK,EAAG;AAEtB,QAAM,SAAS,MAAM,QAAQ,MAAM,GAAG;AAE/B,SAAA,IAAI,KAAK,MAAM;AACxB;AAEA,SAAS,mBAAmB,OAAoC;AAC1D,MAAA,CAAC,SAAS,KAAK,EAAG;AAEtB,QAAM,KAAK;AAEL,QAAA,UAAU,GAAG,KAAK,KAAK;AAE7B,MAAI,CAAC,QAAS;AAEd,QAAM,SAAS,MAAM,QAAQ,IAAI,GAAG;AAC9B,QAAA,IAAI,IAAI,KAAK,MAAM;AAErB,MAAA,CAAC,YAAY,CAAC,EAAG;AAErB,QAAM,GAAG,MAAM,OAAO,OAAO,IAAI;AACjC,QAAM,SAAS,OAAO,SAAS,OAAO,EAAE;AACxC,QAAM,WAAW,OAAO,SAAS,SAAS,EAAE;AACtC,QAAA,SAAS,CAAC,GAAW,MAAuB,SAAS,MAAM,IAAI,IAAI,IAAI;AAE7E,IAAE,SAAS,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;AACvC,IAAE,WAAW,OAAO,EAAE,WAAW,GAAG,QAAQ,CAAC;AAEtC,SAAA;AACT;AAeO,SAAS,UAAU,WAAgC;AAGxD,QAAM,KAAK,OAAO,SAAS,IACvB,IAAI,KAAK,SAAS,IAClB,qBAAqB,eACnB,IAAI,aAAa,SAAS,IAC1B,IAAI,KAAK,SAAS;AACpB,MAAA,YAAY,EAAE,EAAU,QAAA;AAItB,QAAA,KAAK,oBAAoB,SAAS;AACpC,MAAA,YAAY,EAAE,EAAU,QAAA;AAItB,QAAA,KAAK,mBAAmB,SAAS;AACnC,MAAA,YAAY,EAAE,EAAU,QAAA;AAE5B,QAAM,IAAI,YAAY,GAAG,UAAU,SAAA,CAAU,aAAa;AAC5D;AAEA,SAAS,KAAK,KAAa,MAAM,GAAG;AAClC,SAAO,GAAG,GAAG,GAAG,SAAS,KAAK,GAAG;AACnC;AAEA,MAAM,QAAyD;AAAA,EAC7D,CAAC,UAAU,CAAC,SAAS,KAAK,aAAa;AAAA,EACvC,CAAC,UAAU,CAAC,SAAS,KAAK,YAAA,IAAgB,GAAG;AAAA,EAC7C,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,SAAA,IAAa,CAAC,CAAC;AAAA,EAC7C,CAAC,SAAS,CAAC,SAAS,KAAK,SAAA,IAAa,CAAC;AAAA,EACvC,CAAC,UAAU,CAAC,SAAS,KAAK,KAAK,QAAA,CAAS,CAAC;AAAA,EACzC,CAAC,UAAU,CAAC,SAAS,KAAK,SAAS;AAAA,EACnC,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,SAAA,CAAU,CAAC;AAAA,EACzC,CAAC,SAAS,CAAC,SAAS,KAAK,UAAU;AAAA,EACnC;AAAA,IACE;AAAA,IACA,CAAC,SAAS;AACF,YAAA,IAAI,KAAK,SAAS;AACxB,aAAO,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAAA,IAAA;AAAA,EAEnC;AAAA,EACA;AAAA,IACE;AAAA,IACA,CAAC,SAAS;AACF,YAAA,IAAI,KAAK,SAAS;AACjB,aAAA,IAAI,KAAK,IAAI,KAAK;AAAA,IAAA;AAAA,EAE7B;AAAA,EACA,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,WAAA,CAAY,CAAC;AAAA,EAC3C,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY;AAAA,EACrC,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,WAAA,CAAY,CAAC;AAAA,EAC3C,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY;AAAA,EACrC,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,gBAAA,GAAmB,CAAC,CAAC;AAAA,EACnD,CAAC,SAAS,CAAC,SAAS,KAAK,KAAK,gBAAA,GAAmB,CAAC,CAAC;AAAA,EACnD,CAAC,SAAS,CAAC,SAAS,KAAK,gBAAiB,CAAA;AAC5C;AAwBgB,SAAA,WAAW,WAAsB,SAAS,uBAA+B;AACjF,QAAA,OAAO,UAAU,SAAS;AAChC,MAAI,SAAS;AAEb,aAAW,QAAQ,OAAO;AACf,aAAA,OAAO,QAAQ,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;AAAA,EAAA;AAGjD,SAAA;AACT;"}
|
package/dist/date/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TimezoneDate } from './timezone';
|
|
2
2
|
/**
|
|
3
3
|
* 判断一个值是否为有效的日期对象
|
|
4
4
|
* @param unknown - 需要判断的值
|
|
@@ -10,8 +10,8 @@ import { TzDate } from './timezone';
|
|
|
10
10
|
* isValidDate(NaN); // false
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
|
13
|
-
export declare function isValidDate(unknown: unknown): unknown is Date |
|
|
14
|
-
export type DateLike = Date |
|
|
13
|
+
export declare function isValidDate(unknown: unknown): unknown is Date | TimezoneDate;
|
|
14
|
+
export type DateLike = Date | TimezoneDate;
|
|
15
15
|
export type DateValue = number | string | DateLike;
|
|
16
16
|
/**
|
|
17
17
|
* 解析为Date对象
|
package/dist/date/timezone.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type TimezoneDateOptions = {
|
|
2
2
|
/**
|
|
3
3
|
* 时间戳
|
|
4
4
|
* @default Date.now()
|
|
@@ -17,30 +17,34 @@ export type TzDateOptions = {
|
|
|
17
17
|
milliseconds?: number
|
|
18
18
|
];
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* UTC 时区,支持负数和小数,例如:
|
|
21
|
+
* - 8 表示 UTC+8
|
|
22
|
+
* - -12 表示 UTC-12
|
|
23
|
+
* - 0 表示 UTC 时间
|
|
24
|
+
* - 12.5 表示 UTC+12:30
|
|
21
25
|
*/
|
|
22
|
-
|
|
26
|
+
utcOffset?: number;
|
|
23
27
|
};
|
|
24
28
|
/**
|
|
25
29
|
* 时区日期类,用于处理不同时区的日期时间
|
|
26
30
|
*/
|
|
27
|
-
export declare class
|
|
31
|
+
export declare class TimezoneDate {
|
|
28
32
|
#private;
|
|
29
33
|
/**
|
|
30
|
-
* 构造一个
|
|
34
|
+
* 构造一个 TimezoneDate 实例
|
|
31
35
|
* @param options - 配置选项
|
|
32
36
|
*/
|
|
33
|
-
constructor(options?:
|
|
37
|
+
constructor(options?: TimezoneDateOptions | TimezoneDate);
|
|
34
38
|
/**
|
|
35
39
|
* 获取时区偏移量(分钟)
|
|
36
40
|
* @returns 时区偏移量
|
|
37
41
|
*/
|
|
38
42
|
getTimezoneOffset(): number;
|
|
39
43
|
/**
|
|
40
|
-
*
|
|
44
|
+
* 获取时区偏移量(UTC)
|
|
41
45
|
* @returns 时区序号
|
|
42
46
|
*/
|
|
43
|
-
|
|
47
|
+
getUTCOffset(): number;
|
|
44
48
|
/**
|
|
45
49
|
* 获取年份
|
|
46
50
|
* @returns 年份
|
|
@@ -143,26 +147,30 @@ export declare class TzDate {
|
|
|
143
147
|
*/
|
|
144
148
|
toISOString(): string;
|
|
145
149
|
/**
|
|
146
|
-
*
|
|
150
|
+
* 转换为指定时区的 TimezoneDate 对象
|
|
147
151
|
* @param td - 需要转换的日期对象
|
|
148
152
|
* @param offset - 目标时区分钟偏移量,默认为当前时区
|
|
149
|
-
* @returns 返回一个
|
|
153
|
+
* @returns 返回一个 TimezoneDate 对象
|
|
150
154
|
* @example
|
|
151
155
|
* ```js
|
|
152
|
-
*
|
|
156
|
+
* // 转换为 UTC 时间
|
|
157
|
+
* const utc0Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 0);
|
|
158
|
+
*
|
|
159
|
+
* // 转换为东八区时间
|
|
160
|
+
* const utc8Td = TimezoneDate.changeUtcOffset(new TimezoneDate(), 8);
|
|
153
161
|
* ```
|
|
154
162
|
*/
|
|
155
|
-
static
|
|
156
|
-
/**
|
|
157
|
-
* 获取时区序号
|
|
158
|
-
* @param offset - 默认使用当前时区分钟偏移量
|
|
159
|
-
* @returns 时区序号
|
|
160
|
-
*/
|
|
161
|
-
static getOrder(offset?: number): number;
|
|
163
|
+
static changeUtcOffset(td: TimezoneDate, utcOffset: number): TimezoneDate;
|
|
162
164
|
/**
|
|
163
165
|
* 获取时区分钟偏移量
|
|
164
|
-
* @param
|
|
166
|
+
* @param utcOffset - 默认使用当前时区
|
|
165
167
|
* @returns 时区分钟偏移量
|
|
166
168
|
*/
|
|
167
|
-
static
|
|
169
|
+
static getTimezoneOffset(utcOffset?: number): number;
|
|
170
|
+
/**
|
|
171
|
+
* 获取时区序号
|
|
172
|
+
* @param timezoneOffset - 默认使用当前时区分钟偏移量
|
|
173
|
+
* @returns 时区序号
|
|
174
|
+
*/
|
|
175
|
+
static getUTCOffset(timezoneOffset?: number): number;
|
|
168
176
|
}
|
package/dist/date.cjs
CHANGED
|
@@ -206,7 +206,7 @@ exports.DATE_MINUTE_MS = _const.DATE_MINUTE_MS;
|
|
|
206
206
|
exports.DATE_MONTH_MS = _const.DATE_MONTH_MS;
|
|
207
207
|
exports.DATE_SECOND_MS = _const.DATE_SECOND_MS;
|
|
208
208
|
exports.DATE_YEAR_MS = _const.DATE_YEAR_MS;
|
|
209
|
-
exports.
|
|
209
|
+
exports.TimezoneDate = core.TimezoneDate;
|
|
210
210
|
exports.dateFormat = core.dateFormat;
|
|
211
211
|
exports.dateParse = core.dateParse;
|
|
212
212
|
exports.isValidDate = core.isValidDate;
|
package/dist/date.mjs
CHANGED
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED