获取当前时间所对应的周一

1
2
3
4
5
6
7
8
9
dayjs 和 moment 能够正确处理跨年跨月以及夏令时,符合iso标准

utc时间从开始时间的 00:00:00 开始 ,结束时间从 23:59:59结束。

在比较时间戳大小的时候要注意:

new Date('2025-09-20') 默认会被转为utc时间,

new Date('2025-09-20')的时间戳和new Date() (即使现在是2025-09-20,这种写法也和utc对不上)的时间戳会不一致

原生

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function getUTCWeekRange() {
const now = new Date();
// 基于 UTC 的星期计算(0=周日,1=周一...6=周六)
const utcDay = now.getUTCDay();

// 计算到 UTC 周一的天数差
const mondayDiff = utcDay === 0 ? 6 : utcDay - 1;
// 计算到 UTC 周日的天数差(如果是周日则无需调整)
const sundayDiff = utcDay === 0 ? 0 : 7 - utcDay;

// 构建 UTC 周一
const utcMonday = new Date(Date.UTC(
now.getUTCFullYear(),
now.getUTCMonth(),
now.getUTCDate() - mondayDiff
));

// 构建 UTC 周日
const utcSunday = new Date(Date.UTC(
now.getUTCFullYear(),
now.getUTCMonth(),
now.getUTCDate() + sundayDiff
));

return { utcMonday, utcSunday };
}

dayjs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import isoWeek from 'dayjs/plugin/isoWeek';
import timezone from 'dayjs/plugin/timezone';

dayjs.extend(utc);
dayjs.extend(isoWeek);
dayjs.extend(timezone);

/**
* 获取UTC标准周范围(周一00:00:00至周日23:59:59.999)
* @param {string|Date} [date] - 可选的日期输入,默认当前时间
* @returns {{
* start: Date,
* end: Date,
* isoWeekNumber: number,
* isoYear: number,
* isoRange: string
* }}
*/
function getEnhancedUTCWeekRange(date = new Date()) {
const base = dayjs(date).utc();

// 计算ISO标准周起始日(周一)
const start = base.startOf('isoWeek');
// 计算周结束日(周日)并设置到当日最后一毫秒
const end = start.clone().endOf('day').add(6, 'day');

return {
start: start.toDate(),
end: end.toDate(),
isoWeekNumber: base.isoWeek(),
isoYear: base.isoWeekYear(),
isoRange: `${start.format('YYYY-MM-DDTHH:mm:ss.SSS[Z]')}/${end.format('YYYY-MM-DDTHH:mm:ss.SSS[Z]')}`,
days: Array.from({ length: 7 }, (_, i) =>
start.add(i, 'day').format('YYYY-MM-DD')
)
};
}

moment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

function getEnhancedUTCWeekRange(date = new Date()) {
const base = moment(date).utc();
// 计算ISO标准周起始日(周一)
const start = base.clone().startOf('isoWeek');
// 计算周结束日(周日)并设置到当日最后一毫秒
const end = start.clone().endOf('day').add(6, 'day');

return {
start: start.toDate(),
end: end.toDate(),
isoWeekNumber: base.isoWeek(),
isoYear: base.isoWeekYear(),
isoRange: `${start.format('YYYY-MM-DDTHH:mm:ss.SSS[Z]')}/${end.format('YYYY-MM-DDTHH:mm:ss.SSS[Z]')}`,
days: Array.from({ length: 7 }, (_, i) =>
start.clone().add(i, 'days').format('YYYY-MM-DD')
)
};
}

点击事件、onChange事件防抖

1
2
3
4
5
6
7
我们都知道 ,

不能直接对高频的onChange事件加上防抖,

直接加上会使输入卡顿。

因此 ,我们可以对onChange之后要做的事进行防抖。
1
2
3
4
5
6
7
8
9
// setTab是外界传入 间接的对引发高频请求的变量防抖

const debounced = debounce((tab: string) => {
setTab(tab)
}, 800)

<Input onChange={(tab) => {
debounced(tab)
}}/>
需要保持一个防抖实例的情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

// 如果在onChange的时候会引起组件重渲染,需要保持一个防抖实例

// 以下两种写法皆可

const debounced = useCallback(debounce((tab: string) => {
setTab(tab)
}, 800), [])

const debounceRef = useRef(debounce((tab: string) => {
setTab(tab)
}, 800))

<Input onChange={(tab) => {
debounced(tab)
debounceRef(tab)
}}/>