@cloudcome/utils-core 0.0.0 → 1.1.1

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.
Files changed (107) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/LICENSE +21 -0
  3. package/package.json +277 -6
  4. package/src/array.ts +312 -0
  5. package/src/async.ts +379 -0
  6. package/src/base64.ts +20 -0
  7. package/src/cache.ts +146 -0
  8. package/src/color/contrast.ts +20 -0
  9. package/src/color/distance.ts +28 -0
  10. package/src/color/helpers.ts +23 -0
  11. package/src/color/hex-hsl.ts +11 -0
  12. package/src/color/hex-hsv.ts +28 -0
  13. package/src/color/hex-hwb.ts +31 -0
  14. package/src/color/hex-rgb.ts +39 -0
  15. package/src/color/hsl-lighten.ts +15 -0
  16. package/src/color/hsv-brighten.ts +17 -0
  17. package/src/color/luminance.ts +17 -0
  18. package/src/color/mix.ts +26 -0
  19. package/src/color/rgb-hsl.ts +53 -0
  20. package/src/color/rgb-hsv.ts +52 -0
  21. package/src/color/rgb-hwb.ts +56 -0
  22. package/src/color/rgb-lab.ts +33 -0
  23. package/src/color/rgb-whiter.ts +22 -0
  24. package/src/color/rgb-xyz.ts +62 -0
  25. package/src/color/types.ts +65 -0
  26. package/src/color/xyz-lab.ts +54 -0
  27. package/src/color.ts +19 -0
  28. package/src/crypto/md5.mjs +357 -0
  29. package/src/crypto/sha1.mjs +300 -0
  30. package/src/crypto/sha256.mjs +310 -0
  31. package/src/crypto/sha512.mjs +459 -0
  32. package/src/crypto.ts +60 -0
  33. package/src/date/const.ts +6 -0
  34. package/src/date/core.ts +162 -0
  35. package/src/date/days.ts +51 -0
  36. package/src/date/is.ts +186 -0
  37. package/src/date/relative.ts +92 -0
  38. package/src/date/start-end.ts +246 -0
  39. package/src/date/timezone.ts +220 -0
  40. package/src/date/weeks.ts +100 -0
  41. package/src/date.ts +8 -0
  42. package/src/dict.ts +1 -0
  43. package/src/dts/global.d.ts +27 -0
  44. package/src/easing.ts +166 -0
  45. package/src/emitter.ts +117 -0
  46. package/src/enum.ts +171 -0
  47. package/src/env.ts +62 -0
  48. package/src/error.ts +31 -0
  49. package/src/exception.ts +68 -0
  50. package/src/fn.ts +197 -0
  51. package/src/index.ts +1 -0
  52. package/src/number.ts +236 -0
  53. package/src/object/each.ts +56 -0
  54. package/src/object/get-set.ts +273 -0
  55. package/src/object/is.ts +128 -0
  56. package/src/object/merge.ts +180 -0
  57. package/src/object/process.ts +80 -0
  58. package/src/object.ts +5 -0
  59. package/src/path.ts +188 -0
  60. package/src/promise.ts +111 -0
  61. package/src/qs.ts +119 -0
  62. package/src/regexp.ts +156 -0
  63. package/src/string.ts +146 -0
  64. package/src/time/from.ts +57 -0
  65. package/src/time/to.ts +106 -0
  66. package/src/time.ts +2 -0
  67. package/src/timer.ts +226 -0
  68. package/src/tree.ts +394 -0
  69. package/src/type.ts +197 -0
  70. package/src/types.ts +78 -0
  71. package/src/unique.ts +77 -0
  72. package/src/url.ts +93 -0
  73. package/src/version.ts +71 -0
  74. package/test/array.test.ts +332 -0
  75. package/test/async-real.test.ts +39 -0
  76. package/test/async.test.ts +375 -0
  77. package/test/base64.test.ts +32 -0
  78. package/test/cache.test.ts +83 -0
  79. package/test/color.test.ts +163 -0
  80. package/test/crypto.test.ts +34 -0
  81. package/test/date-tz.test.ts +206 -0
  82. package/test/date.test.ts +353 -0
  83. package/test/easing.test.ts +33 -0
  84. package/test/emitter.test.ts +71 -0
  85. package/test/enum.test.ts +113 -0
  86. package/test/env.test.ts +69 -0
  87. package/test/error.test.ts +58 -0
  88. package/test/exception.test.ts +43 -0
  89. package/test/fn.test.ts +263 -0
  90. package/test/helpers.ts +23 -0
  91. package/test/index.test.ts +6 -0
  92. package/test/number.test.ts +213 -0
  93. package/test/object.test.ts +309 -0
  94. package/test/path.test.ts +156 -0
  95. package/test/promise.test.ts +199 -0
  96. package/test/qs.test.ts +79 -0
  97. package/test/regexp.test.ts +97 -0
  98. package/test/string.test.ts +150 -0
  99. package/test/time.test.ts +214 -0
  100. package/test/timer.test.ts +114 -0
  101. package/test/tree.test.ts +348 -0
  102. package/test/type.test.ts +226 -0
  103. package/test/unique.test.ts +71 -0
  104. package/test/url.test.ts +136 -0
  105. package/test/version.test.ts +52 -0
  106. package/tsconfig.json +31 -0
  107. package/vite.config.mts +114 -0
