@cloudcome/utils-core 1.18.1 → 1.18.2
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/README.md +112 -6
- package/dist/core.cjs +2 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.mjs +2 -2
- package/dist/core.mjs.map +1 -1
- package/dist/function.cjs +4 -1
- package/dist/function.cjs.map +1 -1
- package/dist/function.mjs +4 -1
- package/dist/function.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,14 +5,120 @@
|
|
|
5
5
|
[](https://app.codacy.com/gh/cloudcome/utils/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
6
6
|
[](https://app.codacy.com/gh/cloudcome/utils/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
|
|
7
7
|
|
|
8
|
+
跨平台、多框架的 TypeScript 工具函数库,覆盖浏览器、Node.js、Vue、React、UniApp 等环境。
|
|
9
|
+
|
|
10
|
+
## 包列表
|
|
8
11
|
|
|
9
12
|
| 名称 | 版本 | 描述 |
|
|
10
13
|
| --- | --- | --- |
|
|
11
|
-
| @cloudcome/utils-core | [](https://npmjs.com/package/@cloudcome/utils-core) |
|
|
12
|
-
| @cloudcome/utils-browser | [](https://npmjs.com/package/@cloudcome/utils-browser) |
|
|
13
|
-
| @cloudcome/utils-node| [](https://npmjs.com/package/@cloudcome/utils-node) | Node.js
|
|
14
|
-
| @cloudcome/utils-vue| [](https://npmjs.com/package/@cloudcome/utils-vue) | Vue
|
|
15
|
-
| @cloudcome/utils-react| [](https://npmjs.com/package/@cloudcome/utils-react) | React 工具库 |
|
|
16
|
-
| @cloudcome/utils-uni| [](https://npmjs.com/package/@cloudcome/utils-uni) | UniApp
|
|
14
|
+
| [@cloudcome/utils-core](./packages/utils-core) | [](https://npmjs.com/package/@cloudcome/utils-core) | 核心工具库,与运行环境无关的通用工具 |
|
|
15
|
+
| [@cloudcome/utils-browser](./packages/utils-browser) | [](https://npmjs.com/package/@cloudcome/utils-browser) | 浏览器端工具(DOM、Canvas、Cookie、剪贴板等) |
|
|
16
|
+
| [@cloudcome/utils-node](./packages/utils-node) | [](https://npmjs.com/package/@cloudcome/utils-node) | Node.js 端工具(Base64、加密等) |
|
|
17
|
+
| [@cloudcome/utils-vue](./packages/utils-vue) | [](https://npmjs.com/package/@cloudcome/utils-vue) | Vue 3 工具库(组合式函数、组件、请求等) |
|
|
18
|
+
| [@cloudcome/utils-react](./packages/utils-react) | [](https://npmjs.com/package/@cloudcome/utils-react) | React 工具库 |
|
|
19
|
+
| [@cloudcome/utils-uni](./packages/utils-uni) | [](https://npmjs.com/package/@cloudcome/utils-uni) | UniApp 工具库(云函数、数据库、页面等) |
|
|
20
|
+
| [@cloudcome/docs](./packages/docs) | - | VitePress 文档站点 |
|
|
21
|
+
|
|
22
|
+
## 功能概览
|
|
23
|
+
|
|
24
|
+
### @cloudcome/utils-core
|
|
25
|
+
|
|
26
|
+
核心工具库,提供以下子模块:
|
|
27
|
+
|
|
28
|
+
| 子模块 | 导入路径 | 功能 |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| array | `@cloudcome/utils-core/array` | 数组操作 |
|
|
31
|
+
| async | `@cloudcome/utils-core/async` | 异步工具 |
|
|
32
|
+
| base64 | `@cloudcome/utils-core/base64` | Base64 编解码 |
|
|
33
|
+
| cache | `@cloudcome/utils-core/cache` | 缓存工具 |
|
|
34
|
+
| color | `@cloudcome/utils-core/color` | 颜色转换(RGB/HSL/HSV/HWB/LAB/XYZ)、对比度、亮度、混合 |
|
|
35
|
+
| crypto | `@cloudcome/utils-core/crypto` | 加密(MD5、SHA1、SHA256、SHA512) |
|
|
36
|
+
| date | `@cloudcome/utils-core/date` | 日期解析、格式化、时区、相对时间、周/天计算 |
|
|
37
|
+
| dict | `@cloudcome/utils-core/dict` | 字典/映射工具 |
|
|
38
|
+
| easing | `@cloudcome/utils-core/easing` | 缓动函数 |
|
|
39
|
+
| emitter | `@cloudcome/utils-core/emitter` | 事件发射器 |
|
|
40
|
+
| env | `@cloudcome/utils-core/env` | 环境检测 |
|
|
41
|
+
| error | `@cloudcome/utils-core/error` | 错误处理 |
|
|
42
|
+
| exception | `@cloudcome/utils-core/exception` | 异常处理 |
|
|
43
|
+
| function | `@cloudcome/utils-core/function` | 函数工具 |
|
|
44
|
+
| number | `@cloudcome/utils-core/number` | 数字工具 |
|
|
45
|
+
| object | `@cloudcome/utils-core/object` | 对象遍历、深层 get/set、合并、类型判断 |
|
|
46
|
+
| path | `@cloudcome/utils-core/path` | 路径工具 |
|
|
47
|
+
| promise | `@cloudcome/utils-core/promise` | Promise 工具 |
|
|
48
|
+
| qs | `@cloudcome/utils-core/qs` | 查询字符串解析与序列化 |
|
|
49
|
+
| regexp | `@cloudcome/utils-core/regexp` | 正则表达式工具 |
|
|
50
|
+
| string | `@cloudcome/utils-core/string` | 字符串工具 |
|
|
51
|
+
| time | `@cloudcome/utils-core/time` | 时间单位转换 |
|
|
52
|
+
| timer | `@cloudcome/utils-core/timer` | 定时器工具 |
|
|
53
|
+
| tree | `@cloudcome/utils-core/tree` | 树结构操作 |
|
|
54
|
+
| try | `@cloudcome/utils-core/try` | 安全调用(try-catch 包装,支持同步/异步/柯里化) |
|
|
55
|
+
| type | `@cloudcome/utils-core/type` | 类型判断 |
|
|
56
|
+
| types | `@cloudcome/utils-core/types` | 公共类型定义 |
|
|
57
|
+
| unique | `@cloudcome/utils-core/unique` | 唯一 ID 生成 |
|
|
58
|
+
| url | `@cloudcome/utils-core/url` | URL 解析与构建 |
|
|
59
|
+
| version | `@cloudcome/utils-core/version` | 版本号比较 |
|
|
60
|
+
|
|
61
|
+
### @cloudcome/utils-browser
|
|
62
|
+
|
|
63
|
+
浏览器端工具库,依赖 `@cloudcome/utils-core`:
|
|
64
|
+
|
|
65
|
+
| 子模块 | 导入路径 | 功能 |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| base64 | `@cloudcome/utils-browser/base64` | 浏览器端 Base64 编解码 |
|
|
68
|
+
| cache | `@cloudcome/utils-browser/cache` | 浏览器缓存(localStorage/sessionStorage) |
|
|
69
|
+
| canvas | `@cloudcome/utils-browser/canvas` | Canvas 操作 |
|
|
70
|
+
| clipboard | `@cloudcome/utils-browser/clipboard` | 剪贴板读写 |
|
|
71
|
+
| cookie | `@cloudcome/utils-browser/cookie` | Cookie 读写 |
|
|
72
|
+
| dom | `@cloudcome/utils-browser/dom` | DOM 操作 |
|
|
73
|
+
| download | `@cloudcome/utils-browser/download` | 文件下载 |
|
|
74
|
+
| image | `@cloudcome/utils-browser/image` | 图片处理 |
|
|
75
|
+
| timer | `@cloudcome/utils-browser/timer` | 浏览器端定时器 |
|
|
76
|
+
| video | `@cloudcome/utils-browser/video` | 视频处理 |
|
|
77
|
+
|
|
78
|
+
### @cloudcome/utils-node
|
|
79
|
+
|
|
80
|
+
Node.js 端工具库:
|
|
81
|
+
|
|
82
|
+
| 子模块 | 导入路径 | 功能 |
|
|
83
|
+
| --- | --- | --- |
|
|
84
|
+
| base64 | `@cloudcome/utils-node/base64` | Node.js 端 Base64 编解码 |
|
|
85
|
+
| crypto | `@cloudcome/utils-node/crypto` | Node.js 端加密工具 |
|
|
86
|
+
|
|
87
|
+
### @cloudcome/utils-vue
|
|
88
|
+
|
|
89
|
+
Vue 3 工具库,依赖 `@cloudcome/utils-core` 和 `vue`:
|
|
90
|
+
|
|
91
|
+
| 子模块 | 导入路径 | 功能 |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| async | `@cloudcome/utils-vue/async` | Vue 异步组合式函数 |
|
|
94
|
+
| component | `@cloudcome/utils-vue/component` | 组件工具(生命周期等) |
|
|
95
|
+
| event | `@cloudcome/utils-vue/event` | 事件工具 |
|
|
96
|
+
| request | `@cloudcome/utils-vue/request` | 请求组合式函数(useRequest) |
|
|
97
|
+
| shared | `@cloudcome/utils-vue/shared` | 共享工具 |
|
|
98
|
+
| state | `@cloudcome/utils-vue/state` | 状态管理工具 |
|
|
99
|
+
| time | `@cloudcome/utils-vue/time` | 时间相关组合式函数 |
|
|
100
|
+
| types | `@cloudcome/utils-vue/types` | 类型定义 |
|
|
101
|
+
|
|
102
|
+
### @cloudcome/utils-react
|
|
103
|
+
|
|
104
|
+
React 工具库。
|
|
105
|
+
|
|
106
|
+
### @cloudcome/utils-uni
|
|
107
|
+
|
|
108
|
+
UniApp 工具库,依赖 `@cloudcome/utils-core`、`@cloudcome/utils-vue`:
|
|
109
|
+
|
|
110
|
+
| 子模块 | 导入路径 | 功能 |
|
|
111
|
+
| --- | --- | --- |
|
|
112
|
+
| app | `@cloudcome/utils-uni/app` | App 相关工具 |
|
|
113
|
+
| client | `@cloudcome/utils-uni/client` | 客户端工具 |
|
|
114
|
+
| cloud | `@cloudcome/utils-uni/cloud` | 云函数工具(调用、错误处理、uni-id 等) |
|
|
115
|
+
| database | `@cloudcome/utils-uni/database` | 数据库操作(CRUD、事务、分页、upsert 等) |
|
|
116
|
+
| page | `@cloudcome/utils-uni/page` | 页面相关工具 |
|
|
117
|
+
|
|
118
|
+
## 开发
|
|
119
|
+
|
|
120
|
+
详见 [DEVELOPMENT.md](./DEVELOPMENT.md)。
|
|
17
121
|
|
|
122
|
+
## 许可
|
|
18
123
|
|
|
124
|
+
[MIT](LICENSE)
|
package/dist/core.cjs
CHANGED
|
@@ -329,14 +329,14 @@ const rules = [
|
|
|
329
329
|
/h{2}/g,
|
|
330
330
|
(date) => {
|
|
331
331
|
const h = date.getHours();
|
|
332
|
-
return _pad(h > 12 ? h - 12 : h);
|
|
332
|
+
return _pad(h === 0 ? 12 : h > 12 ? h - 12 : h);
|
|
333
333
|
}
|
|
334
334
|
],
|
|
335
335
|
[
|
|
336
336
|
/h{1}/g,
|
|
337
337
|
(date) => {
|
|
338
338
|
const h = date.getHours();
|
|
339
|
-
return h > 12 ? h - 12 : h;
|
|
339
|
+
return h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
340
340
|
}
|
|
341
341
|
],
|
|
342
342
|
[/m{2}/g, (date) => _pad(date.getMinutes())],
|
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 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":"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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 === 0 ? 12 : h > 12 ? h - 12 : h);\n },\n ],\n [\n /h{1}/g,\n (date) => {\n const h = date.getHours();\n return h === 0 ? 12 : 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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"}
|
package/dist/core.mjs
CHANGED
|
@@ -328,14 +328,14 @@ const rules = [
|
|
|
328
328
|
/h{2}/g,
|
|
329
329
|
(date) => {
|
|
330
330
|
const h = date.getHours();
|
|
331
|
-
return _pad(h > 12 ? h - 12 : h);
|
|
331
|
+
return _pad(h === 0 ? 12 : h > 12 ? h - 12 : h);
|
|
332
332
|
}
|
|
333
333
|
],
|
|
334
334
|
[
|
|
335
335
|
/h{1}/g,
|
|
336
336
|
(date) => {
|
|
337
337
|
const h = date.getHours();
|
|
338
|
-
return h > 12 ? h - 12 : h;
|
|
338
|
+
return h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
339
339
|
}
|
|
340
340
|
],
|
|
341
341
|
[/m{2}/g, (date) => _pad(date.getMinutes())],
|
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 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;"}
|
|
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 === 0 ? 12 : h > 12 ? h - 12 : h);\n },\n ],\n [\n /h{1}/g,\n (date) => {\n const h = date.getHours();\n return h === 0 ? 12 : 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":"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"}
|
package/dist/function.cjs
CHANGED
|
@@ -36,16 +36,19 @@ function fnThrottle(fn, wait) {
|
|
|
36
36
|
const throttled = function(...args) {
|
|
37
37
|
if (canceled) return;
|
|
38
38
|
const now = Date.now();
|
|
39
|
+
let executed = false;
|
|
39
40
|
if (options.leading && lastTime === 0) {
|
|
40
41
|
lastTime = now;
|
|
41
42
|
fn.apply(this, args);
|
|
43
|
+
executed = true;
|
|
42
44
|
} else if (lastTime > 0 && now - lastTime >= waitFinal) {
|
|
43
45
|
lastTime = now;
|
|
44
46
|
fn.apply(this, args);
|
|
47
|
+
executed = true;
|
|
45
48
|
} else if (lastTime === 0) {
|
|
46
49
|
lastTime = now;
|
|
47
50
|
}
|
|
48
|
-
if (options.trailing) {
|
|
51
|
+
if (options.trailing && !executed) {
|
|
49
52
|
clearTimeout(timer);
|
|
50
53
|
timer = setTimeout(() => {
|
|
51
54
|
fn.apply(this, args);
|
package/dist/function.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"function.cjs","sources":["../src/function.ts"],"sourcesContent":["import { isNumber } from './type';\nimport type { AnyFunction } from './types';\n\n/**\n * 一个空操作函数,不执行任何操作。\n *\n * @example\n * ```typescript\n * fnNoop(); // 不执行任何操作\n * ```\n */\nexport function fnNoop() {\n //\n}\n\n/**\n * 防抖函数的配置选项。\n */\nexport type DebounceOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n /**\n * 是否在等待开始时立即执行一次\n * @default false\n */\n leading?: boolean;\n};\n\n/**\n * 创建一个防抖函数,该函数会在指定的等待时间后执行,如果在等待时间内再次调用,则重新计时。\n *\n * @param fn - 需要防抖的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait` 和 `leading` 选项的对象。\n * @returns 返回一个防抖函数,该函数具有 `cancel` 方法,用于取消防抖操作。\n *\n * @example\n * ```typescript\n * const debouncedFn = fnDebounce(() => {\n * console.log('Debounced!');\n * }, 100);\n *\n * debouncedFn(); // 不会立即执行\n * debouncedFn(); // 重新计时\n * debouncedFn.cancel(); // 取消防抖操作\n * ```\n */\nexport function fnDebounce<F extends AnyFunction>(fn: F, wait: number | DebounceOptions) {\n const options: DebounceOptions = isNumber(wait) ? { wait } : wait;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let timer: any;\n let leading = false;\n\n const debounced = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n // 第一次执行\n if (options.leading && !leading) {\n leading = true;\n fn.apply(this, args);\n return;\n }\n\n // 最后一次执行\n clearTimeout(timer);\n timer = setTimeout(() => {\n if (canceled) return;\n\n fn.apply(this, args);\n }, options.wait);\n };\n\n debounced.cancel = () => {\n clearTimeout(timer);\n canceled = true;\n };\n\n return debounced;\n}\n\nexport type ThrottleOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n\n /**\n * 是否在第一次调用时立即执行\n * @default false\n */\n leading?: boolean;\n\n /**\n * 是否在调用结束后等待一段时间再执行\n * @default false\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个节流函数,该函数会在指定的等待时间内最多执行一次,如果在等待时间内再次调用,则忽略后续调用。\n *\n * @param fn - 需要节流的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait`、`leading` 和 `trailing` 选项的对象。\n * @returns 返回一个节流函数,该函数具有 `cancel` 方法,用于取消节流操作。\n *\n * @example\n * ```typescript\n * const throttledFn = fnThrottle(() => {\n * console.log('Throttled!');\n * }, 100);\n *\n * throttledFn(); // 立即执行\n * throttledFn(); // 忽略\n * throttledFn.cancel(); // 取消节流操作\n * ```\n */\nexport function fnThrottle<F extends AnyFunction>(fn: F, wait: number | ThrottleOptions) {\n const options = isNumber(wait) ? { wait } : wait;\n const waitFinal = options.wait;\n let lastTime = 0;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let timer: any;\n\n const throttled = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n const now = Date.now();\n\n // 第一次执行\n if (options.leading && lastTime === 0) {\n lastTime = now;\n fn.apply(this, args);\n }\n\n // 中间控频执行\n else if (lastTime > 0 && now - lastTime >= waitFinal) {\n lastTime = now;\n fn.apply(this, args);\n }\n\n // 首次计时\n else if (lastTime === 0) {\n lastTime = now;\n }\n\n //
|
|
1
|
+
{"version":3,"file":"function.cjs","sources":["../src/function.ts"],"sourcesContent":["import { isNumber } from './type';\nimport type { AnyFunction } from './types';\n\n/**\n * 一个空操作函数,不执行任何操作。\n *\n * @example\n * ```typescript\n * fnNoop(); // 不执行任何操作\n * ```\n */\nexport function fnNoop() {\n //\n}\n\n/**\n * 防抖函数的配置选项。\n */\nexport type DebounceOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n /**\n * 是否在等待开始时立即执行一次\n * @default false\n */\n leading?: boolean;\n};\n\n/**\n * 创建一个防抖函数,该函数会在指定的等待时间后执行,如果在等待时间内再次调用,则重新计时。\n *\n * @param fn - 需要防抖的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait` 和 `leading` 选项的对象。\n * @returns 返回一个防抖函数,该函数具有 `cancel` 方法,用于取消防抖操作。\n *\n * @example\n * ```typescript\n * const debouncedFn = fnDebounce(() => {\n * console.log('Debounced!');\n * }, 100);\n *\n * debouncedFn(); // 不会立即执行\n * debouncedFn(); // 重新计时\n * debouncedFn.cancel(); // 取消防抖操作\n * ```\n */\nexport function fnDebounce<F extends AnyFunction>(fn: F, wait: number | DebounceOptions) {\n const options: DebounceOptions = isNumber(wait) ? { wait } : wait;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let timer: any;\n let leading = false;\n\n const debounced = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n // 第一次执行\n if (options.leading && !leading) {\n leading = true;\n fn.apply(this, args);\n return;\n }\n\n // 最后一次执行\n clearTimeout(timer);\n timer = setTimeout(() => {\n if (canceled) return;\n\n fn.apply(this, args);\n }, options.wait);\n };\n\n debounced.cancel = () => {\n clearTimeout(timer);\n canceled = true;\n };\n\n return debounced;\n}\n\nexport type ThrottleOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n\n /**\n * 是否在第一次调用时立即执行\n * @default false\n */\n leading?: boolean;\n\n /**\n * 是否在调用结束后等待一段时间再执行\n * @default false\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个节流函数,该函数会在指定的等待时间内最多执行一次,如果在等待时间内再次调用,则忽略后续调用。\n *\n * @param fn - 需要节流的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait`、`leading` 和 `trailing` 选项的对象。\n * @returns 返回一个节流函数,该函数具有 `cancel` 方法,用于取消节流操作。\n *\n * @example\n * ```typescript\n * const throttledFn = fnThrottle(() => {\n * console.log('Throttled!');\n * }, 100);\n *\n * throttledFn(); // 立即执行\n * throttledFn(); // 忽略\n * throttledFn.cancel(); // 取消节流操作\n * ```\n */\nexport function fnThrottle<F extends AnyFunction>(fn: F, wait: number | ThrottleOptions) {\n const options = isNumber(wait) ? { wait } : wait;\n const waitFinal = options.wait;\n let lastTime = 0;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let timer: any;\n\n const throttled = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n const now = Date.now();\n let executed = false;\n\n // 第一次执行\n if (options.leading && lastTime === 0) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 中间控频执行\n else if (lastTime > 0 && now - lastTime >= waitFinal) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 首次计时\n else if (lastTime === 0) {\n lastTime = now;\n }\n\n // 最后一次执行,仅在本次未执行时才设置 trailing\n if (options.trailing && !executed) {\n clearTimeout(timer);\n timer = setTimeout(() => {\n fn.apply(this, args);\n }, waitFinal);\n }\n };\n\n throttled.cancel = () => {\n canceled = true;\n clearTimeout(timer);\n };\n\n return throttled;\n}\n\n/**\n * 创建一个只执行一次的函数,无论调用多少次,实际执行的函数体也只会执行一次。\n *\n * @param fn - 需要只执行一次的函数。\n * @returns 返回一个只执行一次的函数,该函数在第一次调用后会缓存结果并返回缓存的结果。\n *\n * @example\n * ```typescript\n * const onceFn = fnOnce(() => {\n * console.log('This will be logged only once.');\n * return 42;\n * });\n *\n * console.log(onceFn()); // 输出: This will be logged only once. 42\n * console.log(onceFn()); // 输出: 42\n * ```\n */\nexport function fnOnce<F extends AnyFunction>(fn: F) {\n let called = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let result: any;\n\n return function (this: unknown, ...args: Parameters<F>) {\n if (!called) {\n called = true;\n result = fn.apply(this, args);\n }\n\n return result;\n };\n}\n"],"names":["isNumber"],"mappings":";;;AAWO,SAAS,SAAS;AAEzB;AAmCgB,SAAA,WAAkC,IAAO,MAAgC;AACvF,QAAM,UAA2BA,KAAAA,SAAS,IAAI,IAAI,EAAE,KAAS,IAAA;AAC7D,MAAI,WAAW;AAEX,MAAA;AACJ,MAAI,UAAU;AAER,QAAA,YAAY,YAA4B,MAAqB;AACjE,QAAI,SAAU;AAGV,QAAA,QAAQ,WAAW,CAAC,SAAS;AACrB,gBAAA;AACP,SAAA,MAAM,MAAM,IAAI;AACnB;AAAA,IAAA;AAIF,iBAAa,KAAK;AAClB,YAAQ,WAAW,MAAM;AACvB,UAAI,SAAU;AAEX,SAAA,MAAM,MAAM,IAAI;AAAA,IAAA,GAClB,QAAQ,IAAI;AAAA,EACjB;AAEA,YAAU,SAAS,MAAM;AACvB,iBAAa,KAAK;AACP,eAAA;AAAA,EACb;AAEO,SAAA;AACT;AAuCgB,SAAA,WAAkC,IAAO,MAAgC;AACvF,QAAM,UAAUA,KAAAA,SAAS,IAAI,IAAI,EAAE,KAAS,IAAA;AAC5C,QAAM,YAAY,QAAQ;AAC1B,MAAI,WAAW;AACf,MAAI,WAAW;AAEX,MAAA;AAEE,QAAA,YAAY,YAA4B,MAAqB;AACjE,QAAI,SAAU;AAER,UAAA,MAAM,KAAK,IAAI;AACrB,QAAI,WAAW;AAGX,QAAA,QAAQ,WAAW,aAAa,GAAG;AAC1B,iBAAA;AACR,SAAA,MAAM,MAAM,IAAI;AACR,iBAAA;AAAA,IAIJ,WAAA,WAAW,KAAK,MAAM,YAAY,WAAW;AACzC,iBAAA;AACR,SAAA,MAAM,MAAM,IAAI;AACR,iBAAA;AAAA,IAAA,WAIJ,aAAa,GAAG;AACZ,iBAAA;AAAA,IAAA;AAIT,QAAA,QAAQ,YAAY,CAAC,UAAU;AACjC,mBAAa,KAAK;AAClB,cAAQ,WAAW,MAAM;AACpB,WAAA,MAAM,MAAM,IAAI;AAAA,SAClB,SAAS;AAAA,IAAA;AAAA,EAEhB;AAEA,YAAU,SAAS,MAAM;AACZ,eAAA;AACX,iBAAa,KAAK;AAAA,EACpB;AAEO,SAAA;AACT;AAmBO,SAAS,OAA8B,IAAO;AACnD,MAAI,SAAS;AAET,MAAA;AAEJ,SAAO,YAA4B,MAAqB;AACtD,QAAI,CAAC,QAAQ;AACF,eAAA;AACA,eAAA,GAAG,MAAM,MAAM,IAAI;AAAA,IAAA;AAGvB,WAAA;AAAA,EACT;AACF;;;;;"}
|
package/dist/function.mjs
CHANGED
|
@@ -34,16 +34,19 @@ function fnThrottle(fn, wait) {
|
|
|
34
34
|
const throttled = function(...args) {
|
|
35
35
|
if (canceled) return;
|
|
36
36
|
const now = Date.now();
|
|
37
|
+
let executed = false;
|
|
37
38
|
if (options.leading && lastTime === 0) {
|
|
38
39
|
lastTime = now;
|
|
39
40
|
fn.apply(this, args);
|
|
41
|
+
executed = true;
|
|
40
42
|
} else if (lastTime > 0 && now - lastTime >= waitFinal) {
|
|
41
43
|
lastTime = now;
|
|
42
44
|
fn.apply(this, args);
|
|
45
|
+
executed = true;
|
|
43
46
|
} else if (lastTime === 0) {
|
|
44
47
|
lastTime = now;
|
|
45
48
|
}
|
|
46
|
-
if (options.trailing) {
|
|
49
|
+
if (options.trailing && !executed) {
|
|
47
50
|
clearTimeout(timer);
|
|
48
51
|
timer = setTimeout(() => {
|
|
49
52
|
fn.apply(this, args);
|
package/dist/function.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"function.mjs","sources":["../src/function.ts"],"sourcesContent":["import { isNumber } from './type';\nimport type { AnyFunction } from './types';\n\n/**\n * 一个空操作函数,不执行任何操作。\n *\n * @example\n * ```typescript\n * fnNoop(); // 不执行任何操作\n * ```\n */\nexport function fnNoop() {\n //\n}\n\n/**\n * 防抖函数的配置选项。\n */\nexport type DebounceOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n /**\n * 是否在等待开始时立即执行一次\n * @default false\n */\n leading?: boolean;\n};\n\n/**\n * 创建一个防抖函数,该函数会在指定的等待时间后执行,如果在等待时间内再次调用,则重新计时。\n *\n * @param fn - 需要防抖的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait` 和 `leading` 选项的对象。\n * @returns 返回一个防抖函数,该函数具有 `cancel` 方法,用于取消防抖操作。\n *\n * @example\n * ```typescript\n * const debouncedFn = fnDebounce(() => {\n * console.log('Debounced!');\n * }, 100);\n *\n * debouncedFn(); // 不会立即执行\n * debouncedFn(); // 重新计时\n * debouncedFn.cancel(); // 取消防抖操作\n * ```\n */\nexport function fnDebounce<F extends AnyFunction>(fn: F, wait: number | DebounceOptions) {\n const options: DebounceOptions = isNumber(wait) ? { wait } : wait;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let timer: any;\n let leading = false;\n\n const debounced = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n // 第一次执行\n if (options.leading && !leading) {\n leading = true;\n fn.apply(this, args);\n return;\n }\n\n // 最后一次执行\n clearTimeout(timer);\n timer = setTimeout(() => {\n if (canceled) return;\n\n fn.apply(this, args);\n }, options.wait);\n };\n\n debounced.cancel = () => {\n clearTimeout(timer);\n canceled = true;\n };\n\n return debounced;\n}\n\nexport type ThrottleOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n\n /**\n * 是否在第一次调用时立即执行\n * @default false\n */\n leading?: boolean;\n\n /**\n * 是否在调用结束后等待一段时间再执行\n * @default false\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个节流函数,该函数会在指定的等待时间内最多执行一次,如果在等待时间内再次调用,则忽略后续调用。\n *\n * @param fn - 需要节流的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait`、`leading` 和 `trailing` 选项的对象。\n * @returns 返回一个节流函数,该函数具有 `cancel` 方法,用于取消节流操作。\n *\n * @example\n * ```typescript\n * const throttledFn = fnThrottle(() => {\n * console.log('Throttled!');\n * }, 100);\n *\n * throttledFn(); // 立即执行\n * throttledFn(); // 忽略\n * throttledFn.cancel(); // 取消节流操作\n * ```\n */\nexport function fnThrottle<F extends AnyFunction>(fn: F, wait: number | ThrottleOptions) {\n const options = isNumber(wait) ? { wait } : wait;\n const waitFinal = options.wait;\n let lastTime = 0;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let timer: any;\n\n const throttled = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n const now = Date.now();\n\n // 第一次执行\n if (options.leading && lastTime === 0) {\n lastTime = now;\n fn.apply(this, args);\n }\n\n // 中间控频执行\n else if (lastTime > 0 && now - lastTime >= waitFinal) {\n lastTime = now;\n fn.apply(this, args);\n }\n\n // 首次计时\n else if (lastTime === 0) {\n lastTime = now;\n }\n\n //
|
|
1
|
+
{"version":3,"file":"function.mjs","sources":["../src/function.ts"],"sourcesContent":["import { isNumber } from './type';\nimport type { AnyFunction } from './types';\n\n/**\n * 一个空操作函数,不执行任何操作。\n *\n * @example\n * ```typescript\n * fnNoop(); // 不执行任何操作\n * ```\n */\nexport function fnNoop() {\n //\n}\n\n/**\n * 防抖函数的配置选项。\n */\nexport type DebounceOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n /**\n * 是否在等待开始时立即执行一次\n * @default false\n */\n leading?: boolean;\n};\n\n/**\n * 创建一个防抖函数,该函数会在指定的等待时间后执行,如果在等待时间内再次调用,则重新计时。\n *\n * @param fn - 需要防抖的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait` 和 `leading` 选项的对象。\n * @returns 返回一个防抖函数,该函数具有 `cancel` 方法,用于取消防抖操作。\n *\n * @example\n * ```typescript\n * const debouncedFn = fnDebounce(() => {\n * console.log('Debounced!');\n * }, 100);\n *\n * debouncedFn(); // 不会立即执行\n * debouncedFn(); // 重新计时\n * debouncedFn.cancel(); // 取消防抖操作\n * ```\n */\nexport function fnDebounce<F extends AnyFunction>(fn: F, wait: number | DebounceOptions) {\n const options: DebounceOptions = isNumber(wait) ? { wait } : wait;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let timer: any;\n let leading = false;\n\n const debounced = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n // 第一次执行\n if (options.leading && !leading) {\n leading = true;\n fn.apply(this, args);\n return;\n }\n\n // 最后一次执行\n clearTimeout(timer);\n timer = setTimeout(() => {\n if (canceled) return;\n\n fn.apply(this, args);\n }, options.wait);\n };\n\n debounced.cancel = () => {\n clearTimeout(timer);\n canceled = true;\n };\n\n return debounced;\n}\n\nexport type ThrottleOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n\n /**\n * 是否在第一次调用时立即执行\n * @default false\n */\n leading?: boolean;\n\n /**\n * 是否在调用结束后等待一段时间再执行\n * @default false\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个节流函数,该函数会在指定的等待时间内最多执行一次,如果在等待时间内再次调用,则忽略后续调用。\n *\n * @param fn - 需要节流的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait`、`leading` 和 `trailing` 选项的对象。\n * @returns 返回一个节流函数,该函数具有 `cancel` 方法,用于取消节流操作。\n *\n * @example\n * ```typescript\n * const throttledFn = fnThrottle(() => {\n * console.log('Throttled!');\n * }, 100);\n *\n * throttledFn(); // 立即执行\n * throttledFn(); // 忽略\n * throttledFn.cancel(); // 取消节流操作\n * ```\n */\nexport function fnThrottle<F extends AnyFunction>(fn: F, wait: number | ThrottleOptions) {\n const options = isNumber(wait) ? { wait } : wait;\n const waitFinal = options.wait;\n let lastTime = 0;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let timer: any;\n\n const throttled = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n const now = Date.now();\n let executed = false;\n\n // 第一次执行\n if (options.leading && lastTime === 0) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 中间控频执行\n else if (lastTime > 0 && now - lastTime >= waitFinal) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 首次计时\n else if (lastTime === 0) {\n lastTime = now;\n }\n\n // 最后一次执行,仅在本次未执行时才设置 trailing\n if (options.trailing && !executed) {\n clearTimeout(timer);\n timer = setTimeout(() => {\n fn.apply(this, args);\n }, waitFinal);\n }\n };\n\n throttled.cancel = () => {\n canceled = true;\n clearTimeout(timer);\n };\n\n return throttled;\n}\n\n/**\n * 创建一个只执行一次的函数,无论调用多少次,实际执行的函数体也只会执行一次。\n *\n * @param fn - 需要只执行一次的函数。\n * @returns 返回一个只执行一次的函数,该函数在第一次调用后会缓存结果并返回缓存的结果。\n *\n * @example\n * ```typescript\n * const onceFn = fnOnce(() => {\n * console.log('This will be logged only once.');\n * return 42;\n * });\n *\n * console.log(onceFn()); // 输出: This will be logged only once. 42\n * console.log(onceFn()); // 输出: 42\n * ```\n */\nexport function fnOnce<F extends AnyFunction>(fn: F) {\n let called = false;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let result: any;\n\n return function (this: unknown, ...args: Parameters<F>) {\n if (!called) {\n called = true;\n result = fn.apply(this, args);\n }\n\n return result;\n };\n}\n"],"names":[],"mappings":";AAWO,SAAS,SAAS;AAEzB;AAmCgB,SAAA,WAAkC,IAAO,MAAgC;AACvF,QAAM,UAA2B,SAAS,IAAI,IAAI,EAAE,KAAS,IAAA;AAC7D,MAAI,WAAW;AAEX,MAAA;AACJ,MAAI,UAAU;AAER,QAAA,YAAY,YAA4B,MAAqB;AACjE,QAAI,SAAU;AAGV,QAAA,QAAQ,WAAW,CAAC,SAAS;AACrB,gBAAA;AACP,SAAA,MAAM,MAAM,IAAI;AACnB;AAAA,IAAA;AAIF,iBAAa,KAAK;AAClB,YAAQ,WAAW,MAAM;AACvB,UAAI,SAAU;AAEX,SAAA,MAAM,MAAM,IAAI;AAAA,IAAA,GAClB,QAAQ,IAAI;AAAA,EACjB;AAEA,YAAU,SAAS,MAAM;AACvB,iBAAa,KAAK;AACP,eAAA;AAAA,EACb;AAEO,SAAA;AACT;AAuCgB,SAAA,WAAkC,IAAO,MAAgC;AACvF,QAAM,UAAU,SAAS,IAAI,IAAI,EAAE,KAAS,IAAA;AAC5C,QAAM,YAAY,QAAQ;AAC1B,MAAI,WAAW;AACf,MAAI,WAAW;AAEX,MAAA;AAEE,QAAA,YAAY,YAA4B,MAAqB;AACjE,QAAI,SAAU;AAER,UAAA,MAAM,KAAK,IAAI;AACrB,QAAI,WAAW;AAGX,QAAA,QAAQ,WAAW,aAAa,GAAG;AAC1B,iBAAA;AACR,SAAA,MAAM,MAAM,IAAI;AACR,iBAAA;AAAA,IAIJ,WAAA,WAAW,KAAK,MAAM,YAAY,WAAW;AACzC,iBAAA;AACR,SAAA,MAAM,MAAM,IAAI;AACR,iBAAA;AAAA,IAAA,WAIJ,aAAa,GAAG;AACZ,iBAAA;AAAA,IAAA;AAIT,QAAA,QAAQ,YAAY,CAAC,UAAU;AACjC,mBAAa,KAAK;AAClB,cAAQ,WAAW,MAAM;AACpB,WAAA,MAAM,MAAM,IAAI;AAAA,SAClB,SAAS;AAAA,IAAA;AAAA,EAEhB;AAEA,YAAU,SAAS,MAAM;AACZ,eAAA;AACX,iBAAa,KAAK;AAAA,EACpB;AAEO,SAAA;AACT;AAmBO,SAAS,OAA8B,IAAO;AACnD,MAAI,SAAS;AAET,MAAA;AAEJ,SAAO,YAA4B,MAAqB;AACtD,QAAI,CAAC,QAAQ;AACF,eAAA;AACA,eAAA,GAAG,MAAM,MAAM,IAAI;AAAA,IAAA;AAGvB,WAAA;AAAA,EACT;AACF;"}
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED