345 lines
9.7 KiB
TypeScript
345 lines
9.7 KiB
TypeScript
import dayjs from "dayjs";
|
||
|
||
/**
|
||
* 安全地将字符串转换为 Date 对象,兼容 iOS
|
||
* iOS 不支持 "yyyy-MM-dd HH:mm:ss" 格式,需要转换为 "yyyy-MM-ddTHH:mm:ss" 或 "yyyy/MM/dd HH:mm:ss"
|
||
* @param dateStr 日期字符串
|
||
* @returns Date 对象
|
||
*/
|
||
const parseDate = (dateStr: string): Date => {
|
||
if (!dateStr) return new Date();
|
||
|
||
// 将 "yyyy-MM-dd HH:mm:ss" 格式转换为 "yyyy-MM-ddTHH:mm:ss" (ISO 8601)
|
||
// 替换第一个空格为 T
|
||
const isoStr = dateStr.replace(/^(\d{4}-\d{2}-\d{2})\s(\d{2}:\d{2}(?::\d{2})?)$/, '$1T$2');
|
||
|
||
return new Date(isoStr);
|
||
};
|
||
|
||
/**
|
||
* 获取下一个整点时间
|
||
* @returns 格式为 YYYY-MM-DD HH:mm 的字符串
|
||
*/
|
||
export const getNextHourTime = (): string => {
|
||
const now = dayjs();
|
||
const nextHour = now.add(1, "hour").startOf("hour");
|
||
return nextHour.format("YYYY-MM-DD HH:mm");
|
||
};
|
||
|
||
/**
|
||
* 根据开始时间计算结束时间(2小时后)
|
||
* @param startTime 开始时间,格式为 YYYY-MM-DD HH:mm
|
||
* @returns 格式为 YYYY-MM-DD HH:mm 的字符串
|
||
*/
|
||
export const getEndTime = (startTime: string): string => {
|
||
const startDateTime = dayjs(startTime);
|
||
const endDateTime = startDateTime.add(2, "hour");
|
||
return endDateTime.format("YYYY-MM-DD HH:mm");
|
||
};
|
||
|
||
export const getDateStr = (date: Date): string => {
|
||
return dayjs(date).format("YYYY-MM-DD HH:mm");
|
||
};
|
||
|
||
export const getDate = (date: string): string => {
|
||
return dayjs(date).format("YYYY年MM月DD日");
|
||
};
|
||
|
||
export const getDay = (date?: string | Date): string => {
|
||
if (!date) {
|
||
return dayjs().format("YYYY-MM-DD");
|
||
}
|
||
return dayjs(date).format("YYYY-MM-DD");
|
||
};
|
||
|
||
export const getMonth = (date?: string | Date): string => {
|
||
if (!date) {
|
||
return dayjs().format("MM月 YYYY");
|
||
}
|
||
return dayjs(date).format("MM月 YYYY");
|
||
};
|
||
|
||
export const getWeekend = (date?: string | Date): [Date, Date] => {
|
||
const today = dayjs(date);
|
||
const currentDayOfWeek = today.day();
|
||
console.log("currentDayOfWeek", currentDayOfWeek);
|
||
const saturdayOffset = 6 - currentDayOfWeek;
|
||
const sundayOffset = 7 - currentDayOfWeek;
|
||
const sat = today.add(saturdayOffset, "day");
|
||
const sun = today.add(sundayOffset, "day");
|
||
return [sat.toDate(), sun.toDate()];
|
||
};
|
||
|
||
export const getWeekendOfCurrentWeek = (days = 7): Date[] => {
|
||
const dayList: Date[] = [];
|
||
for (let i = 0; i < days; i++) {
|
||
const day = dayjs().add(i, "day").toDate();
|
||
dayList.push(day);
|
||
}
|
||
return dayList;
|
||
};
|
||
|
||
export const getTime = (time: string): string => {
|
||
const timeObj = dayjs(time);
|
||
const hour = timeObj.hour();
|
||
const minute = timeObj.minute();
|
||
|
||
// 判断是上午还是下午
|
||
const period = hour <= 12 ? "AM" : "PM";
|
||
|
||
// 转换为12小时制
|
||
const hour12 = hour === 0 ? 0 : hour > 12 ? hour - 12 : hour;
|
||
|
||
// 格式化分钟,保证两位数
|
||
const minuteStr = minute.toString().padStart(2, "0");
|
||
|
||
return `${hour12}:${minuteStr} ${period}`;
|
||
};
|
||
|
||
/**
|
||
* 格式化时间显示(相对时间)
|
||
* @param timeStr 时间字符串
|
||
* @returns 格式化后的时间字符串
|
||
*/
|
||
export const formatRelativeTime = (timeStr: string): string => {
|
||
if (!timeStr) return "";
|
||
|
||
const date = parseDate(timeStr);
|
||
const now = new Date();
|
||
|
||
// 获取日期部分(年-月-日),忽略时间
|
||
const getDateString = (d: Date) => {
|
||
const year = d.getFullYear();
|
||
const month = d.getMonth() + 1;
|
||
const day = d.getDate();
|
||
return `${year}-${month.toString().padStart(2, "0")}-${day
|
||
.toString()
|
||
.padStart(2, "0")}`;
|
||
};
|
||
|
||
const dateStr = getDateString(date);
|
||
const nowStr = getDateString(now);
|
||
|
||
// 计算日期差
|
||
const dateObj = new Date(dateStr);
|
||
const nowObj = new Date(nowStr);
|
||
const diffTime = nowObj.getTime() - dateObj.getTime();
|
||
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
||
|
||
if (diffDays === 0) {
|
||
// 今天
|
||
const hours = date.getHours();
|
||
const minutes = date.getMinutes();
|
||
return `今天 ${hours.toString().padStart(2, "0")}:${minutes
|
||
.toString()
|
||
.padStart(2, "0")}`;
|
||
} else if (diffDays === 1) {
|
||
// 昨天
|
||
const hours = date.getHours();
|
||
const minutes = date.getMinutes();
|
||
return `昨天 ${hours.toString().padStart(2, "0")}:${minutes
|
||
.toString()
|
||
.padStart(2, "0")}`;
|
||
} else if (diffDays < 7) {
|
||
// 一周内显示天数
|
||
return `${diffDays}天前`;
|
||
} else {
|
||
// 超过一周显示完整日期
|
||
const year = date.getFullYear();
|
||
const month = date.getMonth() + 1;
|
||
const day = date.getDate();
|
||
const hours = date.getHours();
|
||
const minutes = date.getMinutes();
|
||
return `${year}-${month.toString().padStart(2, "0")}-${day
|
||
.toString()
|
||
.padStart(2, "0")} ${hours.toString().padStart(2, "0")}:${minutes
|
||
.toString()
|
||
.padStart(2, "0")}`;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 格式化时间显示(简短相对时间)
|
||
* @param timeStr 时间字符串
|
||
* @returns 格式化后的时间字符串
|
||
*/
|
||
export const formatShortRelativeTime = (timeStr: string): string => {
|
||
if (!timeStr) return "";
|
||
|
||
const date = parseDate(timeStr);
|
||
const now = new Date();
|
||
|
||
// 获取日期部分(年-月-日),忽略时间
|
||
const getDateString = (d: Date) => {
|
||
const year = d.getFullYear();
|
||
const month = d.getMonth() + 1;
|
||
const day = d.getDate();
|
||
return `${year}-${month.toString().padStart(2, "0")}-${day
|
||
.toString()
|
||
.padStart(2, "0")}`;
|
||
};
|
||
|
||
const dateStr = getDateString(date);
|
||
const nowStr = getDateString(now);
|
||
|
||
// 计算日期差
|
||
const dateObj = new Date(dateStr);
|
||
const nowObj = new Date(nowStr);
|
||
const diffTime = nowObj.getTime() - dateObj.getTime();
|
||
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
||
|
||
// 如果是今天,显示具体时间
|
||
if (diffDays === 0) {
|
||
const diff = now.getTime() - date.getTime();
|
||
const minutes = Math.floor(diff / (1000 * 60));
|
||
const hours = Math.floor(diff / (1000 * 60 * 60));
|
||
|
||
if (minutes < 1) {
|
||
return "刚刚";
|
||
} else if (minutes < 60) {
|
||
return `${minutes}分钟前`;
|
||
} else {
|
||
return `${hours}小时前`;
|
||
}
|
||
} else if (diffDays === 1) {
|
||
return "1天前";
|
||
} else if (diffDays < 7) {
|
||
return `${diffDays}天前`;
|
||
} else {
|
||
const month = date.getMonth() + 1;
|
||
const day = date.getDate();
|
||
return `${month}月${day}日`;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 格式化球局时间显示(例如:明天(周五)下午5点)
|
||
* @param timeStr 时间字符串
|
||
* @returns 格式化后的时间字符串
|
||
*/
|
||
export const formatGameTime = (timeStr: string): string => {
|
||
if (!timeStr) return "";
|
||
|
||
const date = parseDate(timeStr);
|
||
const now = new Date();
|
||
|
||
// 获取星期几
|
||
const weekDays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
|
||
const weekDay = weekDays[date.getDay()];
|
||
|
||
// 获取小时和分钟
|
||
const hours = date.getHours();
|
||
const minutes = date.getMinutes();
|
||
|
||
// 判断上午/下午/晚上
|
||
let period = "";
|
||
let displayHour = hours;
|
||
|
||
if (hours >= 0 && hours < 6) {
|
||
period = "凌晨";
|
||
} else if (hours >= 6 && hours < 12) {
|
||
period = "上午";
|
||
} else if (hours >= 12 && hours < 18) {
|
||
period = "下午";
|
||
displayHour = hours === 12 ? 12 : hours - 12;
|
||
} else {
|
||
period = "晚上";
|
||
displayHour = hours - 12;
|
||
}
|
||
|
||
// 格式化时间部分
|
||
const timeStr2 =
|
||
minutes === 0 ? `${displayHour}点` : `${displayHour}点${minutes}分`;
|
||
|
||
// 获取日期部分(年-月-日),忽略时间
|
||
const getDateString = (d: Date) => {
|
||
const year = d.getFullYear();
|
||
const month = d.getMonth() + 1;
|
||
const day = d.getDate();
|
||
return `${year}-${month.toString().padStart(2, "0")}-${day
|
||
.toString()
|
||
.padStart(2, "0")}`;
|
||
};
|
||
|
||
const dateStr = getDateString(date);
|
||
const nowStr = getDateString(now);
|
||
|
||
// 计算日期差
|
||
const dateObj = new Date(dateStr);
|
||
const nowObj = new Date(nowStr);
|
||
const diffTime = dateObj.getTime() - nowObj.getTime();
|
||
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
||
|
||
// 根据日期差返回不同格式
|
||
if (diffDays === 0) {
|
||
// 今天
|
||
return `今天(${weekDay})${period}${timeStr2}`;
|
||
} else if (diffDays === 1) {
|
||
// 明天
|
||
return `明天(${weekDay})${period}${timeStr2}`;
|
||
} else if (diffDays === 2) {
|
||
// 后天
|
||
return `后天(${weekDay})${period}${timeStr2}`;
|
||
} else if (diffDays > 2 && diffDays <= 7) {
|
||
// 一周内
|
||
return `${weekDay}${period}${timeStr2}`;
|
||
} else {
|
||
// 超过一周,显示具体日期
|
||
const month = date.getMonth() + 1;
|
||
const day = date.getDate();
|
||
return `${month}月${day}日(${weekDay})${period}${timeStr2}`;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 计算时长(结束时间 - 开始时间)
|
||
* @param startTime 开始时间字符串
|
||
* @param endTime 结束时间字符串
|
||
* @returns 格式化后的时长字符串(如:2小时、1.5小时、30分钟)
|
||
*/
|
||
export const calculateDuration = (
|
||
startTime: string,
|
||
endTime: string
|
||
): string => {
|
||
if (!startTime || !endTime) return "";
|
||
|
||
const start = parseDate(startTime);
|
||
const end = parseDate(endTime);
|
||
|
||
// 计算时间差(毫秒)
|
||
const diffMs = end.getTime() - start.getTime();
|
||
|
||
// 转换为分钟
|
||
const diffMinutes = Math.floor(diffMs / (1000 * 60));
|
||
|
||
// 转换为小时
|
||
const hours = Math.floor(diffMinutes / 60);
|
||
const minutes = diffMinutes % 60;
|
||
|
||
// 格式化输出
|
||
if (hours > 0 && minutes > 0) {
|
||
return `${hours}.5小时`;
|
||
} else if (hours > 0) {
|
||
return `${hours}小时`;
|
||
} else if (minutes > 0) {
|
||
return `${minutes}分钟`;
|
||
} else {
|
||
return "";
|
||
}
|
||
};
|
||
|
||
export const getOneMonth = (): Date[] => {
|
||
const dates: Date[] = [];
|
||
const currentDate = dayjs();
|
||
const nextMonth = dayjs().add(1, "month");
|
||
|
||
// 从当前日期开始,遍历到下个月的同一天
|
||
let date = currentDate;
|
||
while (date.isBefore(nextMonth) || date.isSame(nextMonth, "day")) {
|
||
dates.push(date.toDate());
|
||
date = date.add(1, "day");
|
||
}
|
||
|
||
return dates;
|
||
};
|