@@ -0,0 +1,51 @@
1
+ import { DATE_DAY_MS } from './const';
2
+ import { type TDateValue, dateParse } from './core';
3
+ import { dateEndInMonth, dateEndInYear, dateStartInMonth, dateStartInYear } from './start-end';
4
+
5
+ /**
6
+ * 计算指定日期所在年或月的天数
7
+ * @param dateValue - 可以是数值、字符串或 Date 对象
8
+ * @param unit - 时间单位符号,可选值为 'Y'(年)、'M'(月),默认为 'M'
9
+ * @returns 返回指定日期所在年或月的天数
10
+ * @example
11
+ * ```typescript
12
+ * dateDays(new Date('2023-02-15')); // 28
13
+ * dateDays(new Date('2024-02-15')); // 29 (闰年)
14
+ * dateDays(new Date('2023-02-15'), 'Y'); // 365
15
+ * dateDays(new Date('2024-02-15'), 'Y'); // 366 (闰年)
16
+ * ```
17
+ */
18
+ function _dateDays(dateValue: TDateValue, unit: 'Y' | 'M') {
19
+ const d = dateParse(dateValue);
20
+ const ds = unit === 'M' ? dateStartInMonth(d) : dateStartInYear(d);
21
+ const de = unit === 'M' ? dateEndInMonth(d) : dateEndInYear(d);
22
+ return Math.ceil((de.getTime() - ds.getTime()) / DATE_DAY_MS);
23
+ }
24
+
25
+ /**
26
+ * 计算指定日期所在月份的天数
27
+ * @param dateValue - 可以是数值、字符串或 Date 对象
28
+ * @returns 返回指定日期所在月份的天数
29
+ * @example
30
+ * ```typescript
31
+ * dateDaysInMonth(new Date('2023-02-15')); // 28
32
+ * dateDaysInMonth(new Date('2024-02-15')); // 29 (闰年)
33
+ * ```
34
+ */
35
+ export function dateDaysInMonth(dateValue: TDateValue) {
36
+ return _dateDays(dateValue, 'M');
37
+ }
38
+
39
+ /**
40
+ * 计算指定日期所在年份的天数
41
+ * @param dateValue - 可以是数值、字符串或 Date 对象
42
+ * @returns 返回指定日期所在年份的天数
43
+ * @example
44
+ * ```typescript
45
+ * dateDaysInYear(new Date('2023-02-15')); // 365
46
+ * dateDaysInYear(new Date('2024-02-15')); // 366 (闰年)
47
+ * ```
48
+ */
49
+ export function dateDaysInYear(dateValue: TDateValue) {
50
+ return _dateDays(dateValue, 'Y');
51
+ }
package/src/date/is.ts ADDED
@@ -0,0 +1,186 @@
1
+ import { type TDateLike, type TDateValue, dateParse } from './core';
2
+
3
+ /**
4
+ * 判断给定的年份是否为闰年
5
+ * @param year - 需要判断的年份
6
+ * @returns 如果年份是闰年则返回 true,否则返回 false
7
+ * @example
8
+ * ```typescript
9
+ * isLeapYear(2020); // true
10
+ * isLeapYear(2021); // false
11
+ * isLeapYear(2000); // true
12
+ * isLeapYear(1900); // false
13
+ * ```
14
+ */
15
+ export function isLeapYear(year: number): boolean {
16
+ if (year % 4 !== 0) return false;
17
+ if (year % 100 !== 0) return true;
18
+ if (year % 400 !== 0) return false;
19
+ return true;
20
+ }
21
+
22
+ /**
23
+ * 日期比较精度枚举类型
24
+ * - Y = 年
25
+ * - M = 月
26
+ * - D = 天
27
+ * - h = 小时
28
+ * - m = 分钟
29
+ * - s = 秒
30
+ * - S = 毫秒
31
+ */
32
+ type _DateSameSymbol = 'Y' | 'M' | 'D' | 'h' | 'm' | 's' | 'S';
33
+
34
+ /**
35
+ * 比较两个日期在指定精度下是否相同
36
+ * @param date1 - 第一个日期,可以是数值、字符串或 Date 对象
37
+ * @param date2 - 第二个日期,可以是数值、字符串或 Date 对象
38
+ * @param sameSymbol - 比较精度,默认为 'D'(天,即年月日天都相同)
39
+ * @returns 如果两个日期在指定精度下相同则返回 true,否则返回 false
40
+ * @example
41
+ * ```typescript
42
+ * const date1 = new Date(2023, 5, 15, 12, 30, 45, 500);
43
+ * const date2 = new Date(2023, 5, 15, 13, 30, 45, 500);
44
+ *
45
+ * // 比较年份
46
+ * isSameDate(date1, date2, 'Y'); // true
47
+ *
48
+ * // 比较月份(年份也要相同)
49
+ * isSameDate(date1, date2, 'M'); // true
50
+ *
51
+ * // 比较日期(默认,年份、月份也要相同)
52
+ * isSameDate(date1, date2); // true
53
+ *
54
+ * // 比较小时(年、月、日也要相同)
55
+ * isSameDate(date1, date2, 'h'); // false
56
+ *
57
+ * // 比较分钟(年、月、日、小时也要相同)
58
+ * isSameDate(date1, date2, 'm'); // false
59
+ *
60
+ * // 比较秒(年、月、日、小时、分钟也要相同)
61
+ * isSameDate(date1, date2, 's'); // false
62
+ *
63
+ * // 比较毫秒(年、月、日、小时、分钟、秒数也要相同)
64
+ * isSameDate(date1, date2, 'S'); // false
65
+ * ```
66
+ */
67
+ function _isSameDateIn(date1: TDateValue, date2: TDateValue, sameSymbol: _DateSameSymbol = 'D') {
68
+ const defines = [
69
+ ['Y', (d: TDateLike) => d.getFullYear()],
70
+ ['M', (d: TDateLike) => d.getMonth()],
71
+ ['D', (d: TDateLike) => d.getDate()],
72
+ ['h', (d: TDateLike) => d.getHours()],
73
+ ['m', (d: TDateLike) => d.getMinutes()],
74
+ ['s', (d: TDateLike) => d.getSeconds()],
75
+ ['S', (d: TDateLike) => d.getMilliseconds()],
76
+ ] as const;
77
+
78
+ const d1 = dateParse(date1);
79
+ const d2 = dateParse(date2);
80
+
81
+ for (const [sym, fn] of defines) {
82
+ if (fn(d1) !== fn(d2)) {
83
+ return false;
84
+ }
85
+
86
+ if (sym === sameSymbol) break;
87
+ }
88
+
89
+ return true;
90
+ }
91
+
92
+ /**
93
+ * 比较两个日期的年份是否相同
94
+ * @param date1 - 第一个日期,可以是数值、字符串或 Date 对象
95
+ * @param date2 - 第二个日期,可以是数值、字符串或 Date 对象
96
+ * @returns 如果两个日期的年份相同则返回 true,否则返回 false
97
+ * @example
98
+ * ```typescript
99
+ * const date1 = new Date(2023, 5, 15);
100
+ * const date2 = new Date(2023, 6, 20);
101
+ * isSameDateInYear(date1, date2); // true
102
+ * ```
103
+ */
104
+ export function isSameDateInYear(date1: TDateValue, date2: TDateValue) {
105
+ return _isSameDateIn(date1, date2, 'Y');
106
+ }
107
+
108
+ /**
109
+ * 比较两个日期的年份和月份是否相同
110
+ * @param date1 - 第一个日期,可以是数值、字符串或 Date 对象
111
+ * @param date2 - 第二个日期,可以是数值、字符串或 Date 对象
112
+ * @returns 如果两个日期的年份和月份相同则返回 true,否则返回 false
113
+ * @example
114
+ * ```typescript
115
+ * const date1 = new Date(2023, 5, 15);
116
+ * const date2 = new Date(2023, 5, 20);
117
+ * isSameDateInMonth(date1, date2); // true
118
+ * ```
119
+ */
120
+ export function isSameDateInMonth(date1: TDateValue, date2: TDateValue) {
121
+ return _isSameDateIn(date1, date2, 'M');
122
+ }
123
+
124
+ /**
125
+ * 比较两个日期的年份、月份和天数是否相同
126
+ * @param date1 - 第一个日期,可以是数值、字符串或 Date 对象
127
+ * @param date2 - 第二个日期,可以是数值、字符串或 Date 对象
128
+ * @returns 如果两个日期的年份、月份和天数相同则返回 true,否则返回 false
129
+ * @example
130
+ * ```typescript
131
+ * const date1 = new Date(2023, 5, 15);
132
+ * const date2 = new Date(2023, 5, 15);
133
+ * isSameDateInDay(date1, date2); // true
134
+ * ```
135
+ */
136
+ export function isSameDateInDay(date1: TDateValue, date2: TDateValue) {
137
+ return _isSameDateIn(date1, date2, 'D');
138
+ }
139
+
140
+ /**
141
+ * 比较两个日期的年份、月份、天数和小时是否相同
142
+ * @param date1 - 第一个日期,可以是数值、字符串或 Date 对象
143
+ * @param date2 - 第二个日期,可以是数值、字符串或 Date 对象
144
+ * @returns 如果两个日期的年份、月份、天数和小时相同则返回 true,否则返回 false
145
+ * @example
146
+ * ```typescript
147
+ * const date1 = new Date(2023, 5, 15, 12);
148
+ * const date2 = new Date(2023, 5, 15, 12);
149
+ * isSameDateInHour(date1, date2); // true
150
+ * ```
151
+ */
152
+ export function isSameDateInHour(date1: TDateValue, date2: TDateValue) {
153
+ return _isSameDateIn(date1, date2, 'h');
154
+ }
155
+
156
+ /**
157
+ * 比较两个日期的年份、月份、天数、小时和分钟是否相同
158
+ * @param date1 - 第一个日期,可以是数值、字符串或 Date 对象
159
+ * @param date2 - 第二个日期,可以是数值、字符串或 Date 对象
160
+ * @returns 如果两个日期的年份、月份、天数、小时和分钟相同则返回 true,否则返回 false
161
+ * @example
162
+ * ```typescript
163
+ * const date1 = new Date(2023, 5, 15, 12, 30);
164
+ * const date2 = new Date(2023, 5, 15, 12, 30);
165
+ * isSameDateInMinute(date1, date2); // true
166
+ * ```
167
+ */
168
+ export function isSameDateInMinute(date1: TDateValue, date2: TDateValue) {
169
+ return _isSameDateIn(date1, date2, 'm');
170
+ }
171
+
172
+ /**
173
+ * 比较两个日期的年份、月份、天数、小时、分钟和秒数是否相同
174
+ * @param date1 - 第一个日期,可以是数值、字符串或 Date 对象
175
+ * @param date2 - 第二个日期,可以是数值、字符串或 Date 对象
176
+ * @returns 如果两个日期的年份、月份、天数、小时、分钟和秒数相同则返回 true,否则返回 false
177
+ * @example
178
+ * ```typescript
179
+ * const date1 = new Date(2023, 5, 15, 12, 30, 45);
180
+ * const date2 = new Date(2023, 5, 15, 12, 30, 45);
181
+ * isSameDateInSecond(date1, date2); // true
182
+ * ```
183
+ */
184
+ export function isSameDateInSecond(date1: TDateValue, date2: TDateValue) {
185
+ return _isSameDateIn(date1, date2, 's');
186
+ }
@@ -0,0 +1,92 @@
1
+ import { stringFormat } from '@/string';
2
+ import { isArray } from '@/type';
3
+ import { type TDateValue, dateFormat, dateParse } from './core';
4
+
5
+ export type TDateRelativeTemplate = [
6
+ number /*单位时间差,为 0 表示不计算单位差值,单位秒*/,
7
+ number /*最大时间差,单位:秒*/,
8
+ string /*过去模板字符串,%d 表述单位差值*/,
9
+ string? /*将来模板字符串,%d 表述单位差值,可选*/,
10
+ ];
11
+ export type TDateRelativeTemplates = TDateRelativeTemplate[];
12
+
13
+ const defaultDiffTemplates: TDateRelativeTemplates = [
14
+ [0, 10, '刚刚'],
15
+ [1, 60, '{n} 秒前', '{n} 秒后'],
16
+ [60, 60 * 60, '{n} 分钟前', '{n} 分钟后'],
17
+ [60 * 60, 60 * 60 * 24, '{n} 小时前', '{n} 小时后'],
18
+ [0, 60 * 60 * 24 * 2, '昨天', '明天'],
19
+ [0, 60 * 60 * 24 * 3, '前天', '后天'],
20
+ [60 * 60 * 24, 60 * 60 * 24 * 30, '{n} 天前', '{n} 天后'],
21
+ [0, Number.POSITIVE_INFINITY, 'YYYY年MM月DD日'],
22
+ ];
23
+
24
+ /**
25
+ * 相对时间
26
+ * @param {TDateValue} dateValue 比较的时间
27
+ * @param {TDateValue} [refDateValue] 相对的时间,默认为当前
28
+ * @param {TDateRelativeTemplates} [templates] 模板
29
+ * @returns {string} 格式化后的相对时间字符串
30
+ * @example
31
+ * ```typescript
32
+ * // 默认模板
33
+ * dateRelative(new Date('2023-01-01')); // '刚刚'
34
+ * dateRelative(new Date('2023-01-01'), new Date('2023-01-02')); // '昨天'
35
+ * dateRelative(new Date('2023-01-01'), new Date('2023-01-04')); // '3 天前'
36
+ * dateRelative(new Date('2023-01-01'), new Date('2023-02-01')); // '2023年01月01日'
37
+ * ```
38
+ * @example
39
+ * ```typescript
40
+ * // 自定义模板
41
+ * const templates: DateRelativeTemplates = [
42
+ * [0, 10, '刚刚'],
43
+ * [1, 60, '{n} 秒前', '{n} 秒后'],
44
+ * [60, 60 * 60, '{n} 分钟前', '{n} 分钟后'],
45
+ * [60 * 60, 60 * 60 * 24, '{n} 小时前', '{n} 小时后'],
46
+ * [0, 60 * 60 * 24 * 2, '昨天', '明天'],
47
+ * [0, 60 * 60 * 24 * 3, '前天', '后天'],
48
+ * [60 * 60 * 24, 60 * 60 * 24 * 30, '{n} 天前', '{n} 天后'],
49
+ * [0, Number.POSITIVE_INFINITY, 'YYYY年MM月DD日'],
50
+ * ];
51
+ * dateRelative(new Date('2023-01-01'), new Date('2023-01-02'), templates); // '昨天'
52
+ * dateRelative(new Date('2023-01-01'), new Date('2023-01-04'), templates); // '3 天前'
53
+ * dateRelative(new Date('2023-01-01'), new Date('2023-02-01'), templates); // '2023年01月01日'
54
+ * ```
55
+ */
56
+ export function dateRelative(
57
+ dateValue: TDateValue,
58
+ refDateValue: TDateValue,
59
+ templates: TDateRelativeTemplates,
60
+ ): string;
61
+ export function dateRelative(dateValue: TDateValue, refDateValue: TDateValue): string;
62
+ export function dateRelative(dateValue: TDateValue, templates: TDateRelativeTemplates): string;
63
+ export function dateRelative(dateValue: TDateValue): string;
64
+ export function dateRelative(
65
+ dateValue: TDateValue,
66
+ refDateValue?: TDateValue | TDateRelativeTemplates,
67
+ templates?: TDateRelativeTemplates,
68
+ ): string {
69
+ const now = Date.now();
70
+ const refDateValueFinal = isArray(refDateValue) ? now : refDateValue || now;
71
+ const templatesFinal = isArray(templates) ? templates : isArray(refDateValue) ? refDateValue : defaultDiffTemplates;
72
+ const d1 = dateParse(dateValue);
73
+ const d2 = dateParse(refDateValueFinal);
74
+ const diff = d1.getTime() - d2.getTime();
75
+ const isAgo = diff < 0;
76
+ const absDiff = Math.abs(diff);
77
+ let relative = '';
78
+
79
+ for (const [base, max, agoTemplate, featureTemplate] of templatesFinal) {
80
+ const unitFinal = base * 1000;
81
+ const maxFinal = max * 1000;
82
+
83
+ if (absDiff < maxFinal) {
84
+ const template = isAgo ? agoTemplate : featureTemplate || agoTemplate;
85
+ const length = unitFinal === 0 ? 0 : Math.max(Math.floor(absDiff / unitFinal), 1);
86
+ relative = unitFinal === 0 ? dateFormat(dateValue, template) : stringFormat(template, { n: length });
87
+ break;
88
+ }
89
+ }
90
+
91
+ return relative;
92
+ }
@@ -0,0 +1,246 @@
1
+ import { type TDateLike, type TDateValue, dateParse } from './core';
2
+
3
+ /**
4
+ * 时间单位符号枚举
5
+ * - 'Y': 年
6
+ * - 'M': 月
7
+ * - 'D': 天
8
+ * - 'W': 周
9
+ * - 'h': 小时
10
+ * - 'm': 分钟
11
+ * - 's': 秒
12
+ */
13
+ type _TDateOfSymbol = 'Y' | 'M' | 'D' | 'W' | 'h' | 'm' | 's';
14
+
15
+ /**
16
+ * 各时间单位起始时间映射表
17
+ * 包含将日期设置到单位起始时间的函数
18
+ */
19
+ const dateOfStartMap: [_TDateOfSymbol, (date: TDateLike) => unknown][] = [
20
+ ['s', (d) => d.setMilliseconds(0)],
21
+ ['m', (d) => d.setSeconds(0)],
22
+ ['h', (d) => d.setMinutes(0)],
23
+ ['D', (d) => d.setHours(0)],
24
+ ['W', (d) => d.setHours(0)],
25
+ ['M', (d) => d.setDate(1)],
26
+ ['Y', (d) => d.setMonth(0)],
27
+ ];
28
+
29
+ /**
30
+ * 返回指定时间单位的起始时间
31
+ * @param dateValue - 可以是数值、字符串或 Date 对象
32
+ * @param symbol - 时间单位符号,可选值为 'Y'(年)、'M'(月)、'D'(天)、'h'(小时)、'm'(分钟)、's'(秒),默认为 'D'
33
+ * @returns 返回指定时间单位的起始时间
34
+ * @example
35
+ * ```typescript
36
+ * const date = new Date(2023, 5, 15, 12, 30, 45, 500); // 2023-06-15 12:30:45.500
37
+ *
38
+ * // 返回秒级起始时间
39
+ * dateOfStart(date, 's'); // 2023-06-15 12:30:45.000
40
+ *
41
+ * // 返回分钟级起始时间
42
+ * dateOfStart(date, 'm'); // 2023-06-15 12:30:00.000
43
+ *
44
+ * // 返回小时级起始时间
45
+ * dateOfStart(date, 'h'); // 2023-06-15 12:00:00.000
46
+ *
47
+ * // 返回天级起始时间
48
+ * dateOfStart(date, 'D'); // 2023-06-15 00:00:00.000
49
+ *
50
+ * // 返回月级起始时间
51
+ * dateOfStart(date, 'M'); // 2023-06-01 00:00:00.000
52
+ *
53
+ * // 返回年级起始时间
54
+ * dateOfStart(date, 'Y'); // 2023-01-01 00:00:00.000
55
+ *
56
+ * // 默认返回天级起始时间
57
+ * dateOfStart(date); // 2023-06-15 00:00:00.000
58
+ * ```
59
+ */
60
+ function _dateStart(dateValue: TDateValue, symbol: _TDateOfSymbol = 'D') {
61
+ const date = dateParse(dateValue);
62
+
63
+ for (const [sym, fn] of dateOfStartMap) {
64
+ fn(date);
65
+ if (symbol === sym) break;
66
+ }
67
+
68
+ return date;
69
+ }
70
+
71
+ /**
72
+ * 返回秒级起始时间
73
+ * @param dateValue - 可以是数值、字符串或 Date 对象
74
+ * @returns 返回秒级起始时间,毫秒部分为 0
75
+ */
76
+ export function dateStartInSecond(dateValue: TDateValue) {
77
+ return _dateStart(dateValue, 's');
78
+ }
79
+
80
+ /**
81
+ * 返回分钟级起始时间
82
+ * @param dateValue - 可以是数值、字符串或 Date 对象
83
+ * @returns 返回分钟级起始时间,秒和毫秒部分为 0
84
+ */
85
+ export function dateStartInMinute(dateValue: TDateValue) {
86
+ return _dateStart(dateValue, 'm');
87
+ }
88
+
89
+ /**
90
+ * 返回小时级起始时间
91
+ * @param dateValue - 可以是数值、字符串或 Date 对象
92
+ * @returns 返回小时级起始时间,分钟、秒和毫秒部分为 0
93
+ */
94
+ export function dateStartInHour(dateValue: TDateValue) {
95
+ return _dateStart(dateValue, 'h');
96
+ }
97
+
98
+ /**
99
+ * 返回天级起始时间
100
+ * @param dateValue - 可以是数值、字符串或 Date 对象
101
+ * @returns 返回天级起始时间,小时、分钟、秒和毫秒部分为 0
102
+ */
103
+ export function dateStartInDay(dateValue: TDateValue) {
104
+ return _dateStart(dateValue, 'D');
105
+ }
106
+
107
+ /**
108
+ * 返回月级起始时间
109
+ * @param dateValue - 可以是数值、字符串或 Date 对象
110
+ * @returns 返回月级起始时间,日期为当月第一天,时间部分为 0
111
+ */
112
+ export function dateStartInMonth(dateValue: TDateValue) {
113
+ return _dateStart(dateValue, 'M');
114
+ }
115
+
116
+ /**
117
+ * 返回年级起始时间
118
+ * @param dateValue - 可以是数值、字符串或 Date 对象
119
+ * @returns 返回年级起始时间,月份为 1 月,日期为 1 日,时间部分为 0
120
+ */
121
+ export function dateStartInYear(dateValue: TDateValue) {
122
+ return _dateStart(dateValue, 'Y');
123
+ }
124
+
125
+ /**
126
+ * 各时间单位结束时间映射表
127
+ * 包含将日期设置到单位结束时间的函数
128
+ */
129
+ const dateOfEndMap: [_TDateOfSymbol, (date: TDateLike) => unknown][] = [
130
+ ['s', (d) => d.setMilliseconds(999)],
131
+ ['m', (d) => d.setSeconds(59)],
132
+ ['h', (d) => d.setMinutes(59)],
133
+ ['D', (d) => d.setHours(23)],
134
+ [
135
+ 'M',
136
+ (d) => {
137
+ const d2 = dateParse(d);
138
+ d2.setMonth(d.getMonth() + 1);
139
+ d2.setDate(0);
140
+ d.setDate(d2.getDate());
141
+ },
142
+ ],
143
+ [
144
+ 'Y',
145
+ (d) => {
146
+ d.setMonth(11);
147
+ d.setDate(31);
148
+ },
149
+ ],
150
+ ];
151
+
152
+ /**
153
+ * 返回指定时间单位的结束时间
154
+ * @param dateValue - 可以是数值、字符串或 Date 对象
155
+ * @param symbol - 时间单位符号,可选值为 'Y'(年)、'M'(月)、'D'(天)、'h'(小时)、'm'(分钟)、's'(秒),默认为 'D'
156
+ * @returns 返回指定时间单位的结束时间
157
+ * @example
158
+ * ```typescript
159
+ * const date = new Date(2023, 5, 15, 12, 30, 45, 500); // 2023-06-15 12:30:45.500
160
+ *
161
+ * // 返回秒级结束时间
162
+ * dateOfEnd(date, 's'); // 2023-06-15 12:30:45.999
163
+ *
164
+ * // 返回分钟级结束时间
165
+ * dateOfEnd(date, 'm'); // 2023-06-15 12:30:59.999
166
+ *
167
+ * // 返回小时级结束时间
168
+ * dateOfEnd(date, 'h'); // 2023-06-15 12:59:59.999
169
+ *
170
+ * // 返回天级结束时间
171
+ * dateOfEnd(date, 'D'); // 2023-06-15 23:59:59.999
172
+ *
173
+ * // 返回月级结束时间
174
+ * dateOfEnd(date, 'M'); // 2023-06-30 23:59:59.999
175
+ *
176
+ * // 返回年级结束时间
177
+ * dateOfEnd(date, 'Y'); // 2023-12-31 23:59:59.999
178
+ *
179
+ * // 默认返回天级结束时间
180
+ * dateOfEnd(date); // 2023-06-15 23:59:59.999
181
+ * ```
182
+ */
183
+ function _dateEnd(dateValue: TDateValue, symbol: _TDateOfSymbol = 'D') {
184
+ const date = dateParse(dateValue);
185
+
186
+ for (const [sym, fn] of dateOfEndMap) {
187
+ fn(date);
188
+ if (symbol === sym) break;
189
+ }
190
+
191
+ return date;
192
+ }
193
+
194
+ /**
195
+ * 返回秒级结束时间
196
+ * @param dateValue - 可以是数值、字符串或 Date 对象
197
+ * @returns 返回秒级结束时间,毫秒部分为 999
198
+ */
199
+ export function dateEndInSecond(dateValue: TDateValue) {
200
+ return _dateEnd(dateValue, 's');
201
+ }
202
+
203
+ /**
204
+ * 返回分钟级结束时间
205
+ * @param dateValue - 可以是数值、字符串或 Date 对象
206
+ * @returns 返回分钟级结束时间,秒为 59,毫秒为 999
207
+ */
208
+ export function dateEndInMinute(dateValue: TDateValue) {
209
+ return _dateEnd(dateValue, 'm');
210
+ }
211
+
212
+ /**
213
+ * 返回小时级结束时间
214
+ * @param dateValue - 可以是数值、字符串或 Date 对象
215
+ * @returns 返回小时级结束时间,分钟为 59,秒为 59,毫秒为 999
216
+ */
217
+ export function dateEndInHour(dateValue: TDateValue) {
218
+ return _dateEnd(dateValue, 'h');
219
+ }
220
+
221
+ /**
222
+ * 返回天级结束时间
223
+ * @param dateValue - 可以是数值、字符串或 Date 对象
224
+ * @returns 返回天级结束时间,小时为 23,分钟为 59,秒为 59,毫秒为 999
225
+ */
226
+ export function dateEndInDay(dateValue: TDateValue) {
227
+ return _dateEnd(dateValue, 'D');
228
+ }
229
+
230
+ /**
231
+ * 返回月级结束时间
232
+ * @param dateValue - 可以是数值、字符串或 Date 对象
233
+ * @returns 返回月级结束时间,日期为当月最后一天,时间为 23:59:59.999
234
+ */
235
+ export function dateEndInMonth(dateValue: TDateValue) {
236
+ return _dateEnd(dateValue, 'M');
237
+ }
238
+
239
+ /**
240
+ * 返回年级结束时间
241
+ * @param dateValue - 可以是数值、字符串或 Date 对象
242
+ * @returns 返回年级结束时间,月份为 12 月,日期为 31 日,时间为 23:59:59.999
243
+ */
244
+ export function dateEndInYear(dateValue: TDateValue) {
245
+ return _dateEnd(dateValue, 'Y');
246
+ }