add date util

This commit is contained in:
Timi
2026-09-15 13:41:33 +08:00
parent 151427a675
commit b661101a4a
8 changed files with 132 additions and 355 deletions
+99
View File
@@ -0,0 +1,99 @@
import { Time } from "timi-web";
/** 日期筛选器支持的预设范围。 */
export type DateFilterPreset =
| "all"
| "today"
| "yesterday"
| "lastWeek"
| "thisMonth"
| "lastMonth"
| "last7"
| "last30";
/** 日期时间范围,文本格式为 YYYY-MM-DD HH:mm。 */
export type DateTimeRange = [string, string];
/**
* 根据预设筛选类型生成日期时间范围。
*
* `last7` 和 `last30` 为包含今天在内的最近 7 天和 30 天。
*/
export function buildPresetDateRange(type: DateFilterPreset, now = new Date()): DateTimeRange {
if (type === "all") {
return ["", ""];
}
if (type === "lastWeek") {
const current = getDateStart(now);
const day = current.getDay() || 7;
const thisWeekMonday = addDays(current, 1 - day);
const lastWeekMonday = addDays(thisWeekMonday, -7);
const lastWeekSunday = addDays(thisWeekMonday, -1);
return buildDayRange(lastWeekMonday, lastWeekSunday);
}
if (type === "thisMonth") {
const current = new Date(now);
const begin = new Date(current.getFullYear(), current.getMonth(), 1);
return buildDayRange(begin, current);
}
if (type === "lastMonth") {
const current = new Date(now);
const begin = new Date(current.getFullYear(), current.getMonth() - 1, 1);
const end = new Date(current.getFullYear(), current.getMonth(), 0);
return buildDayRange(begin, end);
}
if (type === "last7" || type === "last30") {
const end = new Date(now);
end.setHours(23, 59, 0, 0);
const begin = new Date(end);
begin.setDate(begin.getDate() - (type === "last7" ? 6 : 29));
begin.setHours(0, 0, 0, 0);
return [Time.formatDateTime(begin), Time.formatDateTime(end)];
}
const date = getDateStart(now);
date.setDate(date.getDate() - (type === "today" ? 0 : 1));
return buildDayRange(date, date);
}
/** 将路由或组件输入转换为合法的日期筛选类型。 */
export function parseDateFilterType<T extends string>(
value: unknown,
options: readonly { value: T }[],
fallback: T
): T {
const text = Array.isArray(value) ? String(value[0] || "") : String(value || "");
return options.some(item => item.value === text) ? text as T : fallback;
}
/** 将日期时间文本解析为本地时间。空开始时间和空结束时间分别回退到 Unix 起点和当前时间。 */
export function parseDateTime(value: string, isEnd: boolean): Date {
if (!value) {
return isEnd ? new Date() : new Date(0);
}
const [dateText, timeText = isEnd ? "23:59" : "00:00"] = value.split(" ");
const [year, month, day] = dateText.split("-").map(Number);
const [hour, minute] = timeText.split(":").map(Number);
return new Date(year, month - 1, day, hour || 0, minute || 0, isEnd ? 59 : 0, 0);
}
function buildDayRange(begin: Date, end: Date): DateTimeRange {
return [`${Time.formatDate(begin)} 00:00`, `${Time.formatDate(end)} 23:59`];
}
function getDateStart(date: Date): Date {
const value = new Date(date);
value.setHours(0, 0, 0, 0);
return value;
}
function addDays(date: Date, days: number): Date {
const value = new Date(date);
value.setDate(value.getDate() + days);
return value;
